计数排序
-
计数排序:是一个非基于比较的排序算法,该算法于1954年由 Harold H. Seward 提出。它的优势在于在对一定范围内的整数排序时,快于任何比较排序算法。
-
排序思路
- 找出待排序数组最大值,确定排序数组的索引值
- 定义一个索引最大值为待排序数组最大值的数组
- 遍历待排序数组,将待排序数组中每个数字出现的次数存储在排序数组中
- 整理排序数组中的数字,如果排序数组的值不为零,输出对应的下标值
- 最后将索引值输出即为排序结果
-
解释
-
示例
#include <stdio.h> void CountingSort(int length,int OriginalArray[length]); void PrintArray(int length,int OriginalArray[length]); int main() { //创建待排序数组 int length; printf("请输入待排序数组长度:"); scanf("%d",&length); int OriginalArray[length]; //初始化待排序数组 printf("请输入待排序数组元素:"); for(int i = 0;i < length;i++) { scanf("%d",&OriginalArray[i]); } //调用排序函数对待排序数组进行排序 CountingSort(length,OriginalArray); //打印结果 PrintArray(length,OriginalArray); return 0; } //排序函数 void CountingSort(int length,int OriginalArray[length]) { //寻找待排序数组最大值 int max = OriginalArray[0]; for(int i =1;i < length;i++) { if(OriginalArray[i] > max) { max = OriginalArray[i]; } } //创建排序数组 int SortArray[max + 1]; //初始化排序数组 for(int i = 0;i <= max;i++) { SortArray[i] = 0; } //统计待排序数组每个数字出现的次数 for(int i = 0;i < length;i++) { SortArray[OriginalArray[i]]++; } //整理排序数组 int index = 0; int AuxiliaryArray[length]; for(int i = 0;i <= max;i++) { while(SortArray[i] > 0) { AuxiliaryArray[index] = i; index++; SortArray[i]--; } } //将排序结果返回待排序数组 for(int i = 0;i < length;i++) { OriginalArray[i] = AuxiliaryArray[i]; } } //打印结果 void PrintArray(int length,int OriginalArray[length]) { for(int i = 0;i < length;i++) { printf("%d ",OriginalArray[i]); } }
-
练习
输入90到100以内的5个数,优化计数排序,避免资源浪费
#include <stdio.h> void CountingSort(int length,int OriginalArray[length]); void PrintSort(int length,int OriginalSort[length]); int main() { //定义待排序数组 int length; printf("请输入待排序数组长度:"); scanf("%d",&length); int OriginalArray[length]; //初始化待排序数组 printf("请输入待排序数组元素:"); for(int i = 0;i < length;i++) { scanf("%d",&OriginalArray[i]); } //调用函数 CountingSort(length,OriginalArray); //打印结果 PrintSort(length,OriginalArray); return 0; } //排序算法 void CountingSort(int length,int OriginalArray[length]) { //寻找待排序数组最大最小值 int max = OriginalArray[0]; int min = OriginalArray[0]; for(int i = 1;i < length;i++) { if(OriginalArray[i] > max) { max = OriginalArray[i]; } if(OriginalArray[i] < min) { min = OriginalArray[i]; } } //定义计数数组 int size = max - min + 1; //int maximum = max - min; int SortArray[size]; //初始化计数数组 for(int i = 0;i < size;i++) { SortArray[i] = 0; } //统计待排序数组每个元素出现次数 for(int i = 0;i < length;i++) { SortArray[OriginalArray[i] - min]++; } //整理计数数组 int index = 0; int AuxiliaryArray[length]; for(int i = 0;i < size;i++) { while(SortArray[i] > 0) { AuxiliaryArray[index] = i + min; index++; SortArray[i]--; } } //将排序结果返回待排序数组 for(int i = 0;i < length;i++) { OriginalArray[i] = AuxiliaryArray[i]; } } //打印结果 void PrintSort(int length,int OriginalSort[length]) { for(int i = 0;i < length;i++) { printf("%d ",OriginalSort[i]); } }
选择排序
-
原理:先寻找待排序数组中的最小值,放在第一位,然后寻找剩下的数字中的最小值,放在第二位,以此类推,直到排序完成。
-
排序思路
- 利用第0个元素和后面的元素依次进行对比
- 判断第0个元素是否大于当前被比较元素, 一旦小于就交换位置
- 第0个元素和后续所有元素比较完成后, 第0个元素就是最小值
- 排除第0个元素, 用第1个元素重复1~3操作, 比较完成后第1个元素就是倒数第二小的值
- 以此类推, 直到当前元素没有可比较的元素, 排序完成
-
解释
-
示例
#include <stdio.h> void SelectSort(int length,int OriginalArray[length]); void PrintArray(int length,int OriginalArray[length]); int main() { //定义待排序数组 int length; printf("请输入待排序数组长度:"); scanf("%d",&length); int OriginalArray[length]; //初始化待排序数组 printf("请输入待排序数组元素:"); for(int i = 0;i < length;i++) { scanf("%d",&OriginalArray[i]); } //调用排序函数 SelectSort(length,OriginalArray); //打印结果 PrintArray(length,OriginalArray); return 0; } //排序函数 void SelectSort(int length,int OriginalArray[length]) { for(int i = 0;i < length;i++) { for(int j = i;j < length - 1;j++) //j < length - 1的原因:最后一位数不用做比较,如果继续拿着最后一位数与后面的术进行比较,一来是后面没有数字,二来是会造成数组越界 { if(OriginalArray[i] > OriginalArray[j + 1]) { int temp = OriginalArray[j + 1]; OriginalArray[j + 1] = OriginalArray[i]; OriginalArray[i] = temp; } } } } //打印结果 void PrintArray(int length,int OriginalArray[length]) { for(int i = 0;i < length;i++) { printf("%d ",OriginalArray[i]); } }
冒泡排序
-
冒泡排序:是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端。
-
冒泡排序
-
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
-
对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
-
针对所有的元素重复以上的步骤,除了最后一个。
-
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
-
-
解释
-
示例
#include <stdio.h> void BubbleSort(int length,int OriginalArray[length]); void PrintArray(int length,int OriginalArray[length]); int main() { //创建待排序数组 int length; printf("请输入待排序数组长度:"); scanf("%d",&length); int OriginalArray[length]; //初始化待排序数组 printf("请输入待排序数组元素:"); for(int i = 0; i < length;i++) { scanf("%d",&OriginalArray[i]); } //调用排序函数 BubbleSort(length,OriginalArray); //打印结果 PrintArray(length,OriginalArray); return 0; } //排序函数 void BubbleSort(int length,int OriginalArray[length]) { for(int i = 0;i < length;i++) { for(int j = 0;j < length - 1 -i;j++) { if(OriginalArray[j] > OriginalArray[j + 1]) { int temp = OriginalArray[j]; OriginalArray[j] = OriginalArray[j + 1]; OriginalArray[j + 1] = temp; } } } } //打印结果 void PrintArray(int length,int OriginalArray[length]) { for(int i = 0;i < length;i++) { printf("%d ",OriginalArray[i]); } }
-
计数排序与冒泡排序的区别
乍一看,两种排序算法的代码貌似都一样,但是从原理上我们也知道,两者不一样,区别就在于选择排序是找最小值,而冒泡排序是比较相邻两数字的大小。
插入排序
-
插入排序:是一种最简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
-
算法步骤
- 将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
- 从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)
-
解释
-
示例
#include <stdio.h> void InsertionSort(int length,int OriginalArray[length]); void PrintReasult(int length,int OriginalArray[length]); int main() { //创建待排序数组 int length; printf("请输入待排序数组长度:"); scanf("%d",&length); int OriginalArray[length]; //初始化待排序数组 printf("请输入待排序数组元素:"); for(int i = 0;i < length;i++) { scanf("%d",&OriginalArray[i]); } //调用排序函数 InsertionSort(length,OriginalArray); //打印结果 PrintReasult(length,OriginalArray); return 0; } //排序函数 void InsertionSort(int length,int OriginalArray[length]) { int key; for(int i = 1;i < length;i++) { key = OriginalArray[i]; int j = i - 1; while((j >= 0) && (OriginalArray[j] > key)) { OriginalArray[j + 1] = OriginalArray[j]; j--; } OriginalArray[j + 1] = key; } } //打印结果 void PrintReasult(int length,int OriginalArray[length]) { for(int i = 0;i < length;i++) { printf("%d ",OriginalArray[i]); } }
希尔排序
-
希尔排序:也称递减增量排序算法,是插入排序的一种更高效的改进版本。但希尔排序是非稳定排序算法。
-
希尔排序是基于插入排序的以下两点性质而提出改进方法的:
- 插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率;
- 但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。
-
基本思想
先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录"基本有序"时,再对全体记录进行依次直接插入排序。
-
算法步骤
-
选择一个增量序列 t1,t2,……,tk,其中 ti > tj, tk = 1;
-
按增量序列个数 k,对序列进行 k 趟排序;
-
每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序。仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。
-
-
解释
-
示例
#include <stdio.h> void ShellSort(int length,int OriginalArray[length]); void PrintReasult(int length,int OriginalArray[length]); int main() { //创建待排序数组 int length; printf("请输入待排序数组的长度:"); scanf("%d",&length); int OrigianlArray[length]; //初始化待排序数组 printf("请输入待排序数组元素:"); for(int i = 0;i < length;i++) { scanf("%d",&OrigianlArray[i]); } //调用排序函数 ShellSort(length,OrigianlArray); //打印结果 PrintReasult(length,OrigianlArray); return 0; } //排序函数 void ShellSort(int length,int OriginalArray[length]) { int temp; for(int gap = length >> 1;gap > 0;gap >>= 1) { for(int i = gap;i < length;i++) { temp = OriginalArray[i]; int j; for(j = i - gap;j >= 0 && OriginalArray[j] > temp;j -= gap) { OriginalArray[j + gap] = OriginalArray[j]; } OriginalArray[j + gap] = temp; } } } //打印结果 void PrintReasult(int length,int OriginalArray[length]) { for(int i = 0;i < length;i++) { printf("%d ",OriginalArray[i]); } }