算法入门(BuBuBu)
相关数据结构:
栈 队列 链表 树 并差集 堆 图等;
相关算法:
排序 枚举 深度和广度优先搜索 图的遍历 图中最短路径算法 最小生成树算法 割点和割遍算法 二分图的最大匹配算法等;
排序算法
简单的桶排序
特点:
- 如果需要排序n个数,数的范围是0-m,可以使用一个1维数组a[m+1],记录0-m这m+1个数出现的次数,可以看做是m+1个桶,各自装了对应数出现的次数(数值即下标),循环桶 及 各桶中数字的出现次数,即可实现对n个数的排序;
- 时间复杂度:O(m+n);
缺点:
每一个桶记录的次数,无法对应具体分数的其他信息;
很浪费空间,申请的桶个数需要是数据范围数m+1,但可能实际需要排序的数字很少;排序小数的话也会很麻烦;
冒泡排序
特点:
- 每次比较两个相邻的元素,如果它们的顺序错误就把他们交换过来;一直比较,最后一个就会是最大/最小值;如同一个气泡,向上“起泡”,直到最后一位;
- 第一趟会得到一个最大/小值,第二趟比较会得到第二大/小的值… 每一趟只能将一个数归位,已经归位的不必再参与排序;如果是n个数需要排序,只需将n-1个数归位,只需要n-1趟即可;
- 时间复杂度:O(n^2);
应用:
结合复杂的数据结构数组,可以避免 简单桶排序 的第一个问题;
缺点:
时间复杂度很高,执行效率低;
快速排序
特点:
- 最常用的排序;相比于 桶排序的浪费空间,冒泡排序的“慢”,快速排序就要好多了;
- 首先从待排序的数据中随机选择一个 基准数(P),接下来将这个序列中比基准数大的放右边,比之小的放左边(假设从小到大排序);
实现方式:
- 分别从初始序列的左右两端”探测“:从左往右找直到遇到一个比P大的数,再从右向左找一个比P小的数,将两者交换;可以使用两个”哨兵“变量i、j,开始时分别指向需要排序的序列的最左边和最右边;
- 如果P选择的是最左边的数,则右哨兵j可以先行探测;(一定是从j开始,否则最后i、j相遇时,与P交换的会是一个比P大的值)
- 当i、j相遇时,将相遇点与基准点交换;完成第一轮探测;
- 基于P分割的两个序列,继续使用上述方式;
快速排序的每一轮处理 其实就是将这一轮的基准数 归位;所有基准数都归位了,排序也就结束了;
相比与冒泡排序交换相邻,快速排序的交换是跳跃式的;最坏的情形,其时间复杂度和冒泡一样都是O(n^2);平均的时间复杂度:O(n*log n);
快速排序基于二分的思想;基于while循环和递归调用,可以方便的写出一个递归的快速排序;非递归的快排使用栈实现,参考之前写过的一篇《 排序算法-快速排序》;
其他排序
选择排序、计数排序、基数排序、插入排序、归并排序、堆排序(基于二叉树);