【Mark】啊哈!算法

一大波数正在靠近——排序


  • 最快最简单的 桶排序
  • 冒泡排序
  • 最常用的 快速排序
  • 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.

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值