常用排序算法及动画演示

(一)插入排序
插入排序可形象理解为打扑克时理牌的一个过程,具体分为直接插入、折半插入排序、希尔排序三种;
①直接插入排序

void InsertSort(int a[],int n)  //n为数据的个数
{int i,j,temp;  //i作为已排序好的元素的下标,j存放进行比较的元素的下标for(i=0;i<n-1;i++){temp=a[i+1]; //temp把要排序的数据元素暂时存放j=i;while(j>-1&&temp<a[j])  {a[j+1]=a[j];j--;  //若能一直找到比temp大的数则j一直往前移,直到找到比temp小的数或者已经到了数组的最前端为止}a[j+1]=temp; //当没进入循环,j没j--时,a[j+1]=a[i+1]=temp,不移动//当退出循环,j--时,a[j+1]的位置为temp值须插入的位置}
}

直接插入算法动画演示:

视频引自bilibili up主 太_傅

注:视频中的开始位置为i=1,上文中的开始位置为i=0,区别如下方所示

void InsertSort(int a[],int n)
{int i,j,temp;  for(i=1;i<n;i++)  //从i=1开始{temp=a[i+1]; j=i-1;    //j=i-1;while(j>-1&&temp<a[j])  {a[j+1]=a[j];j--;  }a[j+1]=temp; }
}

②折半插入排序算法
折半插入排序利用二分法来进行查找插入位置,然后依次向后集体移动数据元素,从而插入待插数据;

void BInsertSort(int a[],int n,int x)//x为待插入元素
{int mid;int low=0; //最左边int high=n-1; //最右边int i;//step1.利用二分法查找插入位置while(high>=low){mid=(high+low)/2;if(x>=a[mid])  {low=mid+1; //如果x比a[mid]大,往右边查找}else   //x<a[mid]{high=mid-1;  //往左边查找}}//step2.插入待插元素for(i=n-1;i>=a[high+1];i--)  //从后开始挪动{a[i+1]=a[i];}a[high+1]=x; //插入
}

③希尔排序算法
希尔排序是在分组概念上的直接插入排序
希尔排序算法的核心思想是将需要进行排序的数据按一定规则分成若干个小组,每次对小组左右两边的数进行对比,将较小的数移至前方(升序),移动完后,边缘下标+1,循环完一轮后,将所选的k值除以2再次对数据进行分组,重复上述操作,直至将数据排序完成。

void ShellSort(int a[],int n)
{int i,j,temp;  //i代表右端,j代表左端,temp存放右端数据int k=n/2;while(k>0){for(i=k;i<n;i++)  {temp=a[i];j=i-k;//利用直接插入排序进行排序while(j>=0&&temp<a[j])  //循环条件是原始右端数据小于当前左端数据{a[j+k]=a[j]; //交换j=j-k;  //左移}a[j+k]=temp;  //跳跃式交换}k=k/2;  //重新分组,继续循环操作}
}

希尔排序算法的动画演示:

视频引自bilibili up主 太_傅

(二)选择排序
①直接选择排序算法
直接选择排序的基本思想是每次从待排序的数据元素集合中选取一个最小或最大的数据元素放到数据元素集合的最前端

void SelectSort(int a[],int n)
{int i,j;int min,temp;  //min标记最小数据的下标,temp存储最小数据元素的值for(i=0;i<n-1;i++){min=i;  //初始化for(j=i;j<n;j++){if(a[j]<a[i]){min=j;}//交换最小数据元素if(min!=i){temp=a[j];a[j]=a[i];a[i]=temp;}}}
}

直接选择排序动画演示:

视频引自bilibili up主 太_傅

②堆排序算法
堆排序算法是基于完全二叉树的一种排序方式
堆的定义:
堆分为最大堆和最小堆(又称为大根堆/大顶堆,小根堆/小顶堆),最大堆是指所有的非叶子结点小于对应的子树的根的堆,最小堆则与此相反。如下图就是一个最大堆

创建堆代码算法:

void CreatHeap(int a[],int n,int h)
{//调整非叶结点a[h]使之满足最大堆,n为数组a的元素个数int i,j,flag;int temp;i=h;j=2*i+1;temp=a[i];flag=0;//沿左右孩子中值较大者重复向下筛选while(j<n&&flag!=1){//寻找左右孩子结点中的较大者,j为其下标if(j<n-1&&a[j]<a[j+1]){j++;  //移动到另一个子堆}if(temp>a[j])  //a[i]>a[j]{flag=1;   //标记结束筛选条件}else    //否则把a[j]上移{a[i]=a[j];i=j;j=2*i+1;}}//把最初的a[i]赋予最后的a[j];
}

初始化最大堆:
利用上述CreatHeap(a,n,h)函数,初始化创建最大堆的过程就是从第一个非叶结点a[h](h=(n-2)/2)开始,到根结点a[0]为止,循环调用该函数,初始化创建最大堆。
代码如下:

void InitCreatHeap(int a[],int n)
{//把a[0]-a[n-1]初始化为最大堆int i;for(i=(n-2)/2;i>=0;i--)  //i是非叶结点的下标;{CreatHeap(a,n,i);  //创建最大堆;}
}

【堆排序基本思想】:
①首先把n个元素的数组a初始化创建为一个最大堆
②把最大堆的根a[0]和当前最大堆的最后一个元素交换
③最大堆元素个数减1
④由于第①步后根结点不再满足最大堆的定义,依次需要重新调整一个新的根结点,使之满足最大堆的定义
实现代码如下:

void HeapSort(int a[],int n)
{int i;int temp;InitCreatHeap(a,n);for(i=n-1;i>0;i--)  //从当前最大堆元素个数开始依次递减,直到最大堆变为一个已排序好的数组;{//把堆顶a[0]元素和当前最大堆的最后一个元素交换;temp=a[0];a[0]=a[i];a[i]=temp;CreatHeap(a,n,0);  //调整根结点满足最大堆;//注意:此时子二叉树根结点下标为0,子二叉树结点个数为i;}
}

堆排序算法动画演示:

视频引自bilibili up主 太_傅

(三)交换排序
利用交换数据元素的位置进行排序的方法称作尉交换排序。常用的交换排序方法有冒泡排序和快速排序。其中,快速排序是一种分区交换排序方法。
①冒泡排序

void BubbleSort(int a[],int n)
{int i,j,flag;int temp;for(i=0;i<n-1&&flag==1;i++){flag=0;for(j=0;j<n;j++){if(a[j]<a[j+1])   //交换两个元素{flag=1;    //flag=1表示进行过交换,若flag!=1,说明已经排序好了,可提前结束排序temp=a[j];a[j]=a[j+1];a[j+1]=temp;}}}
}

注:上述算法中的flag,用于标记本次交换排序过程是否有交换动作。若本次交换过程没有交换动作,即本次交换排序过程后flag不等于1,则说明数据元素集合已经全部排好序,可提前结束排序过程。
②快速排序算法
快速排序法是冒泡排序法的改进,它的基本思想是在需要排序的数组中选定一个basic值作为基准点,对左右端分别进行扫描,然后将小于基准点的值放在基准点左侧,大于基准点的值放在基准点的右侧。最后对左右端子集合进行递归排序,最终得到排序好的数组。

void QuickSort(int a[],int left,int right)
{int i=left,j=right;int basic=a[left];  //取第一个数据为基准点while(i<j)    //进行一次排序的条件是i<j{while(i<j&&basic<=a[j]) j--;  //当边的数据元素较大时,右端点左移;if(i<j)    //推出while循环时,已经在右端找到了一个小于basic的数据元素,此时交换左右两端的数据元素{a[i]=a[j];i++;}while(i<j&&basic>a[i]) i--;if(i<j)    //推出while循环时,已经在右端找到了一个大于basic的数据元素,此时交换左右两端的数据元素{a[j]=a[i];j--;}}a[i]=basic;   //此时i=j,此时将basic的值放在此位置if(left<i) QuickSort(a,left,i-1);  //对左端子集合进行递归排序if(i<right) QuickSort(a,j+1,right);  //对右端子集合进行递归排序
}

快速排序算法动画演示:

视频引自bilibili up主 秒懂算法

(四)归并排序
归并排序主要是指二路归并排序
归并排序的基本思想是将数组中的每一个数据元素作为一个单位,然后各单位分别对各自的头元素进行比较,将较小者放入新数组中,然后将剩余元素依次存入新数组。如此重复,直到得到一个长度为n的新的有序数组。

//一次二路归并排序算法如下:
void MSort(int a[],int b[],int i,int m,int n)
{//将a[i..m]和a[m+1..n]有序归并到b[i..n]int k,j,l;for(k=i,j=m+1;i<=m&&j<=n;k++){if(a[k]<a[j]){b[k]=a[k++];}else{b[k]=a[j++];}}if(i<=m){for(l=0;l<=m-i;l++){b[k+l]=a[i+l];  //将剩余的a[i..m]赋值给b[]}}if(j<=n){for(l=0;l<=n-j;j++){b[k+1]=a[j+l];  //将剩余的a[j..n]赋值给b}}
}
//二路归并排序算法如下:
void Merge(int SR[],int TR1[],int s,int t )
{//将SR[]有序归并到TR1[]int m;int TR2[MaxSize+1];  //中间变量数组if(s==t)TR2[s]=SR[s];else{m=(m+t)/2;   //将SR[s..t]分为SR[s..m]到SR[m..t]Merge(SR,TR2,s,m); //将SR[s..m]有序归并到TR2[s..m]Merge(SR,TR2,m,t); //将SR[m..t]有序归并到TR2[m..t]MSort(TR2,TR1,s,m,t); //将TR2[s..t]有序归并到TR1[s..t]}
}//对数组l进行归并排序
void MergeSort(int l[])
{Merge(l,l,1,sizeof(l)/sizeof(int));
}

归并排序算法动画演示:

视频引自bilibili up主 秒懂算法

(五)基数排序算法
基数排序也叫桶排序,其基本思想是以一组数字的个位、十位、百位…为关键字将数字依次存入以队列行是组成的“桶”中,然后依次从第一个“桶”开始逐个桶将数据收回,最后形成一个排序完成的数组。

#include <LQueue.h>//引入队列文件
void RadixSort(int a[],int n,int m,int d)
{//对数据元素a[0]-a[n-1]进行关键字为m位d进制整型数值的基数排列//桶采用链式队列int i,j,k,power;LQueue *tub;//把d个队列定义为动态数组tub=(LQueue *)malloc(sizeof(LQueue )*d);for(i=0;i<d;i++)QueueInitate(&tub[i]);   //d个队列初始化//进行m次放和收for(i=0;i<m;i++){if(i==0) power=1;else power=power*d;//将数据元素按关键字第k位的数值放到相应的队列中for(j=0;j<n;j++){k=a[j]/power-(a[j]/(power*d))*d;  //d为进制}//顺序回收各队列中的数据元素至数组a中k=0;for(j=0;j<d;j++){while(QueueNotEmpty(tub[j])!=0){QueueDelete(&tub[j],&a[k]);  //从各队列中回收k++;}}}
}

基数排序算法动画演示:

视频引自bilibili up主 师布衣

各类排序算法性能比较

目前为止,并没有一种排序算法是最好的,只有根据实际需求去判断哪一种最合适。

各类排序算法汇总及动画演示(C语言)相关推荐

  1. C语言各大排序算法整理及动画演示

    (一)插入排序 插入排序基本思想:从初始的子集合开始,不断地将新的元素插入到已排序好的子集合当中的合适位置.(未排序的插入到已排序当中)具体分为直接插入排序和希尔排序两种. ①直接插入排序 void ...

  2. c 语言从大到小排序算法,10 大经典排序算法(动图演示+ C 语言代码)

    原标题:10 大经典排序算法(动图演示+ C 语言代码) 来源:C语言与CPP编程 以前也零零碎碎发过一些排序算法,但排版都不太好,又重新整理一次,排序算法是数据结构的重要部分,系统地学习很有必要. ...

  3. 终于,把十大经典排序算法汇总了!(Java实现版)

    转载自  终于,把十大经典排序算法汇总了!(Java实现版) 最近几天在研究排序算法,看了很多博客,发现网上有的文章中对排序算法解释的并不是很透彻,而且有很多代码都是错误的,例如有的文章中在" ...

  4. 排序算法汇总(C/C++实现)

    前言:     本人自接触算法近2年以来,在不断学习中越多地发觉各种算法中的美妙.之所以在这方面过多的投入,主要还是基于自身对高级程序设计的热爱,对数学的沉迷.回想一下,先后也曾参加过ACM大大小小的 ...

  5. 各类排序算法总结(作者:__Boost)

    各类排序算法总结 一. 排序的基本概念 排序(Sorting)是计算机程序设计中的一种重要操作,其功能是对一个数据元素集合或序列重新排列成一个按数据元素某个项值有序的序列. 有 n 个记录的序列{R1 ...

  6. 十大经典排序算法(动图演示)(转)

    十大经典排序算法(动图演示) 本文转自https://www.cnblogs.com/onepixel/articles/7674659.html 0.算法概述 0.1 算法分类 十种常见排序算法可以 ...

  7. JAVA堆排序有监视哨吗_数据结构-各类排序算法总结

    各类排序算法总结 一. 排序的基本概念 排序(Sorting)是计算机程序设计中的一种重要操作,其功能是对一个数据元素集合或序列重新排列成一个按数据元素某个项值有序的序列. 有 n 个记录的序列{R1 ...

  8. c语言排序算法 应用与实现,基于C语言排序算法改进与应用.doc

    基于C语言排序算法改进与应用 基于C语言排序算法改进与应用 摘 要:介绍了程序语言中排序的原理及应用,阐述了基于C语言的三种主要排序方法,提出了每种排序方法的改进,计算出改进后算法的时间复杂度,编写了 ...

  9. 排序算法--排序算法汇总

    排序算法无疑是学习数据结构中的重点内容,本文将给出排序算法的汇总. 下面是具体的实现: #include<stdio.h> #include<stdlib.h> #includ ...

最新文章

  1. python是一门什么课程-为什么一定要让孩子学会一门编程语言?
  2. 地址空间和虚拟内存(转载)http://topic.csdn.net/u/20090619/10/4c62a13b-536b-4b0a-af09-2271c6a104e1.html...
  3. Java19-day10【标准输入输出流、字节字符打印流、对象序列化-反序列化流、serialVersionUIDtransient、Properties】
  4. 载:看了你能懂几个?
  5. 关于测试用例的一些思考
  6. sigmoid函数_常用的激活(激励)函数——深度学习笔记(建议收藏)
  7. PLSQL_性能优化系列10_Oracle Array数据组优化
  8. 上周热点回顾(5.26-6.1)
  9. 【设计模式:单例模式】单例模式01:饿汉模式
  10. 2019-5-5学习心得
  11. Redisson 配置
  12. k2p php服务器,网件R6800与斐讯K2P之间的mu-mimo测试
  13. 实现multi()函数,参数个数不限,返回所有参数的乘积
  14. TPshop项目步骤(二)
  15. Prometheus技术系列文章——prometheus调研总结
  16. 一张图看懂手机CPU性能——手机CPU性能天梯图
  17. 【Python】基于Python的复杂网络传播动力学及其可视化
  18. 如何使用高扩展组件制作APP原型的标签栏?
  19. magnum devstack部署
  20. SEO实战教程:“网络营销软件站”SEO策略完全解释

热门文章

  1. SpringMVC配置文件中的各个组件
  2. JL-03-Q9 自动气象站 常见气象9参数 空气温湿度 风速风向 雨量光照 大气压力 土壤温湿度
  3. opencv-之轮廓外接圆
  4. Python抓取QQ音乐歌单并分析
  5. 树莓派4无痛安装OpenCV+python3
  6. 【机器学习】线性回归实战案例一:多元素情况下广告投放效果分析步骤详解
  7. c/c++的改错练习二
  8. 英伟达tegra210 连接电视/hifi,设置默认声卡HDMI,
  9. Cisco 3650交换机断电后配置无法保存
  10. NOI2016 优秀的拆分(图解)