排序算法 最好情况 最坏情况 平均时间复杂度 空间复杂度 稳定性
选择排序 O(n^2) O(n^2) O(n^2) O(1) 不稳定
冒泡排序 O(n) O(n^2) O(n^2) O(1) 稳定
插入排序 O(n) O(n^2) O(n^2) O(1) 稳定
希尔排序 O(n^(1.3)) O(n^2) O(n^(1.3-2)) O(1) 不稳定
快速排序 O(n*logn) O(n^2) O(n*logn) O(logn) 不稳定

文章目录

  • 一、选择排序
    • 1.1 选择排序基础
    • 1.2 代码演示
    • 1.3 选择排序的复杂度、稳定性以及使用场景
      • 1.3.1 时间复杂度
      • 1.3.2 空间复杂度
      • 1.3.3 排序稳定性
      • 1.3.4 使用场景
  • 二、冒泡排序
    • 2.1 冒泡排序基础
    • 2.2 代码演示
    • 2.3 冒泡排序的复杂度、稳定性以及使用场景
      • 2.3.1 时间复杂度
      • 2.3.2 空间复杂度
      • 2.3.3 排序稳定性
      • 2.3.4 使用场景
  • 三、插入排序
    • 3.1 插入排序基础
    • 3.2 代码演示
    • 3.3 插入排序的复杂度、稳定性以及使用场景
      • 3.3.1 时间复杂度
      • 3.3.2 空间复杂度
      • 3.3.3 排序稳定性
      • 3.3.4 使用场景
  • 四、希尔排序
    • 4.1 希尔排序基础
    • 4.2 代码演示
    • 4.3 希尔排序的复杂度、稳定性以及使用场景
      • 4.3.1时间复杂度
      • 4.3.2 空间复杂度
      • 4.3.3 排序稳定性
      • 4.3.4 使用场景
  • 五、快速排序
    • 5.1 快速排序基础
    • 5.2 代码演示
    • 5.3 快速排序的复杂度、稳定性以及使用场景
      • 5.3.1 时间复杂度
      • 5.3.2 空间复杂度
      • 5.3.3 排序稳定性
      • 5.3.4 使用场景

一、选择排序

1.1 选择排序基础

工作原理:扫描整个列表,找出最小的元素,然后将最小的元素与第一个元素交换位置。接着从第二个位置开始扫描,找出n-1个元素中最小的元素,将其与第二位置上的元素交换位置。如此类推,做n-1次后排序结束。
动画演示过程:

1.2 代码演示

void SelectionSort(int a[],int n){int i,j,temp;for(i = 0;i < n;i++){for(j = i+1;j < n;j++){if(a[j]<a[i]){//如果后面元素的值小于前面的,则进行交换temp = a[j];a[j] = a[i];a[i] = temp;}}
}

1.3 选择排序的复杂度、稳定性以及使用场景

1.3.1 时间复杂度

由上面的代码可以看出,选择排序是在两层循环中进行的。因此,不管是最坏,最好的情况,时间复杂度都是O(n^2)。但是,如果一开始就是升序的,则交换的次数为0,如果是降序的,则交换次数为n-1。(默认结果为升序排序)。

1.3.2 空间复杂度

选择排序完全就是比较和交换数据,只需要一个辅助空间用来存储待比较的元素的下标,并没有消耗更多的额外空间,因此其空间复杂度是O(1)。

1.3.3 排序稳定性

选择排序是一种不稳定的算法,因为如果前后两个元素的值相同,则经过排序后,两者的前后顺序发生变化。
Eg:数组 4、6、4、3、8,在对其进行第一遍循环的时候,会将第一个位置的4与后面的3进行交换。此时,就已经将两个4的相对前后位置改变了。因此选择排序不是稳定性排序算法。

1.3.4 使用场景

待排序序列中,元素个数较少时

二、冒泡排序

2.1 冒泡排序基础

工作原理:比较相邻的元素,将大的元素交换到右边的位置,重复多次后,最大的元素就“沉淀”到列表的最后一个位置。第二遍将第二大元素沉淀下去,n-1次后结束。
动画演示过程:

2.2 代码演示

void BubbleSort(int a[],int n){int i,j,temp;for(i = 1;i <= n-1; i++) {//若有n个数,则交换的次数是n-1;for(j = 0;j <= n-i;j++){if(a[j] > a[j+1]){temp = a[j];//如果左边的数大于右边的,则交换a[j]和a[j+1]的位置 a[j] = a[j+1];a[j+1] = temp;}}}
}

2.3 冒泡排序的复杂度、稳定性以及使用场景

2.3.1 时间复杂度

默认结果为升序
(1)如果一开始就是升序排列,一趟扫描即可完成排序。所需的关键字比较次数C和交换次数M均达到最小值:
C(min) = n-1;M(min) = 0
因此,冒泡排序在最好情况下的时间复杂度为O(n)。

(2)如果一开始是降序排列,需要进行n-1趟排序。每趟排序要进行n-i次关键字的比较(1≤i≤n-1),且每次比较都必须移动记录三次来达到交换记录位置。在这种情况下,比较和交换次数均达到最大值:
C(max) = 1+2+…+(n-1)=n*(n-1)/2
M(max)= 3n(n-1)/2
因此,冒泡排序在最坏情况下的时间复杂度为O(n^2)。

2.3.2 空间复杂度

冒泡排序完全就是比较和交换数据,只需要一个辅助空间用来存储待比较的元素的下标,并没有消耗更多的额外空间,因此其空间复杂度是O(1)。

2.3.3 排序稳定性

在冒泡排序中,遇到相等的值,是不进行交换的,只有遇到不相等的值才进行交换,所以是稳定的排序方式。

2.3.4 使用场景

待排序序列中,元素个数较少时

三、插入排序

3.1 插入排序基础

工作原理:先假定第一个为有序数列,后面的为无序数列,然后从第二个元素开始,插入到前面的有序数列中,直到所有元素都插入进去为止。
动画演示过程:

3.2 代码演示

void InsertSort(int a[],int n){int i,j,temp;for(i = 1;i < n;i++){if(a[i] < a[i-1]){j = i-1;//先标记现在的位置temp = a[i];while(j >= 0&&temp < a[j]){a[j+1] = a[j];j--;}a[j+1] = temp;//将待排序元素插入数组中}}
}

3.3 插入排序的复杂度、稳定性以及使用场景

3.3.1 时间复杂度

默认结果为升序排列
(1)如果一开始的时候就是升序排序的话,只需要当前的数与前面一个数作比较就行了,这时一共需要n-1次,时间复杂度为O(n)。
因此,插入排序在最好的情况下的时间复杂度为O(n)。

(2)如果一开始的时候是降序排序的话,总次数为1+2+3+…+n-1 = n*(n-1)/2。
因此,插入排序在最坏的情况下的时间复杂度为O(n^2)。

(3)平均情况是,右半区每一个数,都和一半的左半区的数比较。总次数为1/2 + 2/2 + 3/2 + … + ( n - 1 )/2 = O(n^2)。
因此,插入排序在的平均时间复杂度为O(n^2)。

3.3.2 空间复杂度

插入排序完全就是比较和交换数据,只需要一个辅助空间用来存储待比较的元素的下标,并没有消耗更多的额外空间,因此其空间复杂度是O(1)。

3.3.3 排序稳定性

在使用插入排序时,元素从无序部分移动到有序部分时,必须是不相等(大于或小于)时才会移动,相等时不处理,所以插入排序是稳定的。

3.3.4 使用场景

待排序序列的元素个数不多,且元素基本有序。

四、希尔排序

4.1 希尔排序基础

工作原理:希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序。它与插入排序的不同之处在于,它会优先比较距离较远的元素,间隔慢慢减成1,插入排序的间隔一直就是1希尔排序又叫缩小增量排序
动画演示过程:

4.2 代码演示

void ShellSort(int a[],int n){int i,j,temp;int gap = n/2;//先让比较的间距为n/2;while(gap > 0){for(i = gap;i < n;i++){if(a[i - gap] > a[i]){//与直接插入排序差不多的思路,只是间距逐渐减小temp = a[i];j = i -gap;while(j >= 0&&a[j]>temp){a[j+gap] = a[j];j -= gap;}a[j+gap] = temp;}}gap /= 2;}
}

4.3 希尔排序的复杂度、稳定性以及使用场景

4.3.1时间复杂度

(1)最好情况:T(n) = O(n^1.3)
(2)最坏情况:T(n) = O(n^2)
(3)平均情况:T(n) =O(n^(1.3-2))[:与所分的序列有关]

4.3.2 空间复杂度

希尔排序完全就是比较和交换数据,只需要一个辅助空间用来存储待比较的元素的下标,并没有消耗更多的额外空间,因此其空间复杂度是O(1)。

4.3.3 排序稳定性

希尔排序是直接插入排序的优化版,在排序过程中,会根据间隔将一个序列划分为不同的逻辑分组,在不同的逻辑分组中,有可能将相同元素的相对位置改变。如[2,2,4,1],按间隔为2,降序排序,前两个元素的相对位置就会改变。
因此,希尔排序是不稳定的排序方式。

4.3.4 使用场景

待排序序列元素较少时。

五、快速排序

5.1 快速排序基础

工作原理:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序(在这里用到递归思想),以达到整个序列有序。
动画演示过程:

5.2 代码演示

void QuickSort(int* a,int n)
{int i,j;int pivot = a[0];//让第一个数为基准i =0;j = n-1;while (i < j){while(i <j&&a[j] > pivot){j--;}if (i < j){a[i] = a[j];i++;}while (i < j&&a[i] <= pivot){i++;}if (i <j){a[j] = a[i];j--;}}a[i] = pivot;//此时i == j; if (i > 1){quicksort(a,i) ;//左递归 }if (n-i-1>1){quicksort(a+i+1,n-i-1);//右递归 }
}

5.3 快速排序的复杂度、稳定性以及使用场景

5.3.1 时间复杂度

快速排序涉及到递归调用,所以快速排序的时间复杂度需要从递归算法的复杂度说起。
递归算法的时间复杂度为:T(n) = aT[n/b]+f(n)。
(1)最好情况就是每一次取到的元素都刚好平分整个数组
此时,时间复杂度为:T(n) = 2T[n/2]+f(n)
下面来推算下,在最优的情况下快速排序时间复杂度的计算(用迭代法):
T[n] = 2T[n/2] + n ----------------第一次递归
令:n = n/2 = 2 { 2 T[n/4] + (n/2) } + n ----------------第二次递归
= 2^2 T[ n/ (2^2) ] + 2n
令:n = n/( 2^(m-1) ) = 2^m T[1] + mn ----------------第m次递归(m次后结束)
当最后平分的不能再平分时,也就是说把公式一直往下跌倒,到最后得到T[1]时,说明这个公式已经迭代完了(T[1]是常量了)。 .
得到:T[n/ (2^m) ] = T[1] ===>> n = 2^m ====>> m = logn;
T[n] = 2^m T[1] + mn ;其中m = logn;
T[n] = 2^(logn) T[1] + nlogn = n T[1] + nlogn = n + nlogn ;其中n为元素个数
又因为当n >= 2时:nlogn >= n (也就是logn > 1),所以取后面的 nlogn;
因此,快速排序最好的情况下时间复杂度为:O(nlogn)。

(2)最差情况就是每一次取到的元素就是数组中最小/最大的,这种情况其实就是冒泡排序了(每一次都排好一个元素的顺序)
因此,快速排序最差的情况下时间复杂度为:O(n^2)。

(3)平均时间复杂度:从最好情况的分析中可知,快速排序的最好情况就是按平均来的
因此,快速排序的平均时间复杂度等于最好情况下的时间复杂度,也为:O(nlogn)。

5.3.2 空间复杂度

快速排序使用的空间是O(1)的,也就是个常数级;而真正消耗空间的就是递归调用了,因为每次递归就要保持一些数据,其空间复杂度为O(logn)。

5.3.3 排序稳定性

在快速排序中,每一趟排序都需要选择pivot(基准)。此时,基准两边可能出现和基准元素相同的值。如序列[1,5,2,4,5,4,6,5],如果选择了a[4]作为基准因子,那么a[1]和a[7]势必会被分到基准因子的同一侧,序列的稳定性被破坏。所以,快速排序是一种不稳定的排序算法。

5.3.4 使用场景

待排序序列元素较多,并且元素较无序

十大排序算法笔记(C语言)(一)选择排序、冒泡排序、插入排序、希尔排序、快速排序相关推荐

  1. 数据挖掘十大经典算法笔记

    主要总结一下数据挖掘十大经典算法,包括各自优缺点, 适用数据场景,做个小笔记,分享一下 数据挖掘主要分为分类算法,聚类算法和关联规则三大类,这三类基本上涵盖了目前商业市场对算法的所有需求.而这三类里又 ...

  2. python 按条件选择行和列数据_小白学数据结构-排序算法Python(冒泡、选择、快速、希尔等等)...

    排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存. 我们通常所说的排序算法往往指的是内部排序算法,即数据 ...

  3. JavaScript 几种排序算法实现(冒泡、选择、插入、归并、快速排序)

    1. 冒泡 // 冒泡 - 每次循环, 将两两中偏大的元素移动到右边 for (let i = 0; i < arr.length - 1; i++) {for (let j = i; j &l ...

  4. 常见排序算法(C语言实现)

    常见排序算法(C语言实现) 文章目录 常见排序算法(C语言实现) 一.插入排序 二.希尔排序 三.选择排序 四.堆排序 五.冒泡排序 六.快速排序 七.归并排序 一.插入排序 void insertS ...

  5. c语言动画原理,动画详解十大经典排序算法(C语言版)

    排序算法是程序员必备的基础知识,弄明白它们的原理和实现很有必要.本文中将通过非常细节的动画展示出算法的原理,配合代码更容易理解. 概述 由于待排序的元素数量不同,使得排序过程中涉及的存储器不同,可将排 ...

  6. C语言——十四种内部排序算法【直接插入排序-冒泡排序-选择排序-插入排序-希尔排序-归并排序-快速排序-堆排序-折半插入排序-二分查找-路插入排序-表插入排序-简单选择排序-直接选择排序-树形选择】

    目录: 一:插入排序 A:直接插入排序 1.定义: 2.算法演示 实例1: 3.基本思想 4.排序流程图 实例1: B:希尔排序 1.定义: 2.算法演示 实例2: C:其他插入排序 a:折半插入排序 ...

  7. JS的十大经典算法排序

    更正(2018/5/31):如果看的是原文章的话,注意希尔排序少一个等号,在本博中,我已经添加上了,希尔排序(更正后)及以前的经测试都是正确的,后面的我正找时间持续研究验证中--(过程可能有点慢) 更 ...

  8. 经典十大排序算法(含升序降序,基数排序含负数排序)【Java版完整代码】【建议收藏系列】

    经典十大排序算法[Java版完整代码] 写在前面的话 十大排序算法对比 冒泡排序 快速排序 直接选择排序 堆排序 归并排序 插入排序 希尔排序 计数排序 桶排序 基数排序 完整测试类 写在前面的话   ...

  9. 决策树C4.5算法 c语言实现,数据挖掘十大经典算法(1) C4.5_决策树算法

    数据挖掘十大经典算法(1) C4.5_决策树算法 机器学习中,决策树是一个预测模型:他代表的是对象属性与对象值之间的一种映射关系.树中每个节点表示某个对象,而每个分叉路径则代表的某个可能的属性值,而每 ...

  10. 十大经典算法总结(JavaScript描述)

    前言 读者自行尝试可以想看源码戳这,博主在github建了个库,欢迎star.读者可以Clone下来本地尝试.此博文配合源码体验更棒哦~~~ 个人博客:Damonare的个人博客 原文地址:十大经典算 ...

最新文章

  1. Cocos2d-x 3.0正式版及android环境搭建
  2. 2019 年如何在 CentOS 7 上安装最新版 Nginx
  3. 一键移植工具_让UI设计畅通无阻 — 信息系统人机界面增强工具(HFE Designer)
  4. spring源码分析-core.io包里面的类
  5. Java 文件操作二(重命名、设置只读、是否存在、指定目录中创建文件、获取文件修改日期、创建文件、文件路径比较)
  6. 零基础小白学习UI设计的4个步骤
  7. 集中器到服务器传输协议,集中器130通讯协议(捷先数码).doc
  8. Cpdetector编码识别
  9. ElasticSearch学习笔记(二)
  10. 网卡bonding配置
  11. [译]Chipmunk教程 - 5 跟踪球体的运动
  12. 数值分析第八章知识点总结——常微分方程数值解法
  13. Unity3d iOS 内购详细流程总汇
  14. 产品经理面试,设计攻略
  15. 安装光盘并重新启动计算机戴尔,戴尔电脑怎么设置光盘启动
  16. ShenYu 网关源码学习(1)- 简单介绍、编译和测试
  17. 基于react+antd的后台管理模板
  18. python绘制小提琴图_Python:matplotlib 和 Seaborn 之热图、小提琴图和箱线图 (三十四)...
  19. GAN (Generative Adversarial Nets 生成对抗网络)
  20. matlab中函数参数和变量作用域

热门文章

  1. 带你玩转Visual Studio——Property Manager的配制
  2. puppet自动化部署
  3. 一个因全局变量引发的故事!
  4. 编译小程序,开发者工具打开报错Cannot read property ‘createTextNode‘ of undefined或iphone机型无法预览
  5. springboot 微信支付接口
  6. SpCL阅读笔记:Self-paced Contrastive Learning with Hybrid Memory for Domain Adaptive Object Re-ID
  7. Windows系统下通过文件路径进入相应DOS界面
  8. PHP获取以毫秒级为单位获取当前时间
  9. 愿以三生烟火,换君一世迷离
  10. C. Minimum Ties