排序算法(二)

希尔排序

直接插入排序的改进------希尔排序 ( O ( n log ⁡ 2 ( n ) ) O(n\log_2(n)) O(nlog2(n)),不稳定,就地)

核心:分组预处理+组内直接插入排序

流程:将待排序元素序列分割成若干个子序列,在子序列内分别进行直接插入排序,待序列基本有序(接近正序)时,再对全体记录进行直接插入排序,能够大大提升直接插入排序效率。希尔排序不存在有序区和无序区。

分组方法:并非逐段分组,而是将相距某个增量的元素组成一个子序列。对于长度为 n n n的数组,增量序列为 n 2 1 , n 2 2 , n 2 3 , ... , 1 \frac{n}{2^1},\frac{n}{2^2},\frac{n}{2^3},\ldots,1 21n,22n,23n,...,1,且增量序列互质(最经典的分组方法)。

cpp 复制代码
void sort(){
    for(int gap=MAX/2;gap>0;gap/=2){//逐步缩小gap,初始间隔为MAX/2,依次折半
        for(int j=gap;j<MAX;j++){//从gap开始,对每组序列内进行直接插入排序
            int temp=a[j],i;
            for(i=j-gap;i>=0;i-=gap){//此处与直接插入排序稍有不同:j为i-gap而非i-1,迭代时为j-=gap而非j--
                if(temp<a[i]) a[i+gap]=a[i];//将大者后移
                else break;//找到插入点
            }
            a[i+gap]=temp;
        }
    }
}

归并排序

归并排序是对分治法的运用。 O ( n log ⁡ 2 ( n ) ) O(n\log_2(n)) O(nlog2(n))​,稳定,非就地

cpp 复制代码

快速排序

冒泡排序的改进------快速排序 ( O ( n log ⁡ 2 ( n ) ) O(n\log_2(n)) O(nlog2(n))​,不稳定,就地)

核心:哨兵变量的选取

流程:在每次划分中,选一个枢轴 (哨兵变量 /主元/基准值,通常选第一个元素作为枢轴,但在最坏情况下会劣化为冒泡排序),将待排序序列划分成两部分,左侧记录均 ≤ \le ≤轴值,右侧记录均 ≥ \ge ≥​轴值(左小右大),哨兵变量位于序列中间(枢轴归位),本次划分完毕。然后分别对这两部分重复上述过程,直到每部分内只有一个元素或为空为止,整个序列有序。

  1. 左右指针法
  • 实现方法1
cpp 复制代码
extern int a[MAX];
int part(int l,int r){
   int i=l,j=r;//i为轴值指针
   while(i<j){
       while(a[i]<=a[j]&&i<j) j--;//从右侧开始找比轴值小的元素 注:先从轴值的对侧开始扫描
       if(i<j) swap(a[i],a[j]),i++;//小者置前,此处变为j为轴值指针
       while(a[j]>=a[i]&&i<j) i++;//从左侧开始找比轴值大的元素
       if(i<j) swap(a[i],a[j]),j--;//大者置后,此处变为i为轴值指针
   }
   return i;//返回轴值最终所在位置
}
void sort(int l,int r){
    int i;
    if(l<r){
        i=part(l,r);
        sort(l,i-1);
        sort(i+1,r);
    }
}
//调用:sort(0,MAX-1);
  • 实现方法2
cpp 复制代码
extern int a[MAX];
int part(int l,int r){//l:轴值指针
    int i=l,j=r;
    while(i<j){
        while(a[l]<=a[j]&&i<j) j--;//从右侧找到首个比轴值小的元素
        while(a[l]>=a[i]&&i<j) i++;//从左侧找到首个比轴值大的元素
        swap(a[i],a[j]);//确保左小右大
    }
    swap(a[l],a[i]);//先从右侧扫小的,因此a[i]一定是比轴值小的元素
    return i;
}
void sort(int l,int r){
    int i;
    if(l<r){
        i=part(l,r);
        sort(l,i-1);
        sort(i+1,r);
    }
}
//调用:sort(0,MAX-1);
  1. 挖坑法
cpp 复制代码
extern int a[MAX];
int part(int l,int r){
    int i=l,j=r,key=a[i];
    while(i<j){
        while(a[j]>=key&&i<j) j--;
        if(i<j) a[i]=a[j],i++;
        while(a[i]<=key&&i<j) i++;
        if(i<j) a[j]=a[i],j--;
    }
    a[i]=key;
    return i;
}
void sort(int l,int r){
    int i;
    if(l<r){
        i=part(l,r);
        sort(l,i-1);
        sort(i+1,r);
    }
}
//调用:sort(0,MAX-1);
  1. 前后指针法
cpp 复制代码

堆排序

简单选择排序的改进------堆排序 ( O ( n log ⁡ 2 ( n ) ) O(n\log_2(n)) O(nlog2(n)),不稳定,就地)

cpp 复制代码

计数排序

O ( n + k ) O(n+k) O(n+k),稳定,非就地

cpp 复制代码

桶排序

O ( n + k ) O(n+k) O(n+k),稳定,非就地

cpp 复制代码

基数排序

( O ( n × k ) O(n\times k) O(n×k),稳定,非就地)

cpp 复制代码
相关推荐
mit6.824几秒前
二分猜答案
算法
_OP_CHEN12 分钟前
【算法基础篇】(四十二)数论之欧拉函数深度精讲:从互质到数论应用
c++·算法·蓝桥杯·数论·欧拉函数·算法竞赛·acm/icpc
Eloudy28 分钟前
模板函数动态库与头文件设计示例
算法·cuda
星云数灵39 分钟前
大模型高级工程师考试练习题4
人工智能·算法·机器学习·大模型·大模型考试题库·阿里云aca·阿里云acp大模型考试题库
千金裘换酒42 分钟前
Leetcode 二叉树中序遍历 前序遍历 后序遍历(递归)
算法·leetcode·职场和发展
cookqq43 分钟前
MySQL 5.7 大表删除部分数据:.ibd 文件会变小吗?磁盘会释放吗?
数据结构·数据库·mysql
姓蔡小朋友1 小时前
算法-双指针
算法
D_FW1 小时前
数据结构第三章:栈、队列与数组
数据结构·算法
福楠1 小时前
模拟实现stack、queue、priority_queue
c语言·开发语言·数据结构·c++
Tisfy1 小时前
LeetCode 1339.分裂二叉树的最大乘积:深度优先搜索(一次DFS+存数组并遍历)
算法·leetcode·深度优先·题解