排序小结1

来源:互联网 发布:linux nano 编辑:程序博客网 时间:2024/06/11 12:16
 

1.常用各种排序(限于比较排序)

(1) Insertion:平均时间 O(n^2);最坏时间 O(n^2);空间 O(1);稳定

每次将一个待排的记录插入到前面的已经排好的队列中的适当位置。

$ Insertion-Sort(A)for j=2 to length[A] do    key <- A[j]    i <- j-1    while i>0 && A[i]>key  do        A[i+1] <- A[i]        i--    A[i+1] <- key

(2) Merge:平均时间 O(nlgn);最坏时间 O(nlgn);空间 O(n);稳定

$ Merge(A,p,q,r)for i=1 to q-p+1 do L[i] <- A[p+i-1]for j=1 to r-q do R[j] <- A[q+j]L[q-p+2] <- R[r-q+1] <- inftyi <- j <- 1for k=p to r do    L[i]<=R[j]?A[k]<-L[i++]:A[k]<-R[j++]
$ Merge-Sort(A,p,r)if p<r  then    q <- (p+r)/2    Merge-Sort(A,p,q)    Merge-Sort(A,q+1,r)    Merge(A,p,q,r)

(3)Heap:平均时间 O(nlgn);最坏时间 O(nlgn);空间 O(1);不稳定

$ Max-Heapify(A,i)if Left[i]<=heap-size[A] && A[Left[i]]>A[i]    then largest <- Left[i]    else largest <- iif Right[i]<=heap-size[A] && A[Right[i]]>A[largest]    then largest <- Right[i]if largest 不等于 i  then    exchange A[i] <-> A[largest]    Max-Heapify(A,largest)
$ Build-Max-Heap(A)heap-size[A] <- length[A]for i=length[A]/2 to 1    Max-Heapify(A,i)
$ Heap-Sort(A)Build-Max-Heap(A)for i=length[A] to 2    exchange A[1] <-> A[i]    heap-size[A]--    Max-Heapify(A,1)

衍生的优先级队列算法,下面只介绍最大优先级队列

Insert(S,x):把元素x插入集合S.这一操作可写为S<—SU{x}

$ Heap-Max-Insert(A,key)heap-size[A] <- heap-size[A]+1A[heap-size[A]] <- -infinityHeap-Increase-Key(A,heap-size[A],key)

Maximum(S):返回S中具有最大关键字的元素

$ Heap-Maximum(A)return A[1]

Extract-Max(S):去掉并返回S中的具有最大关键字的元素

$ Heap-Extract-Max(A)if heap-size[A]<1 then        error "heap underflow"max <- A[1]A[1] <- A[heap-size[A]]heap-size[A] <- heap-size[A]-1Max-Heapify(A,1)return max

Increase-Key(S,x,k):将元素x的关键字的值增加到k,这里k值不能小于x的原关键字的值

$ Heap-Increase-Key(A,i,key)if key<A[i]  then errorA[i] <- keywhile i>1 && A[Parent(i)]<A[i]  do        exchange A[i] <-> A[Parent(i)]        i <- Parent(i)

(4)Quick:平均时间 O(nlgn);最坏时间 O(n^2);空间 O(lgn);不稳定

通过一趟排序将待排的记录分割成独立的两部分,其中一部分记录的关键字均比另一个部分的关键字小,然后再分别对这两个部分记录继续进行排序,以达到整个序列有效。

快排有随机版本,也就是说在partition的时候是随机选取分点值的,这样的话平均效果会好一点,但操作相对复杂而且没有质的飞跃。

clrs的Ex7.2-2表明它对排序对象有多个相同值时候的效果是比较差的,有一种快排的三路变体可以解决这中边界数据。

$ Partition(A,p,r)x <- A[r]i <- p-1for j=p to r-1  do    if A[j]<=x then        i++        exchange A[i] <-> A[j]exchange A[i+1] <-> A[r]return i+1
$ Quick-Sort(A,p,r)if p<r then    q <- Partition(A,p,r)    Quick-Sort(A,p,q-1)    Quick-Sort(A,q+1,r)

快排的三路变体

PARTITION(A,p,r,int& q1, int& q2)  //用指针或者引用返回两个参数1 x = A[r]2 i = p-13 for j = p to r - 14 if A[j] <= x5 i = i + 16 exchange A[i] with A[j]7 exchange A[i + 1] with A[r]8 k= i+19 for j = p to i 10 if A[j] = x11k = k - 112 exchange A[j] with A[k]13 q1 = k,q2=i+1

2.总结

n比较小的时候,适合插入排序和选择排序

基本有序的时候,适合直接插入排序和冒泡排序

n很大但是关键字的位数较少时,适合 链式基数排序

n很大的时候,适合 快速排序堆排序归并排序

无序的时候,适合 快速排序