(二)排序和顺序统计学

第六章  堆排序
              二叉堆数据结构是一种数组对象。
            堆排序思想:首先建立一个最大堆函数,得到第一个节点是堆的最大值,将第一个节点与最后一个节点互换,将堆的大少减一,循环调用,即得到一个从大到小的序列。
             堆排序代码:

  


                                                                                                w-s 
Max-heapify(A,i)          //子节点和父节点排序                                                 O(lg(n))                   
{ l = left(i) 
  r = right(i) 
      if l <= heap-size[A] && A[l] > A[i] 
              then largest = l else largest = i 
      if r <= heap-size[A] && A[r] > A[largest] 
              then largest = r 
      if largest != i 
              then exchange A[i] <-> A[largest] 
              Max-heapify(A,largest) }
              
Build-max-heap(A) //建立完整的堆 O(n) 
{ 
  heap-size[A] = length[A] 
  for i = (length[A]/2) downto 1 //只需要将堆里面倒数第二排最后一个有子节点的点开始建立最大堆 
    do Max-heapify(A,i) 
} /*堆排序算法*/
Heapsort(A) //对堆进行排序 
{ 
     Build-max-heap(A)                                                                            O(n) 
     for i = length[A] downto 2 
             do exchange A[1] <-> A[i] 
             heap-size[A] = heap-size[A]-1 
             Max-heapify(A,1)                                                                     O(nlg(n))
}

    复杂度: T(n) =  O(nlg(n))

  优先队列(堆排序的一种应用):
/*
优先级队列支持操作:
                   Heap-maxinum(S)
                   Max-heap-Inser(S,x)
                   Heap-Extract-max(S)   去掉并返回S中具有最大关键字的元素
                   Heap-Increase-key(S,x,k)   将元素x的关键字的值增加到k,这里k不能小于x的原关键字 
*/

// 堆里面最大值                                                   w-s
Heap-maximum(A)                                                    O(1)
   return A[1]
   
//插入x到堆里面
Max-heap-inset(A,key)                                              O(lg(n))   
{
  heap-size[A] = heap-size[A]-1
  A[heap-size[A]] = -∞
  Heap-Increase-key(A,heap-size[A],key)    
}

//去掉并返回S中最大关键字的元素
Heap-Extract-max(A)                                                O(lg(n))
{
  if heap-size[A] < 1
    then error"heap underflow"
  max = A[1]
  A[1] = A[heap-size[A]] 
  heap-size[A] = heap-size[A]-1
  Max-heapify(A,1)
  return max                  
}  

//将元素x的关键字加到k中
Heap-Increase-key(A,i,key)                                          O(lg(n))
{
  if key < A[i]
     then error"new key is smaller than current key"
  A[i] = key 
  while i > 1 && A[parent(i)] < A[i]
    do exchange A[i] <-> A[parent(i)]
        i = parent(i)  
                               
} 

第七章 快速排序
          快速排序的思想:分解:将数组划分两个子数组,取得一直在两个数组中间,并且此元素的下表即为数组排到第几位。
                                         解决:通过递归调用快速排序,对数组进行排序。
                                         合并:无需操作了,由分解知道,其实每个数已经排好序了。

//快速排序的解决式                                        w-s             a-s           b-s
Quick-sort(A,p,r)                                       T(n)= T(n-1)+cn  O(nlg(n))    O(nlg(n))
{
  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)
{
   x = A[r]
   i = p-1
   for j = p to r-1
      do if A[j] <= x
         then i = i+1
              exchange A[i] <-> A[j]
   exchange A[i+1] <-> A[r]
   return i+1                           
} 

快速排序的随机化版本

Randomized-partition(A,p,r)
{
   i = random(p,r)//在A中随机抽取一个值i 
   exchange A[r] <-> A[i]
   return partition(A,p,r)                          
}
 
 Random-quicksort(A,p,r)
 {
    if p < r
      then q = randomized-partition(A,p,r)
          Random-quicksort(A,p,q-1)
          Random-quicksort(A,q+1,r)                      
 }

w-s : Ө(n^2)
期望的运行时间:Ө(nlg(n))
stooge 排序:

Stooge-sort(A,i,j)
{
 if A[i] > A[j]
    then exchange A[i] <-> A[j]
 if i +1 >= j 
  then  return 
  k = (j-i+1)/3           //round down 
  stooge-sort(A,i,j-k)    //first two-thirds
  stooge-sort(A,i+k,j)    //last two-thirds
  stooge-sort(A,i,j-k)    //first two-thirds again
}

猜想:复杂度:T(n) = nlog3(n)

     

决策树模型(比较排序)

    计数排序
    思想:创建一个length(A)大小的数组B,和一个辅助数组C,辅助数组用来计数数组里面相同数的个数和位置,然后将辅助数组的书位置,即排好书序的下标赋给数组B的下表,将数组A对应的数赋给B的值。

   

Counting-sort(A,B,k)                              w-s
{
   for i = 0 to k                                 O(n)   
    do C[i] =0 
   for j = 1 to length[A]                         O(n)                             
    do C[A[j]] = C[A[j]] +1
   for i =1 to k                                  O(n)
     do C[i] = C[i] + C[i-1]
   for j = length[A] downto 1                     O(n)
       do B[C[A[j]]] e= A[j]
          C[A[j]] = C[A[j]] -1                        
}
复杂度:T(n) = O(n)

计数排序:
    思想:首先将数进行分类,得出其位数,然后通过低位进行排序,直到最高位排序,最终得出排好的序列

Radix-sort(A,d)
{
   for i = 1 to d 
     do use a stable sort to sort array A on digit i               
}

T(n) = Ө(n)


桶排序
   思想:创建一个length(A) 的数组,并且元素满足 0<= A[i] =< 1,通过十分位,百分位的数作为下标放入桶B里面,十分位相同,可通过创建链表的方式来比较百分位的位置,依次类推。

Bucket-sort(A)                                              w-s
{ 
 n = length[A]
 for i = 1 to n                                             O(n)
     do inset A[i] into list B[nA[i]]
  for i = 0 to n-1                                           O(n)
     do sort list B[i] with insertion sort 
     concatenate the lists B[0] ,B[1].....B[n] together in order   
}

T(n) = O(n)


第九章  中位数和顺序统计学

            最大值和最小值
  以期望线性时间做选择
     如果我们不选最大值或最小值,而是选一个第i小的值。我们可以用一种分治算法——RAMDOMIZED_SELECT,它以快速排序为模型:把数组随机划分为两部分,A[p...q-1]的元素比A[q]小,A[q+1...r]的元素比A[q]大。与快速排序不同,如果i=q,则A[q]就是要找的第i小的元素,返回这个值;如果i < q,则说明第i小的元素在A[p...q-1]里;如果i > q,则说明第i小的元素在A[q+1...r]里。

     

RANDOMIZED_SELECT(A, p, r, i) {  
1    if p == r  
2        return A[p];  
3    q = RANDOMIZED_PARTITION(A, p, r);  
4    k = q-p+1;  
5    if i == k   
6        return A[q];  
7    elseif i < k  
8        return RANDOMIZED_SELECT(A, p, q-1, i);  
9    else return RANDOMIZED_SELECT(A, q+1, r, i-k);  
}  

用代换法解上式,可以得到E(T(n))=O(n)。也就是说在平均情况下,任何顺序统计量(特别是中位数)都可以在线性时间内得到。
  最坏情况线性时间的选择
首先我们需要稍微修改一下PARTITION算法(不是RANDOMIZED_PARTITION),它接收一个数组和一个值x,并把它划分为小于x和大于x的两部分(x为A中某个元素的值):

PARTITION_X(A, p, r, x) {  
1    for i = 1 to n  
2        if A[i] == x {  
3            swap(A[i], A[n-1]);  
4            break;  
5        }  
6    return PARTITION(A, p, r);  
}  

在修改划分算法后,我们通过以下步骤来实现在n个元素的数组中找第i小元素的SELECT:

SELECT(A, p, r, i) {  
// 步骤1、2  
1    count = ceiling(n/5);    
2    for i = 1 to count-1  
3        insertion sort A[(i-1)*5+1...i*5+1];  
4    insertion sort A[(count-1)*5+1...n];  
5    if count ==1  
6        return A[floor(n/2)];  
// 步骤3  
7    create array B;  
9    for i = 1 to count-1  
10       B[i] = A[(i-1)*5+3];  
11   B[count] = A[(count-1)*5 + floor((n - (count-1)*5)/2)];  
12   x = SELECT(B, 1, count, floor(count/2));  
// 步骤4  
13   q = PARTITION_X(A, p, r, i);  
14   k = q-p+1;  
// 步骤5  
15   if i == k  
16       return x;  
17   elseif i < k  
18       return SELECT(A, p, q-1, i);  
19   else  
20       return SELECT(A, q+1, r, i-k);  
}  

SELECT算法在最坏情况下运行时间为O(n)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值