转自本人知乎文章:https://zhuanlan.zhihu.com/p/30311662

现在,但凡规模大一点的互联网公司招聘软件相关的岗位,都会对数据结构和算法有一定要求。作为非科班出身的程序yuan,要想进好一点的公司,还是老老实实地把基础打扎实吧。

说到排序,大家应该都不陌生,因为你生活中肯定有过网购吧,你在淘宝搜索宝贝的时候,遇到的就是排序,比如有按价格高低排序、按综合排序、按信用高低排序。所以排序算法应该可以说是算法里面很重要的一个分支。

开始之前,先简单介绍一下排序算法的几个重要指标,这里,我尽量用自己理解的傻瓜式方法解读:

(1)稳定性:当序列中存在两个或两个以上的关键字相等的时候,如果排序前序列中r1领先于r2,那么排序后r1如果仍旧领先r2的话,则是稳定的。(相等的元素排序后相对位置不变)

(2)不稳定性:当序列中存在两个或两个以上的关键字相等的时候,如果排序前序列中r1领先于r2,那么排序后r1如果落后r2的话,则是不稳定的。(相等的元素排序后相对位置发生改变)

(3)时间复杂度:算法的时间开销是衡量其好坏的最重要的标志。高效率的算法应该具有更少的比较次数和记录移动次数。

(4)空间复杂度:即执行算法所需要的辅助存储的空间。

一、直接插入排序(插入类)

流程描述:遍历序列中的关键字,每次取一个待排序的关键字,从待排序关键字的前一个关键字逐次向前扫描,如果扫描到的关键字大于待排序关键字,则把扫描到的关键字往后移一个位置。最后找到插入位置,将待排序关键字插入。

void InsertSort(int R[],int n)
{
int i,j
int temp;
for(i=1;i<n;++i){
temp=R[i];   //将待排关键字暂时存放在temp中
j=i-1;      //待排关键字的前一个关键字序号
while(j>=0&&temp<R[j])
//从待排关键字的前一个关键字开始扫描,如果大于待排关键字,则往后移一个位置
  {R[j+1]=R[j];--j; }R[j+1]=temp; //找到插入位置,将temp中暂存的待排关键字插入
 }
}

最坏情况:整个序列是逆序的时候,则内层循环的条件temp<R[j]始终成立,此时对于每一次外层循环,内层循环次数每次达到最大值(即内层循环位i次),外层循环i取值为1~i-1,所以总的执行次数为n(n-1)/2 。

最好情况:整个序列为正序的时候。内层循环条件始终不成立,所以内层循环始终不执行,始终执行语句R[j+1]=temp。所以时间复杂度为O(n)。

空间复杂度:算法所需的辅助存储空间不随待排序列的规模变化而变化,是个常量,所以为O(1)。

二、折半插入排序(插入类)

过程描述:过程同直接插入排序,只是不同于直接插入排序时用顺序查找,这里用的是折半查找。所以折半插入排序在查找过程上比直接插入排序节约不少时间。但是关键字移动次数和直接插入排序一样。

最好情况时间复杂度:

最坏情况时间复杂度:

平均情况时间复杂度:

三、冒泡排序(交换类)

过程描述:通过一系列的交换动作实现排序。首先第一个关键字和第二个关键字比较,如果第一个关键字大,二者交换;然后第二个关键字和第三个关键字比较,如果第二个关键字大,二者交换,否则不交换。一直进行下去,知道最终最大的哪个关键字被交换到了最后,一趟冒泡排序完成。

void BubbleSort(int R[],int n)
{
int i,j,flag;
int temp;
for(i=n-1;i>=1;--i)
{flag=0;    //flag用来标记本趟排序是否发生了交换for(j=1;j<=i;++j){if(R[j-1]>R[j]){temp=R[j];R[j-1]=R[j];R[j]=temp;flag=1;   //flag=1表示本次排序发生了交换
     }  if(flag==0)//如果没有发生交换,说明序列有序,排序结束return;
}
}

最坏情况:序列逆序,此时内层循环if语句的条件始终成立,基本操作执行的次数为n-i。i取值为1~n-1,所以总的执行次数为(n-1+1)(n-1)/2=n(n-1)/2,所以时间复杂度为O(n^2)。

最好情况:序列正序。此时内层循环的条件比较语句始终不成立,不发生交换,内层循环执行n-1次,所以时间复杂度为O(n)。

平均情况:时间复杂度O(n^2)。

四、简单选择排序(选择类)

void SelectSort(int R[],int n)
{
int i,j,k;
int temp;for(i=0;i<n;++i){k=i;for(j=i+1;j<n;++j) //从i后面的序列中挑选一个最小的关键字
    {if(R[k]>R[j])k=j;            //
       temp=R[i];R[i]=R[k];R[k]=temp;}}
}

五、希尔排序(插入类)

过程 描述:重点在增量的选取。如果增量为m,那么将下标为0、m、2m、3m的关键字分成一组,将下标为1、m+1、2m+1、3m+1等关键字分成另外一组,分别对这些组进行插入排序。这就是一趟希尔排序。

六、快速排序(交换类)

过程描述:每一趟选择当前子序列中的一个关键字作为枢轴(一般选择第一个关键字作为枢轴),将子序列中比枢轴小的移到枢轴前面,比枢轴大的移到枢轴后面,本趟交换完成后得到新的更短的子序列,成为下一趟交换的初始序列。一趟排序之后可以确定枢轴的最终位置。比枢轴小的全部在枢轴左边,比枢轴大的全部在枢轴右边。

void QuickSort(int R[],int high,int low)
{
int temp;
int i=low,j=high;
if(low<high)
{
temp=R[low];
while(i!=j){while(j>i&&R[j]>=temp) --j; //从右往左扫描,找到一个小于枢轴temp的关键字if(i<j){R[i]=R[j];  //将右边小于枢轴temp的关键字放在temp的左边++i;       //左边序列号向右移一位
    }while(i<j&&R[i]<temp) ++i;//从左向右扫描,找到一个大于枢轴关键字temp的关键字if(i<j){R[j]=R[i];//将左边大于枢轴temp的关键字放在temp的右边--j;      //右边序号向左移动一位
     }  }R[i]=temp;QuickSort(R,low,i-1);QuickSort(R,i+1,high);}
}

最好情况:时间复杂度为 ,待排序列越接近无序,本算法效率越高。

最坏情况:时间复杂度为  ,待排序列越接近有序,本算法效率越低。

平均情况:时间复杂度  。

空间复杂度:从头到尾只用了temp这一个辅助存储,所以为O(1)。

七、堆排序(选择类)

把堆看成完全二叉树,大根堆---父亲大孩子小;小根堆---父亲小孩子大。

过程描述:整个排序的过程就是不断地将序列调整为堆。

以原始序列:49 38 65 97 76 13 27 49为例,调整为大根堆。

(1)调整97,97>49,不需要调整

(2)调整65,65>13,65>27,不需要调整

(3)调整38,38<97,38<76。需要调整,38和97交换,交换后38成为49的根节点,,继续将38和49交换。

(4)调整49,49<97,49<65,所以49和较大者97交换,交换后,49<76,仍然不满足大根堆,将49与76交换。

八、2路归并排序

void mergeSort(int A[],int low,int high)
{if(low<high){int mid=(low+high)/2;mergeSort(A,low,mid);   //归并排序前半段mergeSort(A,mid+1,high);//归并排序后半段merge(A,low,mid,high);  //把数组中的low到mid  和 mid+1到high的两段有序序列归并成一段有序序列
  }
}

九、基数排序

"多关键字排序",(1)最高位优先(2)最低位优先。例如最高位优先:先按最高位排成若干子序列,再对每个子序列按次高位进行排序。

如下图,低位优先的排序过程:每个桶相当于一个队列,先进先出规则。

最后得到的结果:最高为有序,最高位相同的关键字次高位有序,次高位相同的关键字最低位有序,所以整个序列有序。

转载于:https://www.cnblogs.com/isabelle/p/7720219.html

通俗理解九大排序算法相关推荐

  1. 九大排序算法Java实现

    之前学习数据结构与算法时花了三天时间整理九大排序算法,并采用Java语言来实现,今天第一次写博客,刚好可以把这些东西从总结的文档中拿出来与大家分享一下,同时作为自己以后的备忘录. 1.排序算法时间复杂 ...

  2. c语言折半排序的程序,C语言实现九大排序算法的实例代码

    直接插入排序 将数组分为两个部分,一个是有序部分,一个是无序部分.从无序部分中依次取出元素插入到有序部分中.过程就是遍历有序部分,实现起来比较简单. #include void insertion_s ...

  3. python快速排序算法没看懂_你需要知道的九大排序算法【Python实现】之快速排序...

    五.快速排序 基本思想:  通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分关键字小,则分别对这两部分继续进行排序,直到整个序列有序. 算法实现: ​ #coding: ...

  4. 九大排序算法告诉你什么是内部排序和外部排序

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

  5. 九大排序算法,你会几个?

    概述排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存. 我们这里说说八大排序就是内部排序. 当n较大,则 ...

  6. 九大排序算法-C语言实现及详解

    概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存. 我们这里说说八大排序就是内部排序. 当n较大, ...

  7. 九大排序算法时间复杂度、空间复杂度、稳定性

    排序算法 平均时间复杂度 最坏时间复杂度 最好时间复杂度 空间复杂度 稳定性 冒泡排序 O(n²) O(n²) O(n) O(1) 稳定 直接选择排序 O(n²) O(n²) O(n) O(1) 不稳 ...

  8. (面经总结)一篇文章带你整理面试过程中常考的九大排序算法

    文章目录 一.二分插入排序 1. 原理 2. 代码 二.冒泡排序 1. 原理 2. 代码 三.插入排序算法 1. 原理 2. 代码 四.快速排序算法 1. 原理 2. 代码 五.希尔排序 1. 原理 ...

  9. 九大排序算法之冒泡排序(原理及实现)

    1.算法原理:比较两个相邻的元素,将值大的元素右移. 2.算法思路:首先第一个元素和第二个元素比较,如果第一个大,则二者交换,否则不交换:然后第二个元素和第三个元素比较,如果第二个大,则二者交换,否则 ...

  10. JAVA 九大排序算法

    1.冒泡排序 public class Bobble {private static void sort(int[] arrays) {//一次性读取到高速缓存中,避免cache missint le ...

最新文章

  1. 学习JNI一些基础知识
  2. feign调用第三方接口_讲一个你不知道的事:SringCloud的feign的继承特性
  3. 网络安全技术 —— 防火墙技术基础
  4. DHL全球货运与第四范式达成合作
  5. 用SSD训练自己的数据集
  6. 笔记整理之 SHELL 变量
  7. 给程序员的二十条人生建议
  8. 注解参数获取不到_scm-springboot基于spring boot的统一注解缓存
  9. C语言之预处理探究(三):头文件包含
  10. C语言 pthread_cancelpthread_detach
  11. 关于mysql文件的.frm文件的导入
  12. 光复用技术中三种重要技术_【技术文章】X射线无损检测仪在锂电池行业中的重要应用...
  13. 《Optimized Risk Scores》论文附带代码运行记录
  14. java实现获取当前日期、农历、周
  15. 2019杭电多校6,E.Snowy Smile(线段树维护子段和)
  16. WSTMall微信版
  17. Prometheus为你的SpringBoot应用保驾护航
  18. weinre调试环境搭建
  19. c语言批量修改文件名称,C语言实现批量文档名修改
  20. 毕设论文写作技巧 2021-10-9

热门文章

  1. Windows中MySQL主从数据库搭建(一)
  2. MySQL 字段操作命令
  3. 微服务学习之OpenFeign【Hoxton.SR1版】
  4. SpringCloud和AlibabaCloud区别
  5. java query dsl_java – QueryDsl – 具有字符串值的case表达式
  6. 微型计算机的字长不一定是字节的整数倍数,2015江苏省全国计算机等级考试二级VB笔试试卷及参考答案考试技巧重点...
  7. 留言板删除功能mysql_用PHP写留言板代码时怎样才能实现删除和修改留言的啊?代码是怎样的?...
  8. 给定一个介于0到1之间的实数(如0.625),打印他的二进制表示
  9. qt如何在label中显示汉字_工控机中如何实现多屏显示
  10. pytorch l2正则化_理解机器学习中的 L2 正则化