🎁个人主页:我们的五年
🔍系列专栏:排序算法
🎉欢迎大家点赞👍评论📝收藏⭐文章
一.冒泡排序:
时间复杂度:O(N^2)。
🏄♂️思路分析:
冒泡排序是交换排序。
第一次找出最大的放在数组的最后面num[n-1]。
第二次找出第二大的数放在数组的num[n-2]。
……
两两相比,然后交换位置就可以找到最大的,第二大的……
如果某趟中,没有进行数据交换,证明此时序列已经有序。就可以直接跳出循环。
🏄♂️代码分析:
//冒泡排序
void Bubble_Sort(int* num, int n)
{//n-1趟for (int i = 0;i <n -1; i++){bool flag = 0;//第一趟[0,n-2]for (int j = 1;j <n-i; j++){if (num[j - 1] > num[j]){swap(num[j-1], num[j]);flag = 1;}}if (flag == 0)break;}
}
二.插入排序:
时间复杂度:O(N^2)。
最坏情况:逆序,N*(N-1)/2=O(N^2)。
最好情况:顺序,O(N)。
🏄♂️思路分析:
插入排序有点像我们打扑克牌,打扑克牌的时候,我们每拿一张牌,我们就会去和每一个进行比对,然后放在正确位置,让新拿到的牌和原来有序的序列变成新的有序的序列。
⛳️单趟理解:
如果[0,end]这段区间已经有序,我们想要将下num[end+1]插入到[0,end]这段区间中,使得[0,end+1]这段区间有序。
1.我们首先将num[end]与num[end+1]进行比较,如果num[end+1]的值小于num[end],那么我们就把num[end]移动到num[end+1]。这个一步的时候,num[end+1]就会被覆盖,所以我们可以考虑使用临时变量tmp存num[end+1],最后如果找到正确的位置,我们只需要将tmp的值给它就OK。
2.第一次完了以后,将end-1,然后用tmp和num[end]进行比较。
3.重复上面的步骤,当end减到某个值时,此时num[end]>=tmp就停止,此时[0,end]这个有序区间都<=tmp,end+2以后有序的区间都>tmp,最后我们只需要将tmp给num[end]就完成了单趟。
⛳️多趟理解:
只需要从[0,0]开始,插入n-1个元素就完成了排序。
🏄♂️代码解析:
//插入排序
void Insert_Sort(int* num, int n)
{for (int i = 0; i <= n - 2; i++){//end表示有序区间的最后一个下标//[0,end],end+1int end = i;int tmp = num[end + 1];while (end >= 0){if (tmp < num[end]){num[end + 1] = num[end];--end;}elsebreak;}num[end + 1] = tmp;}
}
🏄♂️冒泡排序和插入排序的比较:
1.冒泡排序如果要提前结束,就是整体有序,其他的都要只要有一次交换,那么就要把整体都交换。(每趟基本都是最坏)
2.但是插入排序,可以移动几个数,然后插入进去,插入位置前面的数就不要移动,这样就比冒泡排序的适应性更强。(每趟基本不是最坏)
三.希尔排序:
因为希尔排序太吊了,会单独用一篇文章讲。在专栏中能找到。
//希尔排序
void Shell_Sort(int* num, int n)
{int gap = n;while(gap>1){//加一的目的让最后一次gap为1gap /= 3+1;//end的最后位置:end+gap<nfor (int j = 0; j+gap<n; j++){int end = j;int tmp =num[j+ gap];while (end >=0){if (tmp < num[end]){num[end + gap] = num[end];end -= gap;}elsebreak;}num[end + gap] = tmp;}}
}
四.验证插入排序和希尔排序的实际实际比较:
🏄♂️头文件:
#pragma once
#include<iostream>
using namespace std;//打印数组
void Print(int* num, int n);//冒泡排序
void Bubble_Sort(int* num, int n);//希尔排序
void Shell_Sort(int* num, int n);//插入排序
void Insert_Sort(int* num, int n);
🏄♂️sort.cpp文件,函数实现文件:
#include<iostream>
#include<algorithm>using namespace std;//打印数组
void Print(int* num, int n)
{for (int i = 0; i < n; i++){printf("%d ", num[i]);}printf("\n");
}//冒泡排序
void Bubble_Sort(int* num, int n)
{//n-1趟for (int i = 0;i <n -1; i++){bool flag = 0;//第一趟[0,n-2]for (int j = 1;j <n-i; j++){if (num[j - 1] > num[j]){swap(num[j-1], num[j]);flag = 1;}}if (flag == 0)break;}
}void Shell_Sort(int* num, int n)
{int gap = n;while(gap>1){gap /= 3+1;//end的最后位置:end+gap<nfor (int j = 0; j+gap<n; j++){int end = j;int tmp =num[j+ gap];while (end >=0){if (tmp < num[end]){num[end + gap] = num[end];end -= gap;}elsebreak;}num[end + gap] = tmp;}}
}void Insert_Sort(int* num, int n)
{for (int i = 0; i <= n - 2; i++){//end表示有序区间的最后一个下标int end = i;int tmp = num[end + 1];while (end >= 0){if (tmp < num[end]){num[end + 1] = num[end];--end;}elsebreak;}num[end + 1] = tmp;}
}
🏄♂️测试文件:
#define _CRT_SECURE_NO_WARNINGS 1
#include"Sort.h"
#include<stdlib.h>
#include<time.h>void Bubble_Sort_Test()
{int n;cin >> n;int* num = new int[n];for (int i = 0; i < n; i++)scanf("%d", &num[i]);Print(num, n);Bubble_Sort(num, n);Print(num, n);delete[] num;
}void Shell_Sort_Test()
{int n;cin >> n;int* num = new int[n];for (int i = 0; i < n; i++)scanf("%d", &num[i]);Print(num, n);Shell_Sort(num, n);Print(num, n);delete[] num;
}void test()
{srand(time(0));const int N = 100000;int* a1 = new int[N];int* a2 = new int[N];for (int i = 0; i < N; i++){a1[i] = rand();a2[i] = a1[i];}int begin1 = clock();Insert_Sort(a1, N);int end1 = clock();int begin2 = clock();Shell_Sort(a2, N);int end2 = clock();//Print(a1, N);//Print(a2, N);printf("Inert_Sort:%d\n", end1 - begin1);printf("Shell_Sort:%d\n", end2 - begin2);delete[] a1;delete[] a2;}int main()
{//Bubble_Sort_Test();//Shell_Sort_Test();test();return 0;
}
几百倍!