十大经典排序算法
1、分类
非线性时间比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此称为非线性时间比较类排序。
线性时间非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此称为线性时间非比较类排序。
2、时间与空间复杂度
Ps:
稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。
不稳定:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b的后面。
1、冒泡排序(Bubble Sort)
1.1 算法描述
- 比较相邻的元素。如果第一个比第二个大,就交换它们两个;
- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
- 针对所有的元素重复以上的步骤,除了最后一个;
- 重复步骤1~3,直到排序完成。
1.2 动图演示
1.3 代码实现
#include<stdio.h> void BuddleSort(int a[],int n){ for(int i=0;i<n-1;i++){ //每一趟 for( int j=0;j<n-i-1;j++){//每一趟比较几次 if(a[j]>a[j+1]){ int temp=a[j]; a[j]=a[j+1]; a[j+1]=temp; } } } } int main(){ int a[]={6, 9,8,4,5,2,1,3,7}; int n=sizeof(a)/sizeof(int); BuddleSort(a,n); printf("冒泡排序结果:"); for (int i = 0; i < n; i++) { printf("%d ", a[i]); } return 0; }
2、选择排序(SelectSort)
选择排序(Selection-sort)是一种简单直观的排序算法。工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
2.1 算法描述
- 初始状态:序列为无序状态。
- 第1次排序:从n个元素中找出最小(大)元素与第1个记录交换
- 第2次排序:从n-1个元素中找出最小(大)元素与第2个记录交换
- 第i次排序:从n-i+1个元素中找出最小(大)元素与第i个记录交换
- 以此类推直到排序完成
2.2 动图演示
2.3 代码实现
#include<stdio.h> void SelectSort(int a[],int n) { for(int i=0;i<n-1;i++) { int min=i; //存放数组最小值的位置 for(int j=i+1;j<n;j++) { if(a[j]<a[min]){ min=j; //找出最小值,并记录位置 } } if(min!=i) //最小元素与第i个元素互换位置 { int temp=a[min]; a[min]=a[i]; a[i]=temp; } } } int main() { int a[]={8,9,7,1,5,4,2,3,6}; int n=sizeof(a)/sizeof(int); SelectSort(a,n); printf("选择排序结果:"); for (int i = 0; i < n; i++) { printf("%d ", a[i]); } printf("\n"); return 0; }
3、插入排序(Insertion Sort)
插入排序(Insertion-Sort)的算法描述是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
3.1 算法描述
一般来说,插入排序都采用in-place在数组上实现。具体算法描述如下:
- 从第一个元素开始,该元素可以认为已经被排序;
- 取出下一个元素,在已经排序的元素序列中从后向前扫描;
- 如果该元素(已排序)大于新元素,将该元素移到下一位置;
- 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
- 将新元素插入到该位置后;
- 重复步骤2~5。
3.2 动图演示
3.3 代码实现
#include<stdio.h> void InsertSort(int a[],int n) { for(int i=0;i<n;i++) { int j=i-1; if(a[i]<a[i-1]){ //若第i个元素小于第i-1个元素,移动有序序列插入------大于的话则直接插入 int temp=a[i]; //存储将要排序的元素 a[i]=a[i-1]; //向后移动一个元素 while(temp<a[j])//查询将要插入的位置 { a[j+1]=a[j]; j--; //元素后移 } a[j+1]=temp;//循环结束 插入到指定位置 } } } int main() { int a[] = { 9,7,8,2,5,1,3,6,4}; int n = sizeof(a)/sizeof(int); InsertSort(a, n); printf("排序好的数组为:"); for (int i = 0; i < n; i++) { printf(" %d", a[i]); } printf("\n"); return 0; }
4、希尔排序(Shell Sort)
4.1 算法描述
先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,具体算法描述:
- 选择一个增量序列t1,t2,…,tk,其中ti>tj,tk=1;
- 按增量序列个数k,对序列进行k 趟排序;
- 每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m 的子序列,分别对各子表进行直接插入排序。仅增量因子为1时,整个序列作为一个表来处理,表长度即为整个序列的长度。
4.2 演示
4.3 代码实现
//希尔排序Shell Sort //杨鑫 #include <stdio.h> #include <stdlib.h> void ShellSort(int a[], int length) { int increment; int i,j; int temp; for(gap = length/2; gap > 0; gap /= 2) //用来控制步长,最后递减到1 { // i从第step开始排列,应为插入排序的第一个元素 // 可以先不动,从第二个开始排序 for(i = gap ; i < length; i++) { temp = a[i]; for(j = i - gap ; j >= 0 && temp < a[j]; j -= gap ) { a[j + gap ] = a[j]; } a[j + gap ] = temp; //将第一个位置填上 } } } int main() { int i, j; int a[] = {5, 18, 151, 138, 160, 63, 174, 169, 79, 200}; for(i = 0; i < 10; i++) { printf("%d ", a[i]); } ShellSort(a, 10); for(j = 0; j < 10; j++) { printf("%d ", a[j]); } printf("\n"); return 0; }
Ps:希尔排序的核心在于间隔序列的设定。既可以提前设定好间隔序列,也可以动态的定义间隔序列。
- 十大经典排序算法最强总结(含JAVA代码实现)
- 十大经典排序算法总结(JavaScript描述)
- 十大经典排序算法
- 十大经典排序算法动画与解析,看我就够了!(配代码完全版)
- 先码后看 十大经典排序算法最强总结(含Java代码实现) 侵立删
- 十大经典排序算法最强总结(含Java代码实现)
- 十大经典排序算法
- 十大经典排序算法
- 十大经典排序算法
- 十大经典排序算法
- 十大经典排序算法
- 用JavaScript实现十大经典排序算法
- 十大经典排序算法小结
- 十大经典排序算法
- 十大经典排序算法总结(JavaScript描述)
- 十大经典排序算法
- 【归纳整理】十大经典排序算法的简单C++实现
- 十大经典排序算法
- 十大经典排序算法(动图演示)
- 十大经典排序算法动画解析和 Java 代码实现