回 帖 发 新 帖 刷新版面

主题:[原创] 排序方法的总结与讨论

DECLARE SUB show (m!())                    '输出排序后的结果
DECLARE SUB CountingSort ()       '计数排序
DECLARE FUNCTION QSSplit! (p!, r!)          '快速排序的关键过程
DECLARE SUB SelectSort ()            '选择排序
DECLARE SUB init ()               '初始化
DECLARE SUB refresh ()          '数组重新赋值以进行下一个排序
DECLARE SUB BubbleSort ()         '冒泡排序
DECLARE SUB InsertSort ()         '插入排序
DECLARE SUB QuickSort (p!, r!)       '快速排序的主过程
CLS
CONST maxn = 15000             '最多有15000个数,考虑到qb的数组也就能开那么大。
CONST maxm = 10000               '数组元素的取值范围是1-10000
DIM SHARED n, a(1 TO maxn), b(0 TO maxn)         'n是元素个数;a存随机生成的、待排序的数;
CALL init          '初始化

REM Simple Sort,简单排序,时间复杂度均为O(n^2)
CALL BubbleSort     
CALL InsertSort
CALL SelectSort

REM Difficult Sort,复杂的。快速排序时间复杂度是O(nlogn),是基于比较的排序法中平均最快的了,强烈推荐
CALL refresh       '因为快速用到了递归,所以只好在子程序外面初始化数组
st# = TIMER          '用来记时
CALL QuickSort(1, n)        '调用快速排序
PRINT "QuickSort:"; TIMER - st#; "s"

CALL CountingSort      '计数排序,时间复杂度是O(m+n),这个超强啊~线性的复杂度~强烈推荐。

SUB BubbleSort
CALL refresh
st# = TIMER
FOR i = 1 TO n - 1
FOR j = i + 1 TO n
  IF b(i) > b(j) THEN SWAP b(i), b(j)
NEXT j
NEXT i
PRINT "BubbleSort:"; TIMER - st#; "s"
'CALL show(b())
END SUB

SUB CountingSort
CALL refresh
DIM c(maxm)
st# = TIMER

FOR i = 1 TO n: c(a(i)) = c(a(i)) + 1: NEXT
FOR i = 2 TO maxm: c(i) = c(i) + c(i - 1): NEXT
FOR i = n TO 1 STEP -1
  b(c(a(i))) = a(i)
  c(a(i)) = c(a(i)) - 1
NEXT i

PRINT "CountingSort:"; TIMER - st#; "s"
'CALL show(b())
END SUB

SUB init
RANDOMIZE TIMER
INPUT "How many numbers:", n
FOR i = 1 TO n
  a(i) = INT(RND * maxm + 1)
'  PRINT a(i);
NEXT
'PRINT
'PRINT
END SUB

SUB InsertSort
CALL refresh
st# = TIMER
FOR i = 2 TO n
  j = i
  WHILE b(j) < b(j - 1)
    SWAP b(j), b(j - 1)
    j = j - 1
  WEND
NEXT i
PRINT "InsertSort:"; TIMER - st#; "s"
'CALL show(b())
END SUB

FUNCTION QSSplit (j, k)
t = INT(RND * (k - j + 1)) + j
x = b(t)
i = j - 1: j = k + 1
WHILE 1
  DO: j = j - 1: LOOP UNTIL b(j) >= x
  DO: i = i + 1: LOOP UNTIL b(i) <= x
  IF i < j THEN
    SWAP b(i), b(j)
  ELSE
    QSSplit = j
    EXIT FUNCTION
  END IF
WEND
END FUNCTION

SUB QuickSort (p, r)
IF p < r THEN
  q = QSSplit((p), (r))
  CALL QuickSort((p), (q))
  CALL QuickSort((q + 1), (r))
END IF
END SUB

SUB refresh
FOR i = 1 TO n
b(i) = a(i)
NEXT
END SUB

SUB SelectSort
CALL refresh
st# = TIMER
FOR i = 1 TO n - 1
  ln = i
  l = b(i)
  FOR j = i + 1 TO n
    IF b(j) < l THEN
      l = b(j)
      ln = j
    END IF
  NEXT j
  SWAP b(i), b(ln)
NEXT i
PRINT "SelectSort:"; TIMER - st#; "s"
'CALL show(b())
END SUB

SUB show (m())
FOR i = 1 TO n
  PRINT m(i);
NEXT i
END SUB

大家运行一下,输入的n要在1-10000之内,不然冒泡之类的简单排序能等死你。
数据是随机生成的。

可以看到,复杂排序(快速和计数)要比简单排序快N倍,但同样,它们费空间。
快速排序用栈空间实现递归,而计数排序要求元素的取值范围已知且不是很大。

其实,复杂排序还有很多,例如归并排序,堆排序,桶排序(线性),基数排序(线性),都是很强的,只不过我都没有掌握,惭愧啊。

大家看看,有问题可以问。程序不懂的也可以提出。

我就先擅自给自己加精了,并临时置顶几天。如果另外两位认为有问题,可以取消。

回复列表 (共22个回复)

沙发

呵呵,先来支持一下!

板凳

[em18]
虽然我很想把它看懂,但是我们的能力有限,而且我面对是单招考试,我想我是没有时间去搞懂了,至少现在是不可能的,等单招考过还可能吧,毕竟我们考试没有那么深吗

3 楼

楼主如果你有一个更详细的说明,
我想能看懂的人就会多一些
重新去修改一下!
OK?!
越是好贴越是要做好!

4 楼

暂时还看不懂,不过支持.

5 楼

看不太懂耶~~!![em12]

6 楼

支持3楼的意见,请楼主完善它。
另外,请教楼主一个问题:能否在QB中实现二叉树排序?

7 楼

当然可以。
因为二叉树可以用数组实现,而不一定非要是链表

8 楼

支持

9 楼

楼主发的好长啊
要看很长时间不容易给人盗版
我西画-v-

10 楼

在下能力有限,楼主能否解释一下,谢了!!

我来回复

您尚未登录,请登录后再回复。点此登录或注册