一大波数正在靠近——排序
- 最快最简单的 桶排序
- 冒泡排序
- 最常用的 快速排序
- ISBN号问题
各时间复杂度排序
- O(1) < O(logn) < O(n) < O(nlogn) < O(n2) < O(n^3) < O(2^n)
简单桶排序,真正的桶排序要比这个复杂一些;
- 时间复杂度 O(M + N),这是一个非常快的排序算法;
要命的是,它非常浪费空间!
Question:数据范围0~1000,输入数据,按序输出 (需1001个桶)
#include<iostream>
#include<cstdlib>
using namespace std;
int main()
{
int book[1024]; //能装0~1023之间的数的桶
int n,t;
for(int i = 0; i < 1024; i++) {
book[i] = 0; //不给桶初始化的话会出错
}
cout << "请输入待装桶的元素的个数:" << endl;
cin >> n;
cout << "请依次输入数(限制范围:0~1023):" << endl;
for(int i = 1; i <= n; i++) {
cin >> t;
book[t]++; //输入数后,相应编号的桶中计数加一
}
for(int i = 0; i < 1024; i++) {
for(int j = 1; j <= book[i]; j++) { //桶中有几个计数,就输出几次桶编号
printf("%d ", i);
}
}
getchar();getchar();
system("pause");
return 0;
}
冒泡排序
冒泡排序的基本思想是:每次比较两个相邻的元素,如果它们的顺序错误就把它们交换过来;
核心部分,双重嵌套循环;
- 时间复杂度 O(N2),这是一个非常高的时间复杂度;
Question:现在分别有5个人的名字和分数:huhu 5分、haha 3分、xixi 5分、hengheng 2分、gaoshou 8分,请按分数从高到低,输出名字
#include<iostream>
using namespace std;
struct student {
char name[21];
int score;
}; //创建一个结构体,用来存储姓名和分数
typedef student Student;
int main()
{
Student a[124],t;
int num;
cout << "the number of students: ";
cin >> num;
for (int i = 0; i < num; i++) {
cout << "name: ";
cin >> a[i].name;
cout << "score: ";
cin >> a[i].score;
}
for (int i = 0; i < num - 1; i++) { //排n - 1遍,最后一遍不用排
for (int j = 0; j < num - i - 1; j++) { //从第一位开始比较直到最后一个尚未归位的数,需要- 1不然会越界(比较时有a[j+1])
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 < num; i++) {
cout << a[i].name << " ";
}
getchar();
getchar(); //用来暂停程序,以便查看程序输出的内容,可用system("pause");等来代替
return 0;
}
可以加一个判断:若已有序,则终止冒泡
链接:ADT_起泡排序的实现代码.
快速排序,
- 先找一个数为基准数 (我选第一个数),将基准数放在辅助空间里;
然后从右开始找比基准数小的数,标记为 high,找到后将其值赋值给基准数(第一个位置),
再从基准数开始从左往右找一个比基准数大的数,标记为 low,找到后将其值赋值给 high 标记位置;
再从 high 的开始找,找到赋值给 low,然后重复操作直到 low >= high 为止;
将辅助空间的基准数赋值给 low high 交界位置,然后此位置的左右两边重复此操作,直到排序完成;
自己按理解叙述的,并不严谨; - 时间复杂度 最坏为 O(N2);平均时间复杂度为 O(N logN);
Question:快速排序
链接:快排.
ISBN号问题
Question: 输入有两行,第一行为一个正整数,表示 n 个同学参与调查 n ≤ 100;第二行有 n 个用空格隔开的正整数,为每本书的 ISBN 号 (假设范围 1~ 1000);
输出两行,第一行为一个正整数 k,表示需要买多少本书;第二行为 k 个用空格隔开的正整数,为从小到大排好序的 ISBN 号
程序运行时间限制1秒
解决思路:先去重,再排序 或 先排序,再去重
本题用桶排序先去重后排序比较快
#include<iostream>
using namespace std;
int main() {
int n = 0;
int tong[1001]; //数据范围 0 ~ 1000
for (int i = 0; i < 1001; i++) {
tong[i] = 0; //初始化
}
cout << "input firstLine:";
cin >> n;
for (int i = 0; i < n; i++) {
int num = 0;
cin >> num;
tong[num]++;
}
for(int i = 0; i < 1001; i++) {
if(tong[i]) {
cout << i << " ";
}
}
return 0;
}
- 运行结果正确,编译时间 0.73s 输出大小 1.8324MiB
栈、队列、链表
- 队列
- 栈
- 纸牌游戏 小猫钓鱼
- 链表
- 模拟链表
- 链接 栈、队列、链表.
枚举!很暴力
- 坑爹的奥数
- 炸弹人
- 火柴棍等式
- 数的全排列
- 链接 枚举!很暴力.
万能的搜索
- 不撞南墙不回头 深度优先搜索
- 解救小哈
- 层层递进 广度优先搜索
- 再解炸弹人
- 宝岛探险
- 水管工游戏
图的遍历
- 深度和广度优先究竟是指啥
- 城市地图 图的深度优先遍历
- 最少转机 图的广度优先遍历
最短路径
- 只有五行的算法 Floyd-Warshall
- Dijkstra 算法 迪杰斯特拉 单源最短路
- Bellman-Ford 解决负权边
- Bellman-Ford 的队列优化
- 最关路径算法对比分析
神奇的树
- 开启 “树” 之旅
- 二叉树
- 堆 神奇的优先队列
- 擒贼先擒王 并查集
更多精彩算法
- 镖局运镖 图的最小生成树
- 再谈最小生成树
- 重要城市 图的割点
- 关键道路 图的割边
- 我要做月老 二分图最大匹配
End.