【数据结构】常见七大排序总结
目录
一、插入排序:直接插入排序【稳定排序方法】
二、插入排序:希尔排序【不稳定排序方法】
三、选择排序:直接选择排序【不稳定排序方法】
四、选择排序:堆排序【不稳定排序方法】
五、交换排序:冒泡排序【稳定排序方法】
六、交换排序:快速排序【不稳定排序方法】
七、归并排序:归并排序【稳定排序方法】
前言
排序是计算机程序设计中的一种重要操作,其功能是对一个数据元素集合或序列重新排列成一个按数据元素某个相知有序的序列。排序分为两类:内排序和外排序。
今天为大家总结一下,常见的七大排序:
一、插入排序:直接插入排序【稳定排序方法】
1.概述
1.1 插入排序,一般也被称为直接插入排序。
1.2 插入排序:每次将一个待排序的记录,按其关键字的大小插入到前面已排序好的记录序列中的适当位置,直到全部记录插入完成为止。
1.3 直接插入排序是一种最简单的排序方法,其基本操作是将一条记录插入到已排好的有序表中,从而得到一个新的、记录数量增1的有序表。
2. 算法实现:
2.1不带监视哨
//【算法1】 不带监视哨的直接插入排序算法
public void insertSort() {RecordNode temp;int i, j;for (i = 1; i < this.curlen; i++) { // n-1趟扫描temp = r[i]; // 将待插入的第i条记录暂存在temp中for (j = i - 1; j >= 0 && temp.key.compareTo(r[j].key) < 0; j--) { r[j + 1] = r[j]; // 将前面比r[i]大的记录向后移动}r[j + 1] = temp; // r[i]插入到第j+1个位置//System.out.print("第" + i + "趟: ");//display();}
}
2.2带监视哨
//【算法2】带监视哨的直接插入排序算法
public void insertSortWithGuard() {int i, j;
// System.out.println("带监视哨的直接插入排序");for (i = 1; i <this.curlen; i++) { //n-1趟扫描r[0] = r[i]; //将待插入的第i条记录暂存在r[0]中,同时r[0]为监视哨for (j = i - 1; r[0].key.compareTo(r[j].key) < 0; j--) { //将前面较大元素向后移动r[j + 1] = r[j];}r[j + 1] = r[0]; // r[i]插入到第j+1个位置System.out.print("第" + i + "趟: ");display(9);}
}
二、插入排序:希尔排序【不稳定排序方法】
1.概述
希尔排序(Shell's Sort)是插入排序的一种又称“缩小增量排序”,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。
2. 算法实现
//【算法3】希尔排序算法
public void shellSort(int[] d) { //d[]为增量数组RecordNode temp;int i, j;System.out.println("希尔排序");//控制增量,增量减半,若干趟扫描for (int k = 0; k < d.length; k++) {//一趟中若干子表,每个记录在自己所属子表内进行直接插入排序int dk = d[k];for (i = dk; i < this.curlen; i++) {temp = r[i];for (j = i - dk; j >= 0 && temp.key.compareTo(r[j].key) < 0; j -= dk) {r[j + dk] = r[j];}r[j + dk] = temp;}System.out.print("增量dk=" + dk + " ");display();}
}
三、选择排序:直接选择排序【不稳定排序方法】
1.概述
首先在所有记录中选出关键字值最小的记录,把它与第一个记录进行位置交换,
然后在其余的记录中再选出关键字值次小的记录,与第二个记录进行位置交换。
依次类推,直到所有记录排好序。
2. 算法实现
//【算法】直接选择排序
public void selectSort() {// System.out.println("直接选择排序");RecordNode temp; //辅助结点for (int i = 0; i < this.curlen - 1; i++) {//n-1趟排序//每趟在从r[i]开始的子序列中寻找最小元素int min = i; //设第i条记录的关键字最小for (int j = i + 1; j < this.curlen; j++) {//在子序列中选择关键字最小的记录if (r[j].key.compareTo(r[min].key) < 0) {min = j; //记住关键字最小记录的下标}}if (min != i) { //将本趟关键字最小的记录与第i条记录交换temp = r[i];r[i] = r[min];r[min] = temp;}System.out.print("第" + (i + 1) + "趟: ");display();}
}
四、选择排序:堆排序【不稳定排序方法】
1.概述
堆排序(英语:Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
大顶堆:每个节点的值都大于或者等于它的左右子节点的值。
小顶堆:每个节点的值都小于或者等于它的左右子节点的值。
一般升序采用大顶堆,降序采用小顶堆
2.示意图
3.算法实现
基本思想:
1. 首先将这n条记录按关键字值的大小建立堆(称为初始堆),将堆顶元素r[0]与r[n-1]交换
2. 然后,将剩下的{r[0]..r[n-2]}序列调整成堆
3. 再将 r[0]与r[n-2]交换,再将剩下的{r[0]..r[n-3]}序列调整成堆
4. 如此反复,直到整个序列有序。
5. 这个过程称为堆排序
3.1 筛选法调整堆:算法
//【算法】将以筛选法调整堆算法
//将以low为根的子树调整成小顶堆,low、high是序列下界和上界
public void sift(int low, int high) {int i = low; //子树的根int j = 2 * i + 1; //j为i结点的左孩子RecordNode temp = r[i];while (j < high) { //沿较小值孩子结点向下筛选if (j < high - 1 && r[j].key.compareTo(r[j + 1].key) > 0) {j++; //数组元素比较,j为左右孩子的较小者}if (temp.key.compareTo(r[j].key) > 0) { //若父母结点值较大r[i] = r[j]; //孩子结点中的较小值上移i = j;j = 2 * i + 1;} else {j = high + 1; //退出循环}}r[i] = temp; //当前子树的原根值调整后的位置
// System.out.print("sift " + low + ".." + high + " ");
// display();
}
3.2堆排序:算法
//【算法】 堆排序算法
public void heapSort() {// System.out.println("堆排序");int n = this.curlen;RecordNode temp;// 从最后一个非叶子节点开始调整堆,直到根结点for (int i = n / 2 - 1; i >= 0; i--) {//创建堆sift(i, n);}System.out.println("堆构建完成");for (int i = n - 1; i > 0; i--) {//每趟将最小值交换到后面,再调整成堆// 第一个元素和无序中的最后一个交换temp = r[0];r[0] = r[i];r[i] = temp;sift(0, i);}
}
五、交换排序:冒泡排序【稳定排序方法】
1.概述
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
将待排序的数组看成从上到下的存放,把关键字较小的记录看成较轻的,关键字较大的记录看成较重的。
较小关键字值的记录,好像水中的气泡一样,向上浮;
较大关键字值的记录,好像水中的石块一样,向下沉;
当所有的气泡都浮到了相应的位置,并且所有的石块都沉到了水中,排序就结束了
2.算法实现
//【算法】 冒泡排序算法
public void bubbleSort() {
// System.out.println("冒泡排序");RecordNode temp; // 辅助结点boolean flag = true; // 是否交换的标记for (int i = 1; i < this.curlen && flag; i++) { // 有交换时再进行下一趟,最多n-1趟flag = false; // 假定元素未交换for (int j = 0; j < this.curlen - i; j++) { // 一次比较、交换if (r[j].key.compareTo(r[j + 1].key) > 0) { // 逆序时,交换temp = r[j];r[j] = r[j + 1];r[j + 1] = temp;flag = true; //如果发生交换,记录}}System.out.print("第" + i + "趟: ");display();}
}
六、交换排序:快速排序【不稳定排序方法】
1.概述
快速排序:Quick Sort
通过一趟排序将要排序的记录分割成独立的两个部分,其中一部分的所有记录的关键字值都比另外一部分的所有记录关键字值小。
然后再按此方法对这两部分记录分别进行快速排序。
整个排序过程可以递归进行,以此达到整个记录序列变成有序
2.算法实现
2.1一趟快速排序
//【算法】一趟快速排序
//交换排序表r[i..j]的记录,使支点记录到位,并返回其所在位置
//此时,在支点之前(后)的记录关键字均不大于(小于)它
public int Partition(int i, int j) {RecordNode pivot = r[i]; //第一个记录作为支点记录System.out.println(i + ".." + j + ", pivot=" + pivot.key + " ");System.out.print("初始值: ");int c = 0;display();while (i < j) { //从表的两端交替地向中间扫描// 1.1 从后到前,寻找第一个比支点小的元素while (i < j && pivot.key.compareTo(r[j].key) <= 0) {j--;}// 1.2 将后面较小的元素,移到前面去if (i < j) {r[i] = r[j]; //将比支点记录关键字小的记录向前移动System.out.print("第"+(++c)+"次交换后:");display();i++;}// 2.1 从前到后,选择第一恶比支点大的元素while (i < j && pivot.key.compareTo(r[i].key) > 0) {i++;}// 2.2 将前面较大的元素,移到后面去if (i < j) {r[j] = r[i]; //将比支点记录关键字大的记录向后移动System.out.print("第"+(++c)+"次交换后:");display();j--;}}r[i] = pivot; //支点记录到位System.out.print("一趟完成: ");display();return i; //返回支点位置
}
2.2 完整快排
//【算法】 递归形式的快速排序算法
//对子表r[low..high]快速排序
public void qSort(int low, int high) {if (low < high) {int pivotloc = Partition(low, high); // 一趟排序,将排序表分为两部分qSort(low, pivotloc - 1); // 低子表递归排序qSort(pivotloc + 1, high); // 高子表递归排序}
}//【算法完整快排】顺序表快速排序算法
public void quickSort() {qSort(0, this.curlen - 1);
}
七、归并排序:归并排序【稳定排序方法】
1.概述
归并排序是建立在归并操作上的一种有效,稳定的排序算法。是将合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。已有序的子序列
归并排序:将两个或两个以上的有序表合并成一个新的有序表。
归并排序分类:
1. 二路归并排序
2. 多路归并排序
2.算法实现
2.1 两个相邻有序序列归并:算法
/**** @param r 待排序的数组(多个有序子序列)* @param order 已经排序号的数组* @param h 第一个子序列开始的位置* @param m 第一个子序列结束的位置,第二个子序列开始的位置为m+1* @param t 第二个子序列结束的位置*/
//【算法】两个有序序列的归并算法
//把r数组中两个相邻的有序表r[h]~r[m]和r[m+1]~r[t]归并为一个有序表order[h]~order[t]
public void merge(RecordNode[] r, RecordNode[] order, int h, int m, int t) {int i = h, j = m + 1, k = h;while (i <= m && j <= t) { // 将r中两个相邻子序列归并到order中if (r[i].key.compareTo(r[j].key) <= 0) {// 较小值复制到order中order[k++] = r[i++];} else {order[k++] = r[j++];}}while (i <= m) { // 将前一个子序列剩余元素复制到order中order[k++] = r[i++];}while (j <= t) { // 将后一个子序列剩余元素复制到order中order[k++] = r[j++];}
}
2.1 一趟归并:算法
//【算法】一趟归并算法
//把数组r[n]中每个长度为s的有序表两两归并到数组order[n]中
//s 为子序列的长度,n为排序序列的长度
public void mergepass(RecordNode[] r, RecordNode[] order, int s, int n) {System.out.print("子序列长度s=" + s + " ");int p = 0; //p为每一对待合并表的第一个元素的下标,初值为0while (p + 2 * s - 1 <= n - 1) { //两两归并长度均为s的有序表merge(r, order, p, p + s - 1, p + 2 * s - 1);p += 2 * s;}if (p + s - 1 < n - 1) { //归并最后两个长度不等的有序表merge(r, order, p, p + s - 1, n - 1);} else {for (int i = p; i <= n - 1; i++) //将剩余的有序表复制到order中{order[i] = r[i];}}
}
2.1 二路归并: 算法
//打印方法
public void display(RecordNode[] arr) { //输出数组元素for (int i = 0; i < arr.length; i++) {String str = arr[i].key.toString().length() == 1 ? " " : " ";System.out.print(str + arr[i].key.toString());}System.out.println();
}//【算法】2-路归并排序算法
public void mergeSort() {System.out.println("归并排序");int s = 1; // s为已排序的子序列长度,初值为1int n = this.curlen;RecordNode[] temp = new RecordNode[n]; // 定义长度为n的辅助数组tempwhile (s < n) {mergepass(r, temp, s, n); // 一趟归并,将r数组中各子序列归并到temp中display(temp); // 打印temp临时数组s *= 2; // 子序列长度加倍,下一趟归并mergepass(temp, r, s, n); // 将temp数组中各子序列再归并到r中display(); // 打印r数组s *= 2;}
}
写到最后
四季轮换,已经数不清凋零了多少, 愿我们往后能向心而行,一路招摇胜!
【数据结构】常见七大排序总结相关推荐
- 【数据结构---排序】庖丁解牛式剖析常见的排序算法
排序算法 一.常见的排序算法 二.常见排序算法的实现 1. 直接插入排序 2. 希尔排序 3. 直接选择排序 4. 堆排序 5. 冒泡排序 6. 快速排序 6.1 递归实现快速排序 思路一.hoare ...
- 数据结构七大排序算法图解
系列文章整合 排序是计算机程序设计中一个非常重要的操作,它将一个数据元素(或记录)的任意序列重新排列成一个按关键字有序的序列,在有序的序列中查找元素的效率很高,但是无序序列只能逐一查找,因此,如何进行 ...
- 七大排序的个人总结(二) 归并排序(Merge
七大排序的个人总结(二) 归并排序(Merge 归并排序(Merge Sort): 归并排序是一个相当"稳定"的算法对于其它排序算法,比如希尔排序,快速排序和堆排序而言,这些算法 ...
- 万字手撕七大排序(代码+动图演示)
万字拿捏七大排序 1.排序的概念及其运用 1.1排序的概念 1.2 排序的运用 1.3 常见的排序算法 2. 常见排序算法的实现 2.1 插入排序 2.1.1 基本思想 2.1.2直接插入排序 2.1 ...
- 白话经典算法之七大排序
本篇转至白话经典算法之七大排序 MoreWindows 白话经典算法之七大排序 这是本人在研一上课时所整理的文档,包括冒泡排序,直接排序这七种常用的排序方法,这些文章不仅使我在考试中取了不 错的成绩, ...
- Java排序(七大排序合集)
七大排序 1.冒泡排序 1.1.排序过程图 1.2.排序思想 1.3.排序代码 1.4.代码改进 2.选择排序 2.1.排序过程图 2.2.排序思想 2.3.排序代码 2.4.代码改进--双向选择排序 ...
- access两字段同时升序排序_7 天时间,我整理并实现了这 9 种常见的排序算法
排序算法 回顾 我们前面已经介绍了 3 种最常见的排序算法: java 实现冒泡排序讲解 QuickSort 快速排序到底快在哪里? SelectionSort 选择排序算法详解(java 实现) 然 ...
- python常用算法有哪些_python常见的排序算法有哪些?
大家都知道,关于python的算法有很多,其中最为复杂的就是python的排序算法,因为它并不是单一的,而是复杂的,关于排序算法就有好几种不同的方式,大家可以根据以下内容,结合自己的项目需求,选择一个 ...
- 数据结构的六大排序算法详解
文章目录 一.简单排序 1.Comparable接口介绍 2.冒泡排序 3.选择排序 4.插入排序 二.高级排序 1.希尔排序 2.归并排序 3.快速排序 4.排序的稳定性 一.简单排序 在我们的程序 ...
最新文章
- android action pick,Intent中各种常见的Action
- 用Discuz/UCenter账号实现Wifi登录认证
- Ceres Solver Document学习笔记
- python(matplotlib1)——figure图像,坐标设置
- 二进制转base64
- ip服务器ip地址信息配置,服务器ip地址配置
- XEngine:深度学习模型推理优化
- 项目交换通知——PM(李忠)
- LR录制https协议报证书错误,导航已阻止
- 使用Python与Sharepoint进行交互——第1部分
- viper4android资源分享,一步一步教你如何使4.42版本ROOT并且安装Viper4Android音效软件...
- 以华为2016年笔试题为例,详解牛客网的在线判题系统(OJ模式)
- 锐龙R3 4300U和i5-9300H 哪个好
- 有道身份证查询接口API
- 小米最大的竞争对手不是苹果而是华为
- Zabbix以trapper方式监控MySQL备份文件
- 浮动与display:inline-block
- Ubuntu 16.04 一系列软件安装命令,包括QQ、搜狗、Chrome、vlc、网易云音乐安装方法(转载)...
- u-boot-2012.04.01移植到TQ2440
- pebble刷android wear,Pebble智能手表刷官方中文固件教程
热门文章