数据结构——排序 笔记合集(C语言)完结

本文详述了排序算法的各种类型,包括插入排序、希尔排序、冒泡排序、快速排序、堆排序、归并排序和基数排序等。深入探讨了排序算法的稳定性、效率分析和优化策略,特别关注了外部排序中的多路平衡归并和败者树的应用。文章适合对数据结构和算法感兴趣的读者,提供PDF版本以供深入研究。
摘要由CSDN通过智能技术生成

文章中其实有很多图来帮助理解,但是因为外链的原因,我电脑上的图不能直接拉过来,要完整版的可以评论我直接发PDF版本。因为笔记的原因没有英文注释代码,个人笔记,仅供参考。

排序

排序算法的评估指标

算法的稳定性:若待排序表中有两个元素 R i R_i Ri R j R_j Rj,其对应的关键字相同即 k e y i = k e y j key_i = key_j keyi=keyj,且在排序前 R i R_i Ri R j R_j Rj的前面,若使用某一排序算法排序后, R i R_i Ri仍然在 R j R_j Rj的前面,则称这个排序算法时稳定的,否则称排序算法是不稳定的。

排序算法的分类

  1. 内部排序:数据都在内存中——关注如何使算法时间、空间复杂度更低。
  2. 外部排序:数据太多,无法全部放入内存——还要关注如何使读/写磁盘次数更少。

插入排序

算法思想:每次将一个待排序的记录按其关键字大小插入到前面已排好序的子序列中,直到全部记录插入完成。

//直接插入排序
void InsertSort(int A[], int n){
   
  int i, j, temp;
  for(i=1; i<n; i++)                     //将各元素插入已排好序的序列中
    if(A[i] < A[i-1]){
                      //若A[i]关键字小于前驱
      temp = A[i];                       //用temp暂存A[i]
      for(j=i-1; j>=0 && A[j]>temp; --j) //检查所有前面已排好序的元素
        A[j+1] = A[j];                   //所有大于temp的元素都向后挪位
      A[j+1] = temp;                     //复制到插入位置
    }
}

算法效率分析

空间复杂度 O ( 1 ) O(1) O(1)

时间复杂度 O ( n 2 ) O(n^2) O(n2)

算法稳定性:稳定

优化——折半插入排序

思路:先用折半查找找到应该插入的位置,再移动元素

l o w > h i g h low > high low>high时,折半查找停止,应将 [ l o w ,   i − 1 ] [low,\ i-1] [low, i1]内的元素全部右移,并将 A [ 0 ] A[0] A[0]复制到 l o w low low所指位置。

A [ m i d ] = = A [ 0 ] A[mid] == A[0] A[mid]==A[0]时,为了保证算法的“稳定性”,应继续在 m i d mid mid所指位置右边寻找插入位置。

//折半插入排序
void InsertSort(int A[], int n){
   
  for i, j, low, high, mid;
  for(i=2; i<=n; i++){
             //依次将A[2]~A[n]插入前面的已排列序列
    A[0] = A[i];                //将A[i]暂存到A[0]
    low = 1;                    //设置折半查找的范围
    high = i-1;
    while(low <= high){
            //折半查找(默认递增有序)
      mid = (low + high) / 2;   //取中间点
      if(A[mid] > A[0])         //查找左半子表
        high = mid - 1;
      else                      //查找右半子表
        low = mid + 1;
    }
    for(j=i-1; j>=high+1; --j)
      A[j+1] = A[j];            //统一后移元素,空出插入位置
    A[high+1] = A[0];           //插入操作
  }
}

希尔排序(Shell Sort)

先追求表中元素部分有序,再逐渐逼近全局有序。

先将待排序表分割成若干形如 L [ i , i + d , i + 2 d , . . . , i + k d ] L[i, i+d, i+2d,..., i+kd] L[i,i+d,i+2d,...,i+kd]的“特殊”子表,对各个子表分布进行直接插入排序。缩小增量 d d d,重复上述过程,直到 d = 1 d=1 d=1为止。(每次将增量缩小一半)

//希尔排序
void ShellSort(int A[i], int n){
   
  int d, i, j;
  //A[0]只是暂存单元,不是哨兵,当j<=0时,插入位置已到
  for(d=n/2; d>=1; d=d/2)      //步长变化
    for(i=d+1; i<=n; ++i)
      if(A[i] < A[i-d]){
          //需将A[i]插入有序增量子表
        A[0] = A[i];           //暂存再A[0]
        for(j=i-d; j>0 && A[0]<A[j]; j-=d)
          A[j+d] = A[j];       //记录后移,查找插入的位置
        A[j+d] = A[0];         //插入
      }//if
}

算法性能分析

时间复杂度:和增量序列 d 1 , d 2 , d 3 . . . d_1,d_2,d_3... d1,d

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值