✏️✏️✏️好,那么今天给大家分享一下七大经典排序算法!
清风的CSDN博客
😛😛😛希望我的文章能对你有所帮助,有不足的地方还请各位看官多多指教,大家一起学习交流!
动动你们发财的小手,点点关注点点赞!在此谢过啦!哈哈哈!😛😛😛
目录
一、排序的概念以及运用
1.1 排序的概念
1.2 排序的运用
1.3 常见的排序算法
二、七大经典排序算法的实现
2.1 插入排序
2.1.1 基本思想
2.1.2 直接插入排序
2.1.3 插入排序实现代码
2.1.4 直接插入排序的特性总结
2.2 希尔排序
2.2.1 基本思想
2.2.2 希尔排序实现代码
2.2.3 希尔排序特性总结
2.3 选择排序
2.3.1 基本思想
2.3.2 选择排序
2.3.3 选择排序实现代码
2.3.4 选择排序特性总结
2.4 堆排序
2.4.1 堆排序基本思想
2.4.2 堆排序实现代码
2.4.3 堆排序特性总结
2.5 冒泡排序
2.5.1 冒泡排序基本思想
2.5.2 冒泡排序实现代码
2.5.3 冒泡排序特性总结
2.6 快速排序
2.6.1 快速排序基本思想
2.6.2 快速排序实现代码
2.6.3 快速排序非递归实现
2.6.4 快速排序特性总结
2.7 归并排序
2.7.1 归并排序基本思想
2.7.2 归并排序实现代码
2.7.3 归并排序非递归实现
2.7.4 归并排序特性总结
三、排序算法复杂度及稳定性一览表
一、排序的概念以及运用
1.1 排序的概念
内部排序:数据元素全部放在内存中的排序。
1.2 排序的运用
1.3 常见的排序算法
二、七大经典排序算法的实现
2.1 插入排序
2.1.1 基本思想
2.1.2 直接插入排序
2.1.3 插入排序实现代码
public static void insertSort(int[] array){
for (int i = 1; i < array.length ; i++) {
int tmp=array[i];
int j = i-1;
for (; j >=0 ; j--) {
if(array[j]>tmp){
array[j+1]=array[j];
}else{
break;
}
}
array[j+1]=tmp;
}
}
2.1.4 直接插入排序的特性总结
- 元素集合越接近有序,直接插入排序算法的时间效率越高
- 时间复杂度:O(N^2)
- 空间复杂度:O(1),它是一种稳定的排序算法
- 稳定性:稳定
2.2 希尔排序
2.2.1 基本思想
2.2.2 希尔排序实现代码
public static void shellSort(int[] array){
int gap= array.length;
while(gap>1){
gap/=2;
shell(array,gap);
}
}
public static void shell(int[] array,int gap){
for (int i = gap; i <array.length ; i++) {
int tmp=array[i];
int j = i-gap;
for (; j >=0 ; j-=gap) {
if(array[j]>tmp){
array[j+gap]=array[j];
}else{
break;
}
}
array[j+gap]=tmp;
}
}
2.2.3 希尔排序特性总结
- 希尔排序是对直接插入排序的优化。
- 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。整体而言,可以达到优化的效果。
- 希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,因此在好些树中给出的希尔排序的时间复杂度都不固定。
- 稳定性:不稳定
《数据结构(C语言版)》--- 严蔚敏
《数据结构-用面向对象方法与C++描述》--- 殷人昆
2.3 选择排序
2.3.1 基本思想
2.3.2 选择排序
- 在元素集合array[i]--array[n-1]中选择关键码最大(小)的数据元素
- 若它不是这组元素中的最后一个(第一个)元素,则将它与这组元素中的最后一个(第一个)元素交换
- 在剩余的array[i]--array[n-2](array[i+1]--array[n-1])集合中,重复上述步骤,直到集合剩余1个元素
2.3.3 选择排序实现代码
public void selectSort(int[] array){
for (int i = 0; i < array.length; i++) {
int smallest=i;
int j = i+1;
for (; j < array.length; j++) {
if(array[j]<array[smallest]){
smallest=j;
}
}
swap(array,i,smallest);
}
}
public static void swap(int[] array,int i,int j){
int tmp=array[i];
array[i]=array[j];
array[j]=tmp;
}
2.3.4 选择排序特性总结
- 直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用
- 时间复杂度:O(N^2)
- 空间复杂度:O(1)
- 稳定性:不稳定
2.4 堆排序
2.4.1 堆排序基本思想
2.4.2 堆排序实现代码
public static void heapSort(int[] array){
crearMaxheap(array);
int end=array.length-1;
while(end>0){
swap(array,0,end);
siftDown(array,0,end);
end--;
}
}
private static void crearMaxheap(int[] array){
for (int parent = (array.length-1-1)/2; parent >=0 ; parent--) {
siftDown(array,parent,array.length);
}
}
private static void siftDown(int[] array,int parent,int len){
int child=2*parent+1;
while(child<len){
if(child+1<len && array[child+1]>array[child]){
child=child+1;
}
//孩子最大值以及找到
if(array[child]>array[parent]){
swap(array,child,parent);
parent=child;
child=2*parent+1;
}else{
break;
}
}
}
2.4.3 堆排序特性总结
- 堆排序使用堆来选数,效率就高了很多。
- 时间复杂度:O(N*logN)
- 空间复杂度:O(1)
- 稳定性:不稳定
2.5 冒泡排序
2.5.1 冒泡排序基本思想
2.5.2 冒泡排序实现代码
public static void bubbleSort(int[] array){
for (int i = 0; i < array.length-1; i++) {
boolean flg=false;
for (int j = 0; j < array.length-1-i; j++) {
if(array[j]>array[j+1]){
swap(array,j,j+1);
flg=true;
}
}
if(flg==false){
break;
}
}
}
2.5.3 冒泡排序特性总结
- 冒泡排序是一种非常容易理解的排序
- 时间复杂度:O(N^2)
- 空间复杂度:O(1)
- 稳定性:稳定
2.6 快速排序
2.6.1 快速排序基本思想
2.6.2 快速排序实现代码
public static void quickSort(int[] array){
int start=0;
int end= array.length-1;
quick(array,start,end);
}
private static void quick(int[] array,int start,int end){
if(start>=end){
return;
}
int pivot=paratition(array,start,end);
quick(array,start,pivot-1);
quick(array,pivot+1,end);
}
//选轴值
private static int paratitionHoare(int[] array,int left,int right){
int i=left;
int tmp=array[left];
while (left<right){
while (left<right && array[right]>=tmp){
right--;
}
while (left<right && array[left]<=tmp){
left++;
}
swap(array,left,right);
}
swap(array,i,left);
return left;
}
//选基准的两种方法
//挖坑法
private static int paratition(int[] array,int left,int right){
int tmp=array[left];
while(left<right){
while (left<right && array[right]>=tmp){
right--;
}
array[left]=array[right];
while (left<right && array[left]<=tmp){
left++;
}
array[right]=array[left];
}
//相遇之后,把tmp放到坑里
array[left]=tmp;
return left;
}
2.6.3 快速排序非递归实现
private static void quickNor(int[] array,int start,int end){
if(start>=end){
return;
}
Stack<Integer> stack=new Stack<>();
int pivot=paratitionHoare(array,start,end);
if(pivot-1>start){
//说明左边有2个以上的元素
stack.push(start);
stack.push(pivot-1);
}
if(pivot+1<end){
//说明右边有2个以上的元素
stack.push(pivot+1);
stack.push(end);
}
while (!stack.isEmpty()){
end=stack.pop();
start=stack.pop();
pivot=paratitionHoare(array,start,end);
if(pivot-1>start){
//说明左边有2个以上的元素
stack.push(start);
stack.push(pivot-1);
}
if(pivot+1<end){
//说明右边有2个以上的元素
stack.push(pivot+1);
stack.push(end);
}
}
2.6.4 快速排序特性总结
- 快速排序整体的综合性能和使用场景都是比较好的,所以才敢叫快速排序
- 时间复杂度:O(N*logN)
- 空间复杂度:O(logN)
- 稳定性:不稳定
2.7 归并排序
2.7.1 归并排序基本思想
2.7.2 归并排序实现代码
public static void mergeSort(int[] array){
mergeSortFun(array,0,array.length-1);
}
private static void mergeSortFun(int[] array,int start,int end){
if(start>=end){
return;
}
int mid=(start+end)/2;
mergeSortFun(array,start,mid);
mergeSortFun(array,mid+1,end);
//开始合并
merge(array,start,mid,end);
}
private static void merge(int[] array,int left,int mid,int right){
int s1=left;
int e1=mid;
int s2=mid+1;
int e2=right;
int k=0;
int[] tmpArr=new int[right-left+1];
while (s1<=e1 && s2<=e2){
if(array[s1]<=array[s2]){
tmpArr[k++]=array[s1++];
}else {
tmpArr[k++]=array[s2++];
}
}
while (s1<=e1){
tmpArr[k++]=array[s1++];
}
while (s2<=e2){
tmpArr[k++]=array[s2++];
}
for (int i = 0; i < tmpArr.length; i++) {
array[i+left]=tmpArr[i];
}
}
2.7.3 归并排序非递归实现
public static void mergeSortNor(int[] array){
int gap=1;
while (gap<array.length){
for (int i = 0; i < array.length; i+=gap*2) {
int left=i;
int mid=left+gap-1;
int right=mid+gap;
//mid和right可能会越界
if(mid>=array.length){
mid=array.length-1;
}
if(right>=array.length){
right=array.length-1;
}
merge(array,left,mid,right);
}
gap*=2;
}
}
2.7.4 归并排序特性总结
- 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
- 时间复杂度:O(N*logN)
- 空间复杂度:O(N)
- 稳定性:稳定
三、排序算法复杂度及稳定性一览表
排序方法 | 最好 | 平均 | 最坏 | 空间复杂度 | 稳定性 |
冒泡排序 | O(n) |
O(n^2)
| O(n^2) | O(1) | 稳定 |
插入排序 | O(n) |
O(n^2)
|
O(n^2)
| O(1) | 稳定 |
希尔排序 | O(n) | O(n^1.3) | O(n^2) | O(1) | 不稳定 |
堆排序 | O(n*logn) | O(n*logn) | O(n*logn) | O(1) | 不稳定 |
选择排序 | O(n^2) | O(n^2) | O(n^2) | O(1) | 不稳定 |
快速排序 | O(n*logn) | O(n*logn) |
O(n^2)
|
O(log(n)) ~ O(n)
| 不稳定 |
归并排序 | O(n*logn) | O(n*logn) | O(n*logn) | O(n) | 稳定 |
✨希望各位看官读完文章后,能够有所提升。
🎉好啦,今天的分享就到这里!!
✨创作不易,还希望各位大佬支持一下!
👍点赞,你的认可是我创作的动力!
⭐收藏,你的青睐是我努力的方向!
✏️评论:你的意见是我进步的财富!