数据结构——排序

参考“浙江大学 数据结构 陈越等”MOOC课程,《数据结构与算法分析——C语言描述》

前提 void X_sort(ElementType A[],int N)

为了简单,只讨论:
从小到大的整数排序;
N是正整数;
基于比较的排序(>=<有定义);
内部排序(所有数据可一次性导入内存空间,所有排序在内存空间一次性完成);
稳定性(任意两个相等的数据,排序前后的相对位置不变)。

没有一种排序在任何情况下都表现最好。

1、冒泡排序

最好情况:顺序T=O(N),最坏情况:逆序T=O(N2)。

简单,用于数组和单向链表,稳定。

void Bubble_Sort(ElementType A[],int N){
  for(P=N-1;P>=0;P--){
    flag=0; 
    for(i=0;i<P;i++){ // 一趟冒泡 
      if(A[i]>A[i+1]){
        Swap(A[i],A[i+1]);
        flag=1; // 标识发生了交换 
      }
    }
    if(flag==0) break; // 全程无交换 
  }
}

2、插入排序

最好情况:顺序T=O(N),最坏情况:逆序T=O(N2)。T(N,I)=O(N+I),如果序列基本有序,则插入排序简单且高效。

简单,不用交换,用于数组和单向链表,稳定。

void Insertion_Sort(ElementType A[],int N){
  for(P=1;P<N;P++){
    Tmp=A[P]; // 摸下一张牌 
    for(i=P;i>0&&A[i-1]>Tmp;i--){
      A[i]=A[i-1]; // 移出空位 
    }
    A[i]=Tmp; // 新牌落位 
  }
}

对于下标i<j,如果A[i]>A[j],则称(i,j)是一对逆序对。交换2个相邻元素正好消去1个逆序对。任意N个不同元素组成的序列平均具有N(N-1)/4个逆序对。任何仅以交换相邻元素来排序的算法,其平均时间复杂度为Ω(N2)。

要提高算法效率,必须每次消去不止1个逆序对,通过交换相隔较远的2个元素。

3、希尔排序

定义增量序列DM>DM-1>...>D1>1,对每个Dk进行“Dk-间隔”排序。注意“Dk-间隔”有序的序列在执行“Dk-1-间隔”排序后,仍然是“Dk-间隔”有序的。

原始希尔排序DM=[N/2],Dk=[Dk+1/2],即每次Dk减半。最坏情况:T=Θ(N2),增量元素不互质,小增量可能根本不起作用。如8,4,2,每一趟均没有元素变动,最后做1间隔插入排序。

void Shell_Sort(ElementType A[],int N){
  for(D=N/2;D>0;D/=2){ // 希尔增量序列
    for(P=D;P<N;P++){ // 插入排序 
      Tmp=A[P];
      for(i=P;i>=D&&A[i-D]>Tmp;i-=D){
        A[i]=A[i-D];
      }
      A[i]=Tmp;
    }
  } 
}

Hibbard增量序列,Dk=2k-1,相邻元素互质。最坏情况:T=Θ(N3/2)。猜想:Tavg=O(N5/4)。

Sedgewick增量序列{1,5,19,41,109,...}9*4i-9*2i+1或4i-3*2i+1。猜想:Tworst=O(N4/3),Tavg=O(N7/6)。元素数量是万数量级以上,效果较好。不稳定。

void Shell_Sort(ElementType A[],int N){
  int Sedgewick[]={929,505,209,109,41,19,5,1,0}; // 只列出少部分增量 
  for(Si=0;Sedgewick[Si]>=N;Si++); // 初始的增量Sedgewick[Si]不能超过待排序列长度
  for(D=Sedgewick[Si];D>0;D=Sedgewick[++Si]){
    for(P=D;P<N;P++){ // 插入排序 
      Tmp=A[P];
      for(i=P;i>=D&&A[i-D]>Tmp;i-=D){
        A[i]=A[i-D];
      }
      A[i]=Tmp;
    }
  } 
}

4、堆排序

选择排序。每次交换可能消掉很多逆序对,最多交换N-1次。

无论如何T=Θ(N2)。如何快速找到最小元?

void Selection_Sort(ElementType A[],int N){
  for(i=0;i<N;i++){
    // 从A[i]到A[N-1]中找到最小元,将最小元的位置赋给MinPosition
    MinPosition=ScanForMin(A,i,N-1); // 包含for循环
    // 将未排序部分的最小元换到有序部分的最后位置
    Swap(A[i],A[MinPosition]);
  }
}

算法1,T(N)=O(NlogN),需要额外O(N)空间,复制元素需要时间。

void Heap_Sort(ElementType A[],int N){
  BuildHeap(A); // O(N),建立堆
  for(i=0;i<N;i++) // O(NlogN),取出最小值存放至新数组 
    TmpA[i]=DeleteMin(A);
  for(i=0;i<N;i++) // O(N),将新数组的数据保存至原数组 
    A[i]=TmpA[i];
}

5、归并排序

 

6、快速排序

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值