目录

一.冒泡排序

二.选择排序

三.插入排序

四.希尔排序

五.堆排序

六.快速排序

七.归并排序

 八.基数排序

 九.总结


一.冒泡排序

1.冒泡排序

冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端。

2.算法步骤

  • 比较相邻的元素。如果第一个比第二个大,就交换他们两个。

  • 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。

  • 针对所有的元素重复以上的步骤,除了最后一个。

  • 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

3.稳定性:稳定

4.时间复杂度:O(n^2)(平均时间复杂度)

5.空间复杂度:O(1)

6.动态图演示:

7.code

void BubbleSort(int *arr,int len)//len代表要排序数组的长度
{for(int i=0;i<len-1;i++){int flag=0;for(int j=0;j<len-1-i;j++){if(arr[j]>arr[j+1]{int tmp = arr[j];arr[j]=arr[j+1];arr[j+1]=tmp;flag=1;}}if(flag == 0){break;}}
}

二.选择排序

1.选择排序

第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。

2.算法步骤

  • 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。

  • 再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。

  • 重复第二步,直到所有元素均排序完毕。

3.稳定性:不稳定

4.时间复杂度:O(n^2)(平均时间复杂度)

5.空间复杂度:O(1)

6.动态图演示:

7.code:

void SelectSort(int *arr,int len)
{for(int i=0;i<len-1;++i){int min = i;for(int j=i+1;j<len;++j){if(arr[j]<arr[min]){min=j;}}int tmp = arr[min];arr[min]=arr[i];arr[i]=tmp;}
}

三.插入排序

1.插入排序

每步将一个待排序的记录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。

2.算法步骤

  • 将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)

3.稳定性:稳定

4.时间复杂度:O(n^2)(平均时间复杂度)

5.空间复杂度:O(1)

6.动态图演示:

7.code:

void InsertSort(int *arr,int len)
{int i;int j;for(int i=1;i<len;++i){int tmp = arr[i];for(j =i-1;j>=0 && arr[j]>tmp;--j){arr[j+1] = arr[j];}arr[j+1] = tmp;}
}

四.希尔排序

1.希尔排序

希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。希尔排序是基于插入排序的以下两点性质而提出改进方法的:

  • 插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率;
  • 但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位;

希尔排序的基本思想是:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录"基本有序"时,再对全体记录进行依次直接插入排序。

2.算法步骤

  • 选择一个增量序列 t1,t2,……,tk,其中 ti > tj, tk = 1;

  • 按增量序列个数 k,对序列进行 k 趟排序;

  • 每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序。仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。

  • 注意:最后一个增量必须为1

3.稳定性:不稳定

4.时间复杂度:O(nlog n)(平均时间复杂度)

5.空间复杂度:O(1)

6.动态图演示:

数据结构排序算法之希尔排序演示_哔哩哔哩_bilibili

7.code

void ShellSort(int* arr, int len)
{int i;int j;int temp;int gap = len / 2;while (gap > 0){for (i = gap; i < len; i++){temp = arr[i];for (j = i - gap; j >= 0 && arr[j] > temp; j -= gap){arr[j + gap] = arr[j];}arr[j + gap] = temp;}gap /= 2;}
}

五.堆排序

1.堆排序

堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。堆排序可以说是一种利用堆的概念来排序的选择排序。分为两种方法:

  • 大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列;
  • 小顶堆:每个节点的值都小于或等于其子节点的值,在堆排序算法中用于降序排列;

2.算法步骤

  1. 创建一个堆 H[0……n-1];

  2. 把堆首(最大值)和堆尾互换;

  3. 把堆的尺寸缩小 1,并调用 shift_down(0),目的是把新的数组顶端数据调整到相应位置;

  4. 重复步骤 2,直到堆的尺寸为 1。

3.稳定性:不稳定

4.时间复杂度:O(nlogn)(平均时间复杂度)

5.空间复杂度:O(1)

6.动态图演示:

7.code

void OneAdjust(int *arr,int len,int root)
{int i = root;int tmp = arr[i];//此时的tmp的值为此时根节点的值int j = 2 * i + 1;//左孩子while (j < len){if (j + 1 < len && arr[j] < arr[j + 1]){j = j + 1;}//此时j就是左右孩子中较大的那一个if (arr[j] > tmp){arr[i] = arr[j];//形成大堆根i = j;//下一个子树的根j = 2 * i + 1;//下一个子树的左孩子}else{break;}}arr[i] = tmp;
}
void CreateHeap(int* arr, int len)//创建堆
{int root = len / 2 - 1;//最后一个叶子节点的父节点for (; root >= 0; root--){OneAdjust(arr, len, root);}
}void HeapSort(int* arr, int len)
{int t;CreateHeap(arr, len);for (int i = 0; i < len - 1; i++){t = arr[0];arr[0] = arr[len - 1 - i];arr[len - 1 - i] = t;OneAdjust(arr, len - i - 1, 0);}
}

六.快速排序

1.快速排序

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

2.算法步骤

  1. 从数列中挑出一个元素,称为 "基准"(pivot);

  2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;

  3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;

3.稳定性:不稳定

4.时间复杂度:O(nlogn)(平均时间复杂度)

5.空间复杂度:O(logn)

6.动态图演示:

数据结构排序算法之快速排序演示_哔哩哔哩_bilibili

7.code

void QuickSort(int* a, int left, int right)
//left是最左边的下标
//right是最右边的下标
{if (left >=right){return;}int i = left;int j = right;int temp = a[left];//基准数//排除特殊情况while (i != j){while (a[j] >= temp && i < j){j--;//继续向右寻找比基准数小的数,直到找到为止,或者i与j相遇}while (a[i] <= temp && i < j){i++;//继续向右寻找比基准数大的数,直到找到为止,或者i与j相遇}if (i < j)//此时小于和大于基准数都已被找到,且i与j没有相遇{int t = a[i];a[i] = a[j];a[j] = t;}}//此时i已经与j相遇,a[left] = a[i];//将相遇位置的那个数放到最左边a[i] = temp;//将基准数放到最中间,即相遇的位置//此时基准数将数组分割为两组,基准数之前的数都小于它,后边的都大于它//然后分别对基准数两侧的两组数再次进行快排QuickSort(a,left, i - 1);QuickSort(a,i + 1, right);
}

七.归并排序

1.归并排序

归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。

作为一种典型的分而治之思想的算法应用,归并排序的实现由两种方法:

  • 自上而下的递归(所有递归的方法都可以用迭代重写,所以就有了第 2 种方法);
  • 自下而上的迭代;

 2.算法步骤

  1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;

  2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置;

  3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;

  4. 重复步骤 3 直到某一指针达到序列尾;

  5. 将另一序列剩下的所有元素直接复制到合并序列尾。

3.稳定性:稳定

4.时间复杂度:O(nlogn)(平均时间复杂度)

5.空间复杂度:O(n)

6.动态图演示:

7.code

void Meger(int* arr, int left,int right)
{int* temp = (int*)malloc(sizeof(int) *(right-left+1));int middle = (right+left) / 2;int i = left;int j = middle + 1;int t = 0;while (i <= middle && j <=right){if (arr[i] <= arr[j])       temp[t++] = arr[i++];else{temp[t++] = arr[j++];}}while (i <= middle){temp[t++] = arr[i++];}while (j <= right){temp[t++] = arr[j++];}for (i = 0; i < t; i++){arr[left+i] = temp[i];}free(temp);
}void MegerSort(int* arr, int left,int right)
{if (left<right){int middle = (left+right) / 2;MegerSort(arr,left,middle);MegerSort(arr, middle + 1, right);Meger(arr, left, right);}
}

八.基数排序

1.基数排序

基数排序是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数,所以基数排序也不是只能使用于整数。

2.算法步骤

  1. 创建队列
  2. 先求最大数字的位数
  3. 求出相应位数的值, 并根据位数值将其存储相应的队列中
  4. 按顺序输出所有队列中的值,  循环处理3,4步,循环次数由第一步算出

3.稳定性: 稳定

4.时间复杂度:O(n x k)(平均时间复杂度)

5.空间复杂度:O(n+k)

6.动态图演示:

7.code

void RadixSort(int *arr, int len)
{queue que[10];for (int i = 0; i < 10; ++i){que[i].data = (int*)malloc(sizeof(int)* len);assert(que[i].data != NULL);que[i].head = que[i].tail = 0;}int width = GetMaxWidth(arr, len); // O(n)for (int i = 0; i < width; ++i)  // O(d * n){//  将数组中所有的数字取其相应位数的值,并将其存储到相应的队列中for (int j = 0; j < len; ++j){int  num = GetNumOfWidth(arr[j], i);que[num].data[que[num].tail++] = arr[j];}int k = 0;for (int m = 0; m < 10; ++m){while (que[m].head != que[m].tail){arr[k++] = que[m].data[que[m].head++];}}for (int n = 0; n < 10; ++n){que[n].head = que[n].tail = 0;}}for (int i = 0; i < 10; ++i){free(que[i].data);}
}

8.基数排序 vs 计数排序 vs 桶排序

基数排序有两种方法:

这三种排序算法都利用了桶的概念,但对桶的使用方法上有明显差异:

  • 基数排序:根据键值的每位数字来分配桶;
  • 计数排序:每个桶只存储单一键值;
  • 桶排序:每个桶存储一定范围的数值;

九.总结

参考博客:1.0 十大经典排序算法 | 菜鸟教程

 注意:本文没有讲述红框中的两个排序算法。

算法 | 八大排序算法,含动态图详解相关推荐

  1. 算法之高精度(含实例与详解)C语言

    一.什么是高精度 高精度本质上是一种计算,由于int型和long long型的存储的数据大小有限.在有符号定义的情况下,int型为2的31次方减1:在无符号定义的情况下,lint型为2的32次方.因此 ...

  2. 八大排序算法(理论和动态图)

    八大排序算法 一.冒泡排序 二.选择排序 三.快速排序 四.归并排序 五.堆排序 六.直接插入排序 七.希尔排序 八.基数排序 排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或 递减的排 ...

  3. DL之CNN:卷积神经网络算法简介之原理简介(步幅/填充/特征图)、七大层级结构(动态图详解卷积/池化+方块法理解卷积运算)、CNN各层作用及其可视化等之详细攻略

    DL之CNN:卷积神经网络算法简介之原理简介(步幅/填充/特征图).七大层级结构(动态图详解卷积/池化+方块法理解卷积运算).CNN各层作用及其可视化等之详细攻略 目录 CNN 的层级结构及相关概念 ...

  4. C语言八大排序算法,附动图和详细代码解释!

    文章来源:电子工程专辑.C语言与程序设计.竹雨听闲 一.前言 如果说各种编程语言是程序员的招式,那么数据结构和算法就相当于程序员的内功. 想写出精炼.优秀的代码,不通过不断的锤炼,是很难做到的. 二. ...

  5. 硬核!C语言八大排序算法,附动图和详细代码解释!

    来源 :C语言与程序设计.竹雨听闲等 一 前言 如果说各种编程语言是程序员的招式,那么数据结构和算法就相当于程序员的内功. 想写出精炼.优秀的代码,不通过不断的锤炼,是很难做到的. 二 八大排序算法 ...

  6. 算法 经典的八大排序算法详解和代码实现

    算法 经典的八大排序算法详解和代码实现 排序算法的介绍 排序的分类 算法的时间复杂度 时间频度 示例 图表理解时间复杂度的特点 时间复杂度 常见的时间复杂度 空间复杂度 排序算法的时间复杂度 冒泡排序 ...

  7. 八大排序算法——(万字图文详解)

    本篇文章是我对之前写过的八个排序算法的总结,感兴趣的小伙伴可以去我的八大排序算法专栏浏览,也可以点击下方标题跳转. 提示:本篇博客篇幅较长,建议小伙伴们查看目录,按需浏览 目录 正文 1 直接插入排序 ...

  8. 图解八大排序算法——我见过的最详细的讲解(转)

    一.分类 1.内部排序和外部排序 内部排序:待排序记录存放在计算机随机存储器中(说简单点,就是内存)进行的排序过程. 外部排序:待排序记录的数量很大,以致于内存不能一次容纳全部记录,所以在排序过程中需 ...

  9. 数据结构算法---八大排序

    目录 冒泡排序 插入排序 希尔排序 选择排序 堆排序 计数排序 归并排序 快速排序 源码 一般使用的八大排序算法是:插入排序.选择排序.冒泡排序.希尔排序.归并排序.快速排序.堆排序.计数排序.   ...

  10. python 排序算法 简书_Python---简析八大排序算法

    前言 1 .排序的概念 排序是计算机内经常进行的一种操作,其目的是将一组"无序"的记录序列调整为"有序"的记录序列. 排序分为内部排序和外部排序. 若整个排序过 ...

最新文章

  1. python流程控制-详解Python流程控制语句
  2. 【错误记录】p7zip 交叉编译 Android 版本 NDK 报错 ( error: case value evaluates to -2 , which cannot be narrowed )
  3. linux shell 字符串 数组,bash shell函数返回数组字符串
  4. 蓄电池维护中的几大误区
  5. 虚拟化技术简介--CPU/内存/IO/网络虚拟化介绍
  6. ForkJoinPool分支合并框架计算加法
  7. iOS - 正则表达式判断邮箱、身份证..是否正确
  8. 二、语音合成(TTS)
  9. php集成环境总结(php新手)
  10. 网站搭建niushop系统,全面搭建,打包app,h5详细教程
  11. Swift游戏实战-跑酷熊猫 14 熊猫打滚
  12. MySQL数据库的完美卸载
  13. 安卓毕业设计源码基于Uniapp+SSM实现的校园心理健康APP
  14. DFX:面向产品生命周期的设计
  15. excel不均匀坐标轴_将Excel图表的纵坐标轴设置成不等间距的2种方法
  16. 《Java并发编程的艺术》——Java中的并发工具类、线程池、Execute框架(笔记)
  17. 如何将证件照的休闲装变职业装
  18. python音标1003python音标_python selenium 爬取百度翻译单词音标
  19. CF-Watermelon
  20. 小程序团购商品CPS接入,实现达人分佣模式

热门文章

  1. 智慧城市大数据运营中心,发挥大数据价值
  2. matlab的yalmip为什么这么慢,Yalmip使用学习
  3. jspstudy启动mysql失败_JspStudy软件快速本地部署JDK+tomcat+Apache+mysql环境
  4. react小书 笔记6
  5. PHP开发环境准备,PHPWAMP使用,图文教程
  6. Irrlicht引擎源码剖析——第十三天
  7. 8uftp链接linux,8UFTP工具,FTP工具连接的办法,配置方式
  8. 计算机材料学常用计算软件,计算机在材料科学中的应用-用MaterialsStudio计算简单材料的能带.doc...
  9. 阮一峰ES6学习-Symbol
  10. js设置cookie,包含多个name