🎁个人主页:我们的五年
🔍系列专栏:排序算法
🎉欢迎大家点赞👍评论📝收藏⭐文章
一.冒泡排序:
时间复杂度: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+1
int end = i;
int tmp = num[end + 1];
while (end >= 0)
{
if (tmp < num[end])
{
num[end + 1] = num[end];
--end;
}
else
break;
}
num[end + 1] = tmp;
}
}
🏄♂️冒泡排序和插入排序的比较:
1.冒泡排序如果要提前结束,就是整体有序,其他的都要只要有一次交换,那么就要把整体都交换。(每趟基本都是最坏)
2.但是插入排序,可以移动几个数,然后插入进去,插入位置前面的数就不要移动,这样就比冒泡排序的适应性更强。(每趟基本不是最坏)
三.希尔排序:
因为希尔排序太吊了,会单独用一篇文章讲。在专栏中能找到。
//希尔排序
void Shell_Sort(int* num, int n)
{
int gap = n;
while(gap>1)
{
//加一的目的让最后一次gap为1
gap /= 3+1;
//end的最后位置:end+gap<n
for (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;
}
else
break;
}
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<n
for (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;
}
else
break;
}
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;
}
else
break;
}
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;
}
几百倍!