C语言各大排序算法整理及动画演示
(一)插入排序
插入排序基本思想:从初始的子集合开始,不断地将新的元素插入到已排序好的子集合当中的合适位置。(未排序的插入到已排序当中)具体分为直接插入排序和希尔排序两种。
①直接插入排序
void InsertSort(int a[], int n)//直接插入排序
{
int i, j, temp;
for (i = 0; i < n-1; i++)//循环n-1次
{
temp = a[i + 1];//将未排序的元素暂存在temp里面
j = i;
while (j > -1 && temp < a[j])
{
a[j + 1] = a[j];//将已排序子集合里面最右边的数赋值给未排序的第一个元素
j--; //若能在已排序好的元素里面一直找到比temp大的数,j就前移,直到找到比temp小的数或者j值为-1,j停止
}
a[j + 1] = temp;//当上述循环结束之后,此时j+1的位置就是插入的合适位置
}
}
直接插入排序的动画演示:
②希尔排序
希尔排序基本思想:(事实上是经过分组整理之后,变得更加有序才使用直接插入排序)
将待排序的元素分成若干个小组,对同一个小组使用直接插入排序。
void ShellSort(int a[], int n, int d[], int m)//希尔排序 d[]代表增量 n代表次数
{ //d[3]={6,3,1} ,m=3
int i, j, k, s, span,temp;
for (s = 0; s < m; s++) //一共m次循环
{
span = d[s]; //取本次循环的增量
for (k = 0; k < span; k++) //一共span个小组
{ //组内是直接插入排序,但是并不是相邻比较,而是隔span比较
for (i = 0; i < n - span; i++) //以下为直接插入排序的操作方法
{
temp = a[i + span];
j = i;
while (j > -1 && temp < a[j])
{
a[j + span] = a[j];
j = j - span;
}
a[j + span] = temp;
}
}
}
}
希尔排序的动画演示:
(二)选择排序
选择排序基本思想:每次从待排序集合里面选取最小或最大的元素放在元素集合的最前面或最后面。一般有直接选择排序和堆排序两种算法。
①直接选择排序
void SelectSort(int a[], int n) //直接选择排序
{
int i, j, temp,small;
for (i = 0; i < n - 1; i++) //第一次做n-1次循环
{
small = i; //设a[0]为最小值
for (j = i + 1; j < n; j++)
{
if (a[j] < a[small]) //将a[small]与后面n-1个数比较,找到最小值
small = j; //标记最小值位置
}
if (small != i) //上述循环做完一次之后,若不是同一个位置,就交换元素
{
temp = a[i];
a[i] = a[small];
a[small] = temp;
}
}
}
直接选择排序动画演示:
②堆排序算法
堆排序基本思想:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了。
堆的定义:堆分为最大堆(根结点比左右孩子结点都要大)和最小堆(根结点比左右孩子结点都要小)两种。
大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]
小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]
同时,我们对堆中的结点按层进行编号,将这种逻辑结构映射到数组中就是下面这个样子
第一步:写出满足最大堆的函数
void CreatHeap(int a[], int n, int h) //满足最大堆的函数
{
int i, j, flag,temp;
i = h; //建立堆的二叉树根结点下标
j = 2 * h + 1; //i的左孩子结点下标
temp = a[i]; //保存根结点
flag = 0;
while (j < n && flag != 1)
{
if (j < n - 1 && a[j] < a[j + 1]) j++;//找到左右孩子的最大值,j为下标
if (temp > a[j]) flag = 1; //标记结束筛选条件
else //若根结点不是最大,就将a[j](左右孩子最大值)上移
{
a[i] = a[j]; //将最大值赋给根结点
i = j; //将最大孩子结点赋给i,方便后面a[i]=temp,调换
j = 2 * i + 1;//判断j是否超过元素个数
}
}
a[i] = temp; //把最初的a[i]赋给最后的a[j],对换
}第二步:建立最大堆
void InitCreatHeap(int a[], int n) //创建最大堆
{
for (int i = (n - 2) / 2; i >= 0; i--) //第一个非叶子结点开始
CreatHeap(a, n, i);
}
a.将无序序列构建成一个堆,根据升序降序需求选择大顶堆(升序)或小顶堆(降序);
b.将堆顶元素与末尾元素交换,将最大元素"沉"到数组末端;
c.重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。
第三步:堆排序算法
void HeapSort(int a[], int n) //堆排序算法
{
int i,temp;
InitCreatHeap(a, n);//初始化最大堆
for (i = n - 1; i > 0; i--)//做n-1次
{
temp = a[0]; //将第一个元素与最后一个元素对换
a[0] = a[i];
a[i] = temp;
CreatHeap(a, i, 0); //调整根结点满足堆的定义
}
}
堆排序算法动画演示:
(三)交换排序
交换排序基本思想:利用交换元素的位置进行排序的方法。常用的交换排序方法有冒泡排序和快速排序法。其中快速排序法是一种分区交换的排序方法。
①冒泡排序
冒泡排序基本思想:每一趟均比较相邻的两个元素。若前一个比后一个大就交换它们的位置,否则就不交换。相当于每次找到了最大元素,将其放在最后一位。
void BubbleSort(int a[], int n) //冒泡排序
{
int i, j, temp,flag=1; //flag优化算法
for (i = 1; i < n&&flag==1; i++)
{flag=0;
for (j = 0; j < n - i; j++)//做n-1次 n-2次 直到0次结束
{
if (a[j] > a[j+1]) //比较相邻元素大小
{flag=1;
temp = a[j]; //交换
a[j] = a[j+1];
a[j+1] = temp;
}
}
}
}
冒泡排序动画演示:
②快速排序
快速排序基本思想:选一个数作为基数(这里我选的是第一个数),大于这个基数的放到右边,小于这个基数的放到左边,等于这个基数的数可以放到左边或右边,看自己习惯,这里我是放到了左边,一趟结束后,将基数放到中间分隔的位置,第二趟将数组从基数的位置分成两半,分割后的两个的数组继续重复以上步骤,选基数,将小数放在基数左边,将大数放到基数的右边,在分割数组,直到数组不能再分为止,排序结束。
例如从小到大排序:
1. 第一趟,第一个数为基数temp,设置两个指针left = 0,right = n.length,
①从right开始与基数temp比较,如果n[right]>基数temp,则right指针向前移一位,继续与基数temp比较,直到不满足n[right]>基数temp
②将n[right]赋给n[left]
③从left开始与基数temp比较,如果n[left]<=基数temp,则left指针向后移一位,继续与基数temp比较,直到不满足n[left]<=基数temp
④将n[left]赋给n[right]
⑤重复①-④步,直到left==right结束,将基数temp赋给n[left]
2. 第二趟,将数组从中间分隔,每个数组再进行第1步的操作,然后再将分隔后的数组进行分隔再快排,
3. 递归重复分隔快排,直到数组不能再分,也就是只剩下一个元素的时候,结束递归,排序完成
根据思路分析,第一趟的执行流程如下图所示:
void QuickSort(int a[], int low, int high) //快速排序算法
{
int i = low, j = high, temp = a[low];//先把a[i]取出来暂存
while (i < j)
{
while(i < j && a[j] >= temp) j--; //最→边找到比temp小的数就停止
if (i < j)
{
a[i] = a[j]; //将这个数赋给a[i],第一次为a[0]
i++; //移到左边扫描
}
while (i < j && a[i] < temp) i++; //最左边找到比temp大的数就停止
if (i < j)
{
a[j] = a[i]; //将这个数赋给刚刚j停止的地方
j--; //移到右边扫描
}
}
a[i] = temp; //扫描完一遍之后,当i=j时循环停止。将temp赋给ij的位置
if (low < i)
QuickSort(a, low, i - 1); //对左边子集合扫描
if (high > i)
QuickSort(a, j + 1, high); //对右边子集合扫描
}
快速排序动画演示:
C语言各大排序算法整理及动画演示相关推荐
- 【C#】十大排序算法(动图演示+代码实现)
文章目录 1.冒泡排序 2.插入排序 3.选择排序 4.快速排序 5.希尔排序 6.堆排序 7.归并排序 8.计数排序 9.桶排序 10.基数排序 参考 1.冒泡排序 口诀: 外层循环 n-1;内层循 ...
- c语言sort_C语言十大排序算法,让老师对你刮目相看的技巧
排序算法作为数据结构的重要部分,系统地学习一下是很有必要的. 十种常见排序算法可以分为两大类: 比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时 ...
- 数据结构与算法--经典10大排序算法(动图演示)【建议收藏】
十大经典排序算法总结(动图演示) 算法分类 十大常见排序算法可分为两大类: 比较排序算法:通过比较来决定元素的位置,由于时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序 非比较类型排 ...
- 各类排序算法汇总及动画演示(C语言)
常用排序算法及动画演示 (一)插入排序 插入排序可形象理解为打扑克时理牌的一个过程,具体分为直接插入.折半插入排序.希尔排序三种: ①直接插入排序 void InsertSort(int a[],in ...
- c语言折半排序的程序,C语言实现九大排序算法的实例代码
直接插入排序 将数组分为两个部分,一个是有序部分,一个是无序部分.从无序部分中依次取出元素插入到有序部分中.过程就是遍历有序部分,实现起来比较简单. #include void insertion_s ...
- 九大排序算法Java实现
之前学习数据结构与算法时花了三天时间整理九大排序算法,并采用Java语言来实现,今天第一次写博客,刚好可以把这些东西从总结的文档中拿出来与大家分享一下,同时作为自己以后的备忘录. 1.排序算法时间复杂 ...
- 中希尔排序例题代码_【数据结构与算法】这或许是东半球分析十大排序算法最好的一篇文章...
码农有道 历史文章目录(请戳我) 关于码农有道(请戳我) 前言 本文全长 14237 字,配有 70 张图片和动画,和你一起一步步看懂排序算法的运行过程. 预计阅读时间 47 分钟,强烈建议先收藏然后 ...
- python快速排序算法没看懂_你需要知道的九大排序算法【Python实现】之快速排序...
五.快速排序 基本思想: 通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分关键字小,则分别对这两部分继续进行排序,直到整个序列有序. 算法实现: #coding: ...
- 程序员必备十大排序算法
程序员必备十大排序算法 常见排序算法 基本概念 插入排序 直接插入排序 排序思路 排序过程 代码实现 算法分析 折半插入排序 排序思路 排序过程 代码实现 算法分析 希尔排序 排序思路 排序过程 代码 ...
最新文章
- HDU 2896 病毒侵袭 AC自己主动机题解
- 太厉害了!这应该是目前Redis可视化工具最全的横向评测
- iOS用户设计指南 - 平台特征
- 在SunOS5.8/solaris7上使用Xerces-C解析器
- golang基本数据类型和string的相互转换
- appium启动app失败_Appium-Desktop Capability 配置及启动App演示
- rest api如何创建_创建一个安全的Spring REST API
- 嵌入式Jetty和Apache CXF:借助Spring Security来保护REST服务
- java volatile修饰引用_关于volatile修饰引用类型的疑惑
- python 描述器 详解_深入解析Python中的descriptor描述器的作用及用法
- 2019 ACM/ICPC 南昌站 G,拉格朗日插值
- javascript获取Select下拉框的值
- 轻松学习JavaScript二十一:DOM编程学习之获取元素节点的子节点和属性节点
- python定时重启程序
- 通信原理(五) 信道编码
- 清华大学计算机系高考选科要求,清华大学新高考选课要求-清华大学新高考选考科目...
- 《老爸老妈浪漫史》Barney和Robin终于。。。
- 虚拟同步发电机_学术简报基于分散式微电网的虚拟同步发电机无通信预同步并网方案...
- 敏捷开发“松结对编程”系列之十二:L型代码结构(质量篇之一)
- 阿里云数据库再获学术顶会认可,一文全览VLDB最新亮点