排序


文章目录

  • 排序
  • 内部排序
    • 一、插入排序
      • 1.直接插入排序
      • 2.折半插入排序
      • 3.希尔排序
    • 二、交换排序
      • 1.冒泡排序
      • 2.快速排序
    • 三、选择排序
      • 1.简单选择排序
      • 2.堆排序
    • 四、归并排序和基数排序
      • 1.二路归并排序(merge sort)
      • 2.桶排序(计数排序)
      • 3,基数排序
    • 五、王道中的实现细节
      • 1.快速排序
      • 2.堆排序(非递归)
      • 3.归并排序
      • 4.基数排序

内部排序

一、插入排序

基本思想:每次将一个待排序的记录按其关键字大小插入前面已经排好序的子序列中。

1.直接插入排序

给定一个整数数组 q[],将该数组升序排列。以第一个元素作为有序数组,其后的元素通过在这个已有序的数组中找到合适的位置并插入
a. 时间复杂度[1] 最好情况:O(n)[2] 平均情况:O(n^2)[3] 最坏情况:O(n^2)
b. 辅助空间复杂度      O(1)
c. 稳定性:           稳定
void insert_sort()
{for(int i = 1;i < n; i ++ ) //0~i-1已经有序{int t = q[i], j;//i位置元素待插入for(j = i-1; j>=0 && q[j] > t; j -- ){ //向前寻找插入位置if(q[j] > t) q[j+1] = q[j];}q[j+1] = t; //插入}
}

2.折半插入排序

给定一个整数数组 q[],将该数组升序排列。与直接插入排序的唯一区别就是 查找插入位置时 使用二分,复杂度不变
a. 时间复杂度[1] 最好情况:O(n)[2] 平均情况:O(n^2)[3] 最坏情况:O(n^2)
b. 辅助空间复杂度      O(1)
c. 稳定性:           稳定void binary_search_insert_sort()
{for(int i = 1; i < n; i ++ ) //0~i-1已经有序{if(q[i]>=q[i-1]) continue; int t = q[i];//i位置元素待插入int l = 0, r = i-1;while(l < r)  //二分寻找插入位置(大于t的第一个位置){int mid = (l+r)>>1;if(q[mid] > t) r=mid;else l=mid+1;}for(int j = i-1; j >= r ;j--) q[j+1]=q[j];q[r]=t;//插入}
}

3.希尔排序

给定一个整数数组 q[],将该数组升序排列。类插入排序,只是向前移动的步数变成d,分别在各组内进行 直接插入排序
a. 时间复杂度         O(n^(3/2))
b. 辅助空间复杂度      O(1)
c. 稳定性:           不稳定(分组导致)void shell_sort()  // 希尔排序
{for(int d = n/2; d >= 1; d /= 2)//步长{for(int start = 0; start < d; start ++)//分组(分别进行直接插入排序){for(int j = start+d; j < n; j += d)//直接插入排序{int t = q[j],k;for(k = j-d; k >=0 && q[k] > t; k -= d){q[k+d]=q[k];}q[k+d]=t;}}}
}

二、交换排序

基本思想:根据比较两个关键字结果来对换其位置(每次确定一个元素的最终位置)

1.冒泡排序

给定一个整数数组 nums,将该数组升序排列。通过相邻元素的比较和交换,使得每一趟循环都能找到未有序数组的最小值(从后往前)
a. 时间复杂度[1] 最好情况:O(n) [2] 平均情况:O(n^2)[3] 最坏情况:O(n^2)
b. 辅助空间复杂度      O(1)
c. 稳定性:           稳定void bubble_sort()  // 冒泡排序
{for(int i = 0; i < n-1; i ++ ) //0~i-1已经有序{bool has_swap = false;for(int j = n-1; j > i; j -- ){ //从后往前冒泡if(q[j] < q[j-1]) swap(q[j],q[j-1]),has_swap=true;}if(!has_swap) return ;//没有交换说明已经有序}
}

2.快速排序

给定一个整数数组 q[],将该数组升序排列。基于分治思想
选择中间点为分界点,使得左边的数<=x,右边的数>=x
最后再递归左右两边a. 时间复杂度[1] 最好情况:O(nlogn)[2] 平均情况:O(nlogn)[3] 最坏情况:O(n^2)   数组逆序且选择边界点为分界点时
b. 辅助空间复杂度      O(logn)
c. 稳定性:           不稳定void quick_sort(int l, int r)  // 快速排序
{if(l>=r) return ;int i = l-1,  j= r+1, x=q[(l+r)/2];while(i < j){do i++; while(q[i] < x);do j--; while(q[j] > x);if(i < j) swap(q[i],q[j]);}quick_sort(l,j);quick_sort(j+1,r);
}

三、选择排序

基本思想:每一趟都从待排序的元素中选取最小(或最大)的元素加入有序子序列

1.简单选择排序

给定一个整数数组 q[],将该数组升序排列。每次从未排序中找到最小的元素放到当前位置
a. 时间复杂度[1] 最好情况:O(n^2)[2] 平均情况:O(n^2)[3] 最坏情况:O(n^2)
b. 辅助空间复杂度      O(1)
c. 稳定性:           不稳定void select_sort()  // 简单选择排序
{for(int i = 0; i < n; i ++){int k=i;for(int j = i+1; j < n ;j++){if(q[j]<q[k]) k=j;}swap(q[k],q[i]);}
}

2.堆排序

给定一个整数数组 q[],将该数组升序排列。是一棵采用顺序存储的完全二叉树,从下往上建图,down()操作:建立以当前结点为根的大根堆
a. 时间复杂度[1] 最好情况:O(nlogn)[2] 平均情况:O(nlogn)[3] 最坏情况:O(nlogn)
b. 辅助空间复杂度      O(logn)
c. 稳定性:           不稳定
void down(int u)
{int t=u;if(u*2 <= sz && q[u*2] > q[t]) t = u*2;if(u*2+1 <= sz && q[u*2+1] > q[t]) t=u*2+1;if(t != u){swap(q[t],q[u]);down(t);}
}
void heap_sort()  // 堆排序(大根堆),下标一定要从1开始
{sz=n;for(int i = n/2; i; i--) down(i);for(int j = 0; j < n-1 ; j ++) //堆的删除{swap(q[1],q[sz]);sz--;down(1);}
}

四、归并排序和基数排序

1.二路归并排序(merge sort)

//基于分治思想
//1.[L,R]=> [L,mid],[mid+1,R]
//2.递归排序[L,mid],[mid+1,r]
//3.归并,将左右两个有序序列合并成一个有序序列a. 时间复杂度[1] 最好情况:O(nlogn)[2] 平均情况:O(nlogn)[3] 最坏情况:O(nlogn)
b. 辅助空间复杂度      O(n)
c. 稳定性:           稳定void merge_sort(int l, int r) //二路归并排序
{if(l>=r) return ;int mid = (l+r)>>1;merge_sort(l,mid),merge_sort(mid+1,r);int i = l, j = mid+1, k=0;while(i<=mid&&j<=r){if(q[i]<=q[j]) w[k++]=q[i++];else w[k++] = q[j++];}while(i<=mid) w[k++] = q[i++];while(j<=r)   w[k++] = q[j++];for(int i = l,j = 0; j < k; i ++, j ++) q[i]=w[j];
}

2.桶排序(计数排序)

//数据范围为m
//开m个桶,分别记录每个元素的个数(又称计数排序)
//求m个桶的前缀和S[i]
//从后往前遍历数组元素,把元素放入最终位置上(大于等于q[i]的元素个数就是元素q[i]的最终位置)(1) 时间复杂度a. 最好情况:O(n + m)b. 平均情况:O(n + m)c. 最坏情况:O(n + m)(2) 空间复杂度O(n + m)(3) 稳定void bucket_sort()   //桶排序
{for(int i=0;i<n;i++) s[q[i]]++; //开m个桶,计算每个桶的元素个数for(int i=1;i<N;i++) s[i]+=s[i-1];//前缀和for(int i=n-1;i>=0;i--) w[--s[q[i]]]=q[i];//计算元素的最终位置((s[q[i]]-1)即为q[i]的最终位置)for(int i=0;i<n;i++) q[i]=w[i];
}

3,基数排序

基数排序是桶排序的特例,优势是可以处理浮点数和负数,劣势是还要配合别的排序函数

将关键字转化为r进制数,把r进制的各位存入有序数组中,对其进行多关键字排序
由于r进制的每位的大小都是0~r-1,可以对其进行桶排序(O(n+r))对已经转化为r进制的关键字从r进制的低位到高位  分别进行k次桶排序(k为r进制的位数)  --O(k(n+r))(1) 时间复杂度a. 最好情况:O(d(n+r))b. 平均情况:O(d(n+r))c. 最坏情况:O(d(n+r))(2) 空间复杂度O(n + r)(3) 稳定(因为桶排序稳定)void radix_sort(int d,int r)  //基数排序(d表示r进制下有几位数)
{int radix=1;//r进制下的第一位for(int i = 1; i <= d; i++)  //从低位到高位{//对r进制的每位分别进行桶排序(以下5行为桶排序的操作)for(int j = 0; j < r; j ++ ) s[j] = 0;//r个桶清零(r进制下每位大小范围0~r-1)for(int j = 0; j < n; j ++ ) s[q[j] / radix % r] ++; //桶排序的计数for(int j = 1; j < r; j ++ ) s[j] += s[j - 1];//前缀和for(int j = n-1; j >= 0; j -- ) w[ -- s[q[j] / radix % r]] = q[j];//计算元素的位置for(int j = 0; j < n; j ++ ) q[j] = w[j];radix *= r;//处理r进制的下一位}
}radix_sort(10,10); //10进制  数据范围10^10所以d=10

五、王道中的实现细节

1.快速排序

考研初试题目中默认以第一个元素为基准元素。

2.堆排序(非递归)



3.归并排序


4.基数排序

建议参考上面提到的基数排序代码,以下是基于链表的实现,将桶排序部分改为了m个队列。



基数排序笔记:

基数排序笔记:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KILJJBYE-1653355701303)(E:\ACM算法模板\图片\11.png)]

十大排序算法(数据结构)相关推荐

  1. 中希尔排序例题代码_【数据结构与算法】这或许是东半球分析十大排序算法最好的一篇文章...

    码农有道 历史文章目录(请戳我) 关于码农有道(请戳我) 前言 本文全长 14237 字,配有 70 张图片和动画,和你一起一步步看懂排序算法的运行过程. 预计阅读时间 47 分钟,强烈建议先收藏然后 ...

  2. 数据结构与算法:十大排序算法之归并排序

    数据结构与算法:十大排序算法之归并排序 package TopTenSortingAlgorithms;/*** 归并排序:Java** @author skywang* @date 2014/03/ ...

  3. 数据结构与算法:十大排序算法之插入排序

    数据结构与算法:十大排序算法之插入排序 package TopTenSortingAlgorithms;import java.util.Arrays; import java.util.Scanne ...

  4. 数据结构与算法:十大排序算法之堆排序

    数据结构与算法:十大排序算法之堆排序 堆排序可以说是选择排序的优化 package TopTenSortingAlgorithms;import java.util.Arrays; import ja ...

  5. 数据结构与算法:十大排序算法之冒泡排序

    数据结构与算法:十大排序算法之冒泡排序 package array;import java.util.Arrays;//冒泡排序 //1.比较数组中两个相邻的元素,如果第一个数比第二个数大,我们就交换 ...

  6. 【数据结构与算法】这或许是东半球分析十大排序算法最好的一篇文章

    原地址:https://mp.weixin.qq.com/s?__biz=MzIwNTc4NTEwOQ==&mid=2247486981&idx=1&sn=c63cd080be ...

  7. 这或许是东半球分析十大排序算法最好的一篇文章

    作者 | 不该相遇在秋天 转载自五分钟学算法(ID:CXYxiaowu) 前言 本文全长 14237 字,配有 70 张图片和动画,和你一起一步步看懂排序算法的运行过程. 预计阅读时间 47 分钟,强 ...

  8. 「干货总结」程序员必知必会的十大排序算法

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:硬刚一周,3W字总结,一年的经验告诉你如何准备校招! 个人原创100W+访问量博客:点击前往,查看更多 绪论 身 ...

  9. 「归纳|总结」程序员必知必会的十大排序算法

    微信搜一搜「bigsai」关注这个有趣的程序员 新人原创公众号,求支持一下!你的点赞三连肯定对我至关重要! 文章已收录在 我的Github bigsai-algorithm 欢迎star 本文目录 绪 ...

  10. 归并排序执行次数_十大排序算法,看这篇就够了

    排序算法分类[1][2] 比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序. 非比较类排序:不通过比较来决定元素间的相对次序,它可以 ...

最新文章

  1. 【神经网络】(10) Resnet18、34 残差网络复现,附python完整代码
  2. Keras使用多个GPU并行
  3. Android 操作串口 (android serial port api)
  4. php获得帮助类数据_PHP解析xml格式数据工具类示例
  5. 有时间的话一定开办一个C语言视频讲座,希望得到支持。
  6. [iOS] dom解析xml数据,拿到lt;gt;里面的值
  7. 2018 KubeCon + CloudNativeCon完美落幕,行云献力
  8. 前端学习(2737):重读vue电商网站47之生成打包报告
  9. 此 sqltransaction 已完成;它再也无法使用_win10笔记本自带office报错无法激活的解决方法...
  10. OpenCV--读取图像中任意点的像素值,并显示坐标
  11. web界面设计要素及基本设计规范
  12. HI3559A soc中使用sensor hub的uart0
  13. 纯CSS实现正方体旋转效果
  14. 计算机格式化没有fat32,无需格式化 U盘FAT32转NTFS格式教程
  15. Android实现高斯模糊背景对话框,Android进行高斯模糊的简单实现
  16. 《八股文》20道Redis面试题
  17. wifi密码本 字典(免费二)
  18. 帝国CMS手游综合门户网站模板
  19. tft连接nodemcu 2
  20. 数据分析-网络爬虫:中美在这一领域展开无声较量,事关国家安全

热门文章

  1. dz论坛非应用商店的插件如何安装教程
  2. 计算机硬盘密码,电脑常识之--如何给移动硬盘[硬盘]加密码
  3. 关于PCB与设备外壳接地问题
  4. 运营商5G商业模式研究
  5. markdown编写操作手册
  6. PHP实训笔记,Java实训笔记(八)之mysql
  7. 蚂蚁金服技术90后:从艺术转投数学,还出版首本TensorFlow中文教材
  8. PEP 635 – Structural Pattern Matching: Motivation and Rationale
  9. OpenStack在天河二号的大规模部署实践(转)
  10. Hortonworks的开源框架SHC的使用(一)