排序算法学习

时间复杂度为O(n²)的三种排序方法、基于比较的三种排序方法

选择排序

基本思路:从 i 到 n - 1 依次遍历,找出最值与当前位置互换

简单优化:可以同时记录最大值和最小值,两边开工

变式解决问题:最小交换次数

代码实现

void mysort(int s[], int n)
{
for (int i = 0; i < n - 1; i++)
{
int minpos = i;
for (int j = i + 1; j < n; j++)
{
if (s[j] < s[minpos])
minpos = j;
}
if (minpos != i)
{
int tmp = s[i];
s[i] = s[minpos];
s[minpos] = tmp;
}
}
}

冒泡排序

基本思路:进行不断比较

简单优化:

  1. 可以使用nflags记录是不是有交换,如果没有交换那么停止排序;
  2. 使用一个数记录最后面的交换的地方,在这个数字后面的数字无需交换

代码实现

void mysort(int s[], int n)
{
int last = n - 1;
int nflags = 0;
do
{
nflags = 0;
int tmp_last = 0;
for (int i = 0; i < last; i++)//注意:循环变量在循环内部一定不能改变
{
if (s[i] > s[i + 1])
{
int tmp = s[i + 1];
s[i + 1] = s[i];
s[i] = tmp;
nflags = 1;
tmp_last = i ;
}
}
last = tmp_last;
} while (nflags);
}

插入排序(简单版本)

不断进行对比,然后插入。

三种不基于比较的排序(时间复杂度为O(n), 但是数据的变化范围要尽可能地小)

计数排序(桶排序的变种)

注意,如果是成绩等等数据范围有限的数字排列,桶排序的时间复杂度竟然是O( n )全场最低

#include <iostream>
#include <map>
using namespace std;
int a[1000];
int b[1000];
map<int, int >bucket;
void my_sort(int* s, int n)
{
int max_num = s[0];
int min_num = s[0];
map<int, int >t;
for (int i = 0; i < n; i++)
{
if (s[i] > max_num)
max_num = s[i];
if (s[i] < min_num)
min_num = s[i];
t[s[i]]++;
}
for (int i = min_num,k = 0; i <= max_num; i++)
{
int pos = 0;
while (t[i]--)
s[k++] = i;
}
}
void print(int s[], int n)
{
for (int i = 0; i < n; i++)
cout << s[i] << ' ';
}
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++)
cin >> a[i];
my_sort(a, n);
print(a, n);
}

基数排序

类似于桶排序:

  1. 但是可以更好地在内存不够的情况下拓展桶排序的数目(可以设置的位数不一定是一位,还可以多次设置)
  2. 可以完成多级排序

重点是类似于队列,不同队列,从左到右,相同队列,从前到后

避坑:从优先级最后按照顺序向前排列

代码实现

#include <iostream>
#include <map>
#include <cmath>
using namespace std;
int a[1000];
int b[1000];
void jishupaixu(int *s, int n)
{
for (int t = 0; t < 10; t++)
{
int a[10][1000] = { 0 };
int pos[10] = { 0 };
int shang = pow(10, t);
for (int i = 0; i < n; i++)
{
int hs = s[i] / shang % 10;
a[hs][(pos[hs]++)] = s[i];
}
for (int i = 0, p = 0; i < 10; i++)
{
for (int j = 0; j < pos[i]; j++)
{
s[p++] = a[i][j];
}
}
}
}
void print(int s[], int n)
{
for (int i = 0; i < n; i++)
cout << s[i] << ' ';
}
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++)
cin >> a[i];
jishupaixu(a, n);
print(a, n);
}

桶排序

桶排序确实比较拉胯,它的意思是分一些桶,把数据放在一个区间范围内的桶中,然后分别排每一个桶,最后输出;

但是桶的数据结构也很拉胯,

  1. 数组会增加空间消耗
  2. vector会增加时间消耗
  3. list直接是冒泡排序级别的

所以一般不用,如果要使用,就是先分成几个区间中的桶,然后对每个桶使用sort。。。。。。。。。

两种大神级别排序

归并排序

代码实现

  1. 注意这里有一个临时数组:b
  2. 在归并实现的时候:
    • 是左右两个数组比较后放入备份数组
      1. 是否有效,即有没有用完
      2. 大小关系
#include <iostream>
using namespace std;
int a[1000];
int b[1000];
void my_sort(int l, int mid, int r)
{
int lpos = l, rpos = mid + 1;
for (int i = l; i <= r; i++)
{
if (lpos <= mid && (a[lpos] <= a[rpos] || rpos > r))
{
b[i] = a[lpos++];
}
else
{
b[i] = a[rpos++];
}
}
for (int i = l; i <= r; i++)
a[i] = b[i];
}
void dive(int l, int r)
{
int mid = (l + r) / 2;
if (l < r)
{
dive(l, mid);
dive(mid + 1, r);
}
my_sort(l, mid, r);
}
void print(int s[], int n)
{
for (int i = 0; i < n; i++)
cout << s[i] << ' ';
}
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++)
cin >> a[i];
dive(0, n - 1);
print(a, n);
}

快速排序

#include <iostream>
using namespace std;
int a[1000];
int b[1000];
void quike_sort(int l, int r)
{
int i = l;
int j = r;
int mid = (l + r) >> 1;
int t = a[mid];//一定要拿出这个基准值,因为后面会变化
while (i <= j)
{
while (a[i] < t) i++;//一定是小于,为了让左指针在基准值之前停留下来
while (a[j] > t) j--;//同上
if (i <= j)
{
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
i++;
j--;
}
}
if (l < j)
quike_sort(l, j);
if (i < r)
quike_sort(i, r);
}
void print(int s[], int n)
{
for (int i = 0; i < n; i++)
cout << s[i] << ' ';
}
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++)
cin >> a[i];
quike_sort(0, n-1);
print(a, n);
}
posted @   心坚石穿  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示