目录
一,计数排序
二,冒泡排序(Bubble Sort)
三,快速排序(Quick Sort)
四,桶排序(Bucket Sort)
五,小哼买书
从无到有掌握最基础的算法
多学点算法,做题时就能拓宽思路;一种简单的算法思路,能将看起来很复杂的问题,变得简单
关于冒泡排序,快速排序和桶排序
冒泡
最慢的,只在数据量很小时能用,时间复杂度为O(n^2)
快排(推荐)
万金油(最常用),包含分治的思想,复杂度为O(N*logN),类似sort()
桶排序
时间复杂度最低(最快),为O(N + C),N为循环次数,C为N*(logN - logM),M为桶数量
也含有分治的思想
它利用函数中映射的关系(即桶与数据一对多的关系),减少了大量比较,所以时间复杂度很低,正因为如此,导致空间复杂度很高,时间越快占用空间越多(桶的数量越多),当样本跨度较大时不适用,比如对1000001,1,200099999,88进行排序,不会考虑桶排序
它只适用于数据均匀分布,元素值较为集中的序列
一,计数排序
它是桶排序的简化版本
比桶排序还浪费空间,比如需要排序的范围 0 ~ 2e9(2*10^9),就需要2*10^9个桶,也就是申请2*10^9个变量,即使只对3个数排序,仍需要这么大的空间,就很浪费
eg: 5个同学分别考了5分,3分,5分,2分,8分,将分数从大到小排序并输出
#include<iostream>
using namespace std;
int a[9]; //全局数组自动初始化为0
int main()
{
int t;
for(int i = 0; i < 5; ++i) { //输入5次
cin>>t; //分数
a[t]++; //这个分数出现的次数
}
for(int i = 8; i >= 0; --i) //i为分数
for(int j = 0; j < a[i]; ++j) //j为次数
cout<<i<<" ";
return 0;
}
5 3 5 2 8
8 5 5 3 2
二,冒泡排序(Bubble Sort)
每次比较相邻两个元素,如果顺序不对,就交换
比如下图就是一趟冒泡排序
对n个数进行冒泡,需要将 n - 1 个数归位,也就是进行 n - 1 趟操作
eg: 有5个同学和自己的分数,Amy 5分, Mike 10分, Bob 6分, Girl 4分, Jhon 5分,按照分数从高到低输出他们的名字(涉及结构体)
#include<iostream>
using namespace std;
struct stu
{
char name[20];
int score;
};
int main()
{
struct stu a[10], t; //t要声明为结构体的变量
int n = 5;
for(int i = 0; i < n; ++i)
cin>>a[i].name>>a[i].score;
for(int i = 0; i < n - 1; ++i) //n - 1趟
for(int j = 0; j < n - i - 1; ++j) { //每趟比上一趟少比较一次
if(a[j].score < a[j + 1].score) {
t = a[j];
a[j] = a[j + 1];
a[j + 1] = t; //交换结构体两个变量
}
}
for(int i = 0; i < n; ++i)
cout<<a[i].name<<" ";
return 0;
}
Amy 5 Mike 10 Bob 6 Girl 4 Jhon 5
Mike Bob Amy Jhon Girl
三,快速排序(Quick Sort)
先上图
假设左端第一个数字6为基数(便于后续参照),根据传入的左右边界声明 i, j两个游标
j游标先行,(假设从小到大排序)直到 j游标 指向的数字小于基数6,停止
i游标后走,直到 i游标 指向的数字大于基数6
i, j 指向的数字交换
重复上面的过程直到 i, j相遇(指向同一个数,这个数必然比基数6小)
然后相遇的数字再与左端基数6交换
此时中间的左边都比中间小,中间的右边都比中间大
后续分别对6的左边和右边递归就好
#include<iostream>
using namespace std;
int a[66666], n; //定义全局变量,可在子函数使用
void quick_sort(int left, int right)
{
if(left > right)
return; //终止条件,说明当前数组长度为1或物理不存在
int i, j, base;
i = left, j = right, base = a[left];
while(i < j) {
while(i < j && a[j] >= base)
j--; //j游标先行
while(i < j && a[i] <= base)
i++;
if(i < j) {
a[i] = a[i]^a[j];
a[j] = a[i]^a[j];
a[i] = a[i]^a[j]; //异或交换两个数
}
}
a[left] = a[j];
a[j] = base; //基数与指向的数交换
quick_sort(left, j - 1); //对左边递归
quick_sort(j + 1, right); //对右边递归
}
int main()
{
cin>>n; //n个数
for(int i = 0; i < n; ++i)
cin>>a[i];
quick_sort(0, n - 1);
for(int i = 0; i < n; ++i)
cout<<a[i]<<" ";
return 0;
}
7
-50 666 99 12 -2 36 2
-50 -2 2 12 36 99 666
详细点的可以看这个
(5条消息) C++快速排序之整型数组_码龄11天的博客-CSDN博客_c++整数排序
四,桶排序(Bucket Sort)
与快排的区别:
快排将集合分为两个桶,对两个桶按快排排序,它是在集合本身上的排序,即原地排序
桶排序将集合分为多个桶,在额外空间上对桶进行排序,避免了构成桶过程中元素的比较和交换
算法过程:
1,Max和Min
遍历数组,得到最大值Max和最小值Min
2,桶的个数
(Max - Min) / 间隔 + 1 = 桶的个数,
比如Max == 666, Min == -28,每个桶间隔假设100,则桶的个数为 694 / 100 + 1 = 7
3,放入桶
遍历数组,将元素加入对应区间的桶中
4,对桶排序(方法自选)
5,将桶内元素放回原序列
意思就是这么个意思,不想敲了,书里没有
五,小哼买书
就是对输入的数组进行排序和去重,很简单我就不写了
可以考虑先排序,如果和上一个不相等,就输出
相等则代表重复,不输出