各种排序算法总结

【C++】排序算法 冒泡排序、插入排序、选择排序、希尔排序、堆排序、归并排序、快速排序、计数排序、基数排序、桶排序、外排序 阅读详情

各种排序算法总结

   排序(Sorting) 是计算机程序设计中的一种重要操作,它的功能是将一个数据元素(或记录)的任意序列,重新排列成一个关键字有序的序列。

1、选择排序

  选择排序是一种直观简单的排序算法,它每次从待排序的数据元素中选出最小(或者最大)元素存放到序列的起始位置,直到全部待排序的数据元素排完。注意,选择排序并不是稳定的排序。

复制代码

 1 /*
 2  * @brief select sort
 3  * @param [in] arr: the array be sorted
 4  *           [in] length: the array size
 5  * @return void
 6  */
 7 void SelectSort(int arr[], int length)
 8 {
 9     for (int i = 0; i < length; i++) {
10         int min = i;
11         for (int j = i + 1; j < length; j++) {
12             if (arr[min] < arr[j]) {
13                 min = j;
14             }
15         }
16         if (min != i) {
17             swap(arr[min], arr[i]);
18         }
19     }
20 }

复制代码

2、冒泡排序

  冒泡排序也是一种直观简单的排序算法,它重复地走访要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。冒泡排序是一种稳定的排序。

复制代码

 1 /*
 2  * @brief bubble sort
 3  * @param [in] arr: the array be sorted
 4  *          [in] length: the array size
 5  * @return void
 6  */
 7 void BubbleSort(int arr[], int length)
 8 {
 9     for (int i = 0; i < length; i++) {
10         for (int j = 0; j < length - i - 1; j++) {
11             if (arr[j] > arr[j + 1]) {
12                 swap(arr[j], arr[j + 1]);
13             }
14         }
15     }
16 }

复制代码

3、插入排序

  插入排序基本思想是:每步将一个待排序的纪录,按其关键码值的大小插入前面已经排序的元素序列中适当位置上,直到全部插入完为止。插入排序是稳定的排序算法。

复制代码

 1 /*
 2  * @brief insert sort
 3  * @param [in] arr: the array be sorted
 4  *          [in] length: the array size
 5  * @return void
 6  */
 7 void InsertSort(int arr[], int length)
 8 {
 9     for (int i = 0; i < length; i++) {
10         for (int j = i; j > 0 && arr[j - 1] > arr[j]; j--) {
11             swap(arr[j], arr[j - 1]);
12         }
13     }
14 }
15 /* 这是插入排序的第二种写法 */
16 void InsertSort2(int arr[], int length)
17 {
18     for (int i = 0; i < length; i++)
19     {
20         int x = arr[i], j;
21         for (j = i; j > 0 && arr[j - 1] > x; j--)
22             arr[j] = arr[j - 1];
23         arr[j] = x;
24     }
25 }

复制代码

 4、希尔排序

  希尔排序(Shell Sort)是插入排序的一种,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个数组恰被分成一组,算法便终止。

复制代码

 1 /*
 2 * @brief shell sort
 3 * @param [in] arr: the array be sorted
 4 *          [in] length: the array size
 5 * @return void
 6 */
 7 void ShellSort(int arr[], int length)
 8 {
 9     for (int inc = length / 2; inc > 0; inc /= 2) {
10         for (int i = inc; i < length; i++) {
11             for (int j = i; j >= inc && arr[j - inc] > arr[j]; j -= inc) {
12                 swap(arr[j], arr[j - inc]);
13             }
14         }
15     }
16 }

复制代码

5、快速排序

  快速排序的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

复制代码

 1 /*
 2  * 快速排序
 3  * 快速排序是一种分治的排序算法,它将一个数组分成两个子数组,将两部分独立地排序。
 4  * 快速排序和归并排序是互补的:归并排序将数组分成两个子数组分别排序,并将有序的子数组归并以将整个数组排序;
 5  * 而快速排序的方式是当两个子数组有序时整个数组也就自然有序了。归并排序中,递归发生在处理整个数组之前,
 6  * 一个数组被分为两半;快速排序中,递归调用发生在处理整个数组之后,切分的位置取决于数组的内容。
 7  */
 8 int Partion(int arr[], int left, int right)
 9 {
10     int x = arr[right];
11     int i, j;
12 
13     for (i = j = left; i < right; i++) {
14         if (arr[i] <= x) {
15             swap(arr[i], arr[j++]);
16         }
17     }
18     swap(arr[j], arr[right]);
19 
20     return j;
21 }
22 void QuickSort(int arr[], int left, int right)
23 {
24     if (left < right) {
25         int mid = Partion(arr, left, right);
26         QuickSort(arr, left, mid - 1);
27         QuickSort(arr, mid + 1, right);
28     }
29 }
30 void QuickSort(int arr[], int length)
31 {
32     QuickSort(arr, 0, length - 1);
33 }

复制代码

 6、归并排序

  归并排序是将两个有序的数组归并成一个更大的有序数组。要将一个数组排序,可以先(递归的)将他分成两半分别排序,让后将结果归并起来。它能够保证将任意长度为N的数组排序所需时间和NlogN成正比;它的主要缺点就是所需的额外空间和N成正比。归并排序是稳定的排序算法。

复制代码

 1 /*
 2  * 归并排序
 3  * 归并排序将数组分成两个子数组分别排序,并将有序的子数组归并以将整个数组排序
 4  */
 5 void Merge(int arr[], int aux[], int left, int mid, int right) 
 6 {
 7     int i = left;
 8     int j = mid + 1;
 9     int k = left;
10 
11     while (i <= mid && j <= right) {
12         if (arr[i] > arr[j]) {
13             aux[k++] = arr[j++];
14         }
15         else {
16             aux[k++] = arr[i++];
17         }
18     }
19     while (i <= mid) {
20         aux[k++] = arr[i++];
21     }
22     while (j <= right) {
23         aux[k++] = arr[j++];
24     }
25     for (int i = left; i <= right; i++) {
26         arr[i] = aux[i];
27     }
28 }
29 void MergeSort(int arr[], int aux[], int left, int right)
30 {
31     if (left < right) {
32         int mid = left + (right - left) / 2;
33         MergeSort(arr, aux, left, mid);
34         MergeSort(arr, aux, mid + 1, right);
35         Merge(arr, aux, left, mid, right);
36     }
37 }
38 void MergeSort(int arr[], int length)
39 {
40     int *aux = new int[length];
41     MergeSort(arr, aux, 0, length - 1);
42     delete []aux;
43 }

复制代码

7、 堆排序

  堆排序可以分为两个阶段。在堆的构造阶段,我们将元使数组重新组织安排进一个堆中;然后在下沉阶段,我们从堆中按递减顺序取出所有元素并得到排序结果。堆排序主要工作都是在堆的下沉阶段完成的,这里我们将堆中最大的元素删除,然后放入堆缩小后数组中空出的位置。

复制代码

 1 /*
 2  * 堆排序
 3  * 堆排序是用堆来实现的一种排序算法,堆排序分为两个阶段,在堆的构造阶段中,我们将原始数据重新组织安排
 4  * 进一个堆中;然后在下沉排序阶段,我们从堆中按照递减顺序取出所有元素并得到排序算法
 5  */
 6 void Sink(int arr[], int i, int length)
 7 {
 8     while (2 * i <= length) {
 9         int child = 2 * i;
10         if (child < length && arr[child] < arr[child + 1]) {
11             child++;
12         }
13         if (arr[i] >= arr[child]) {
14             break;
15         }
16 
17         swap(arr[i], arr[child]);
18         i = child;
19     }
20 }
21 void HeapSort(int arr[], int length)
22 {
23     length--; /* 此时length代表数组最后一个元素下标 */
24     for (int i = length / 2; i >= 0; i--) { /* 这里一定要 i>=0,否则建堆不完全 */
25         Sink(arr, i, length);
26     }
27     
28     while(length >= 0) {
29         swap(arr[0], arr[length--]);
30         Sink(arr, 0, length);
31     }
32 }

复制代码

8、各种排序算法的稳定性和时间复杂度分析

什么是排序的稳定性呢?如果一个排序算法能够保留数组中重复元素的相对位置则可以称为是稳定的。以下是各个排序算法稳定性总结:

  • 选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法,
  • 冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法。

各个排序时间复杂度总结:

  • 冒泡法:这是最原始,也是众所周知的最慢的算法了。他的名字的由来因为它的工作看来象是冒泡:复杂度为O(n*n)。当数据为正序,将不会有交换。复杂度为O(n^2)。
  • 直接插入排序:O(n^2)
  • 选择排序:O(n^2)
  • 快速排序:平均时间复杂度log2(n)*n,所有内部排序方法中最高好的,大多数情况下总是最好的。
  • 归并排序:log2(n)*n
  • 堆排序:log2(n)*n
  • 希尔排序:算法的复杂度为log2(n)*n

 下面是一个总的表格,大致总结了我们常见的所有的排序算法的特点。

排序法平均时间最差情形稳定度额外空间备注
冒泡O(n2)    O(n2)稳定O(1)n小时较好
交换    O(n2)    O(n2)不稳定O(1)n小时较好
选择O(n2)O(n2)不稳定O(1)n小时较好
插入O(n2)O(n2)稳定O(1)大部分已排序时较好
基数O(logRB)O(logRB)稳定O(n)

B是真数(0-9),

R是基数(个十百)

ShellO(nlogn)O(ns) 1<s<2不稳定O(1)s是所选分组
快速O(nlogn)O(n2)不稳定O(nlogn)n大时较好
归并O(nlogn)O(nlogn)稳定O(1)n大时较好
堆O(nlogn)O(nlogn)不稳定O(1)n大时较好

更多排序算法时间复杂度和稳定性见:http://blog.youkuaiyun.com/u012796139/article/details/43889449

 

参考资料:

  1、https://github.com/luoxn28/algorithm_data_structure/tree/master/sort

  2、http://blog.youkuaiyun.com/u012796139/article/details/43889449

排序算法:稳定的排序算法 元素,并围绕主元对列表进行分区,将较小的元素放入低数组中,将所有较大的元素放入高数组中。然后,我们对他们的第十位的值进行排序。因此,我们可以对任意大小的列表进行排序,而无需在冒泡排序中使用任何额外的空间。我们可以说,子问题可以被视为对数组的一部分进行排序,从任何索引 s(start) 开始,到任何索引 e(end) 结束。正如我们上面所讨论的,最大堆是一个完全二叉树,其中每个内部节点中的值都大于或等于该节点的子节点中的值。此外,每次迭代后,已排序子数组的大小都会增加,而未排序子数组的大小会减少。 阅读详情

相关推荐

八种排序算法

偶尔有看到排序算法,想起来大学里老师也有讲授过冒泡排序、快速排序等,不过现在已经没什么概念,一查发现排序算法有八种,有的甚至连名字都没听过,感概平时看的少。既然已经看到了,就干脆了解下基础概念,避免在后续学习途中,出现一看就懵逼的情况。   冒泡排序 冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到...

dobat的博客 3349

九大排序算法再总结

如果要转载,需要注明出处: http://blog.youkuaiyun.com/xiazdong 本文是 http://blog.youkuaiyun.com/xiazdong/article/details/7304239 的补充,当年看了《大话数据结构》总结的,但是现在看了《算法导论》,发现以前对排序的理解还不深入,所以打算对各个排序的思想再整理一遍。 本文首先介绍了基于比较模型的排序算法,

xiazdong 31万+

排序算法总结及C++实现

文章目录1 引入 认识时间复杂度2 补充 对数器3 排序算法分析3.1 基于比较的排序3.1.1 冒泡排序3.1.2 选择排序3.1.3 插入排序3.1.4 归并排序补充题目 小和问题补充题目 逆序数3.1.5 快速排序3.1.6 堆排序3.2 非基于比较的排序3.2.1 计数排序3.2.2 桶排序3.2.3 基数排序4 排序总结4.1 稳定性4.2 工程中的综合排序算法4.3 有关排序...

李滚滚的博客 2223

「排序算法」十大经典排序算法

文章目录十大经典排序算法一、冒泡排序二、选择排序三、插入排序四、希尔排序五、归并排序六、快速排序七、堆排序八、计数排序九、桶排序十、基数排序 引用网站:菜鸟教程十大经典排序 十大经典排序算法 排序算法图片总结(图片来源于网络) 一、冒泡排序 冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢

秋天,黄叶坠地,凉风有信。 6436

排序算法 - 面试中的排序算法总结

排序算法总结 查找和排序算法是算法的入门知识,其经典思想可以用于很多算法当中。因为其实现代码较短,应用较常见。所以在面试中经常会问到排序算法及其相关的问题。但万变不离其宗,只要熟悉了思想,灵活运用也不是难事。 一般在面试中最常考的是快速排序和归并排序,并且经常有面试官要求现场写出这两种排序的代码。对这两种排序的代码一定要信手拈来才行。还有插入排序、冒泡排序、堆排序、基数排序、桶排序等。面试官对

从零开始 2982

TOD和PPS精确时间同步技术

授时

u010783226的专栏 1万+

【排序算法】排序算法总结

排序算法总结,将排序算法的分类、稳定性和特点进行一个总结,并附有跳转到对应详解的链接,方便大家学习

weixin_52811588的博客 988

MIKE11实战:平原河网水动力建模从入门到精通(附GIS数据处理技巧)

本文系统介绍了MIKE11软件在平原河网水动力建模中的完整实战流程。从GIS数据预处理、河网构建、参数率定到结果分析,详细阐述了构建可靠数字孪生模型的关键步骤与技巧,旨在帮助水利工程师高效解决平原地区复杂水流模拟的挑战,为防洪决策提供科学依据。

weixin_28419039的博客 690

稳定排序算法有哪些

稳定排序算法有哪些 相信您已经掌握了很多种排序算法,比如冒泡排序、插入排序、希尔排序、选择排序等。这些排序算法中,有些是 “稳定” 的,有些是 “不稳定” 的。 给定的待排序序列中,经常会包含相同的元素,例如: 3 1 2 4 2 此序列中包含两个元素 2,为了区分它们,我们分别称它们为 “红 2” 和 “绿 2”。 评价一个排序算法是否稳定,是指该算法完成排序的同时,是否会改变序列中相同元素的相对位置。例如,上面序列中红 2 和绿 2 的相对位置是:红 2 位于绿 2 的左侧,或者说绿 2 位于红 2

ccc369639963的博客 1万+

Gromacs空蛋白模拟实战:从PDB文件到动力学轨迹的完整流程解析

本文详细解析了使用Gromacs进行空蛋白分子动力学模拟的完整实战流程。从PDB文件处理、力场选择与拓扑构建,到模拟盒子创建、溶剂化与电荷中和,再到能量最小化、NVT/NPT平衡及最终的生产模拟与基础分析,提供了每一步的命令详解和关键注意事项,旨在帮助计算生物学研究者系统掌握这一核心研究工具。

weixin_28454475的博客 279

网络工程师如何利用Python自动Telnet到N个路由器并执行配置?

telnetlib是Python标准库中的一个模块,专门用于实现Telnet协议。通过telnetlib,我们可以方便地与支持Telnet协议的远程设备进行通信。telnetlib提供了基本的Telnet功能,如连接远程主机、发送命令、读取响应等,使得编写Telnet自动化脚本变得非常简单。文档:可以选择中文:虽然telnetlib的功能相对基础,但对于大多数Telnet操作来说已经足够。通过telnetlib,可以轻松地实现与网络设备的交互,完成自动化配置任务。

网络技术联盟站 299

什么是排序算法?常见的排序算法有哪些?

计数排序适用于数据范围较小且已知的情况,其时间复杂度为线性时间,非常适合处理小范围内的数据排序。基数排序适用于整数排序,特别是当数据范围较大但数据量适中时。它通过多次应用计数排序来实现多轮排序,从而克服了传统排序算法在处理大范围数据时的效率问题。

破损的天堂鸟博客 1229

科研绘图系列:基因突变瀑布图统计以及可视化

科研绘图系列:基因突变瀑布图统计以及可视化

专注生信领域 1659

排序算法详解

排序算法是计算机科学中最基础也最重要的算法之一。它将一组数据(例如数字列表、字符串集合)按照特定的顺序(升序或降序)重新排列。高效的排序算法对于优化其他算法(如搜索和合并算法)的效率至关重要。

m0_54069809的博客 1173

Unlocking Decoding-time Controllability: Gradient-FreeMulti-Objective Alignment with Contrastive Pr

将基于庞大网络语料库训练的大型语言模型(LLMs)(OpenAI,2023;Touvron 等,2023;Google,2023)与人类偏好对齐,是减少产生不安全(Wei 等,2023)、幻觉(Zhang 等,2023b)和有偏见(Gallegos 等,2023)内容的重要一步。随着偏好学习技术(如 PPO(Schulman 等,2017)、DPO(Rafailov 等,2023)及其他变体(Azar 等,2023;Ethayarajh 等,2024;

qq_52053775的博客 1169

《ESP32单片机基础入门》第2章:开发环境搭建

【代码】《ESP32单片机基础入门》第2章:开发环境搭建。

2301_79143213的博客 582

十大经典排序算法

十种常见的排序算法可分为以下两大类: 比较类排序:通过比较来决定元素间的相对位置,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序。 非比较类排序:不通过比较来决定元素间的相对位置,它可以突破基于比较排序的时间下限,以线性时间运行,因此也称为线性时间非比较类排序。 时间复杂度: 从序列的初始状态到经过排序算法的变换移位等操作变到最终排序好的结果状态的过程所花费的时间度量。

qq_40896594的博客 3672

基于AUTOSAR的汽车电子项目--电动助力转向系统

基于AUTOSAR的汽车电子项目开发通常涵盖广泛的领域,例如动力系统控制、车身电子、信息娱乐系统、高级驾驶辅助系统(ADAS)等。以下是一个简化的示例项目,展示了如何在AUTOSAR环境下开发一个电动助力转向系统(Electric Power Steering, EPS)的控制软件

MHD0815的博客 2131

十大排序算法

算法稳定性:单次比较后,两个值相等的邻近元素的位置在排序后,相对位置没有改变。

一名想做出点成就的后端~ 1429

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

排序算法总结

1.排序算法分类 基础的排序算法包含冒泡排序、选择排序、插入排序、希尔排序、堆排序、归并排序及快速排序。 根据实现类型可分为插入排序类、选择排序类、交换排序类及归并排序类。 2.排序算法的综合分析 各算法的排序方式、平均情况、最好最坏情况、所需的辅助空间及稳定性如下: 事实上,排序算法没有十全十美,本来想写一套模拟测试的数据来验证孰优孰略。但是突然发现可比性不高,需要根据

黄俊彬 2542

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

排序算法-10种排序算法

文章目录一、排序算法是什么?1.解释2.内部排序3.外部排序二、排序算法介绍及实现1.冒泡排序算法描述四、测试 一、排序算法是什么? 1.解释 这里引入百度百科的解释: 谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。 排序算法,就是如何使得记录按照要求排列的方法。排序算法在很多领域得到相当地重视,尤其是在大量数据的处理方面。一个优秀的算法可以节省大量的资源。 在各个领域中考虑到数据的各种限制和规范,要得到一个符合实际的优秀算法,得经过大量的推理和分析。 2.内

GGB__的博客 934

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

浅解排序算法

排序算法是计算机科学中的基础算法,用于将数据按特定规则排列。根据性能和应用场景可分为三类:1)基础排序(O(n²))如冒泡、插入排序,适合小数据量或接近有序的数据;2)高级排序(O(nlogn))如快速、归并和堆排序,适合中等规模数据,其中快排平均性能最优,归并稳定但需额外空间;3)非比较排序(O(n))如计数、桶和基数排序,适用于特定范围或分布均匀的数据。选择算法需综合考虑数据规模、特征(如是否重复)、内存限制及稳定性要求。

youngerwang的博客 1151

常见排序算法详解

排序是我们在日常生活和工作中常见的一种操作。在计算机科学中,排序算法就是将一串或一组数据按照特定的顺序进行排列的算法。这些顺序可能是数字的升序或降序,也可能是字母或字词的字母顺序等。我们将探讨几种不同的排序算法,包括他们的原理、优缺点以及代码实现。常见的排序算法包括:冒泡排序、快速排序、插入排序、选择排序、希尔排序、归并排序、堆排序、基数排序等。这些排序算法中,有些是比较排序,即通过比较元素之间的关系进行排序;

沐雨风栉 875

浅谈经典排序算法系列—各种排序算法总结

排序算法的稳定性定义: 假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,ri=rj,且ri在rj之前,而在排序后的序列中,ri仍在rj之前,则称这种排序算法是稳定的;否则称为不稳定的。 稳定性判定方法: 对于不稳定的排序算法,只要举出一个实例,即可说明它的不稳定性;而对于稳定的排序算法,必须对算法进行分析从而得到稳定的特

Tham 在思索中前行! 1083

排序算法--如何分析、评价一个排序算法的优劣

学习排序算法感觉有种回到高中做数学题的感觉,需要深入的理解这些排序算法,才能真正的掌握它。 如何评价、分析一个排序算法? 一)、排序算法的执行效率 如何来评估排序算法的执行效率呢 1、最好情况、最坏情况、评价情况的时间复杂度 对于要排序的数据,有的接近有序,有的完全无序,而排序数据的有序度会影响算法的执行时间,我们需要知道排序算 法在不同数据下的性能表现 2、时间复杂度的系数、常量、低阶 时间复杂度是随规模n增长的变化趋势。对于规模很小的数据,如...

铭 3147
上一篇: Protobuffer和json深度对比
下一篇: ZeroMQ实例-使用ZMQ(ZeroMQ)进行局域网内网络通信
zero_china
博客等级 码龄16年 10粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值