排序算法
2021-05-17 00:27
标签:输入参数 中间 需要 空间 排序算法 void 思考 要求 最小堆 排序算法两阶段 第一阶段(比较排序) 第二阶段(非比较排序) 插入排序的主要思想: 将当前的元素放入前面合适的位置 插入排序的实现细节: 插入排序的小结: 插入排序是 插入排序的时间复杂度是\(\Theta(n^2)\) 合并排序的主要思想: 使用分而治之的思想,分治法的核心在 分:将一个需要排序的数组,分成对称的左右两个 合:将两段升序数组合并 合并排序的实现细节: 合并排序的小结: 合并排序需要最多的额外 算法的复杂度是\(\Theta(nlogn)\) 个人认为:该算法设计的精妙之处在于每一次的修改都是直接作用在数组本身,这样可以是分合过程十分自然的连为一体! 堆排序所使用到的数据结构:最大堆/最小堆 形式化的结构: a[15] : {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15} 抽象式的结构:完全二叉树 7 8 9 10 11 12 13 14 注:在实现过程中发现诸多计算机数学中的细节问题 最大(最小)堆的性质: 对于任意一个\(node[i]\),其父亲节点\(node[\frac{i-1}{2}]\),孩子节点分别为\(node[2\times i]\)和\(node[2\times i+1]\) 。(以最大堆为例)每个节点必然满足大于其左右任意孩子节点。 堆排序涉及到的三个过程以及具体实现 heap_sort小结: heap_sort中最重要的过程是max_heapify过程,对该过程进行适当修改可以适应不同算法的要求。 build_max_heap算法采用 heap_sort方法:初始状态-过程状态-结束状态。 快速排序的主要思想是 将一个数放在合适的位置上,然后左右递归。 \([ \dots \forall mi\ ,\ x_n \ge x_i \dots]\) 算法实现细节: 对递归过程的文字描述: 每次等待排序的是数组最后一个元素,从头到尾对数组进行一次遍历,再标记一个分割线,如果当前元素小于待安插元素,将分界线右移一位,将该元素放进左边,若该元素大于待安插元素,则进行下一次判断。 本算法的初始状态为在没有开始之前,没有元素在左边。 过程演示: 个人认为本算法中唯一难点就在于当前元素小于待安插元素时,分割线右移,小于元素与分割线占位元素交换,当然将两个操作顺序交换也是完全没有问题的。 首先,比较算法的最坏下界一定是\(\Theta (nlgn)\),关于这点可以使用决策树来解释(此处不做解释)。所以非比较算法一定是在特定的问题条件下,牺牲空间或者其它非时间因素,完成对算法的优化。 使用条件:待排序样本满足 \(X = \{x|a\le x \le b,a、b\in Z \}\) 使用思想: hash 映射 注意数组下标的调试 基数排序还是非常有意思的过程下面模拟下: 其伪代码 桶排序的使用场景比较特殊: 桶排序适用于均匀分布的数组,期望与最终待分类的样本会被均匀的分布到一个个小桶中(这貌似有点经典统计学派)。所以就认为事先将其划分出一个个大小相等的桶,然后将待分配元素放在合适桶中,最终整个数组就是一个天然有序! 排序算法 标签:输入参数 中间 需要 空间 排序算法 void 思考 要求 最小堆 原文地址:https://www.cnblogs.com/TheTinkerJ/p/9748249.html排序算法
第一阶段:比较排序
插入排序
public int[] insert_sort(int[]a){
int len = a.length;
for(int i = 0;i
原地排序
最多只需要一个额外空间,用于中间的交换合并排序
合
public void merge(int[]a,int p,int q,int m){
// [p-----m][-----q]
int len_l = m-p+2;
int len_r = q-(m+1)+2;// ****容易出错的部分!***
int[] left = new int[len_l];
int[] right= new int[len_r];
for(int i=p;i
空间
是数组一倍的空间堆排序
0
1 2
3 4 5 6
public int[] max_heapify(int[]a,int i,int size){
/*
一个基本假设:
a[i]是待插入元素,其左右两边的堆是最大堆
a[i]有可能比左右两个最大堆的子堆还要小
*/
//对输入参数的解释
// a 输入数组 i 需要调整的根节点
// 其左儿子 left = a[2×i]
// 其右儿子 right = a[2×i+1]
// 目标是使元素a[i]贪心下沉到一个合适的位置
// 使合并后的堆任然是一个 max_heap
// size参数的设计是为了方便配合heap_sort
// 由于heap_sort过程中需要在衰减的空间中进行原地排序
int max_idx = i;
int left = 2*(i+1)-1;
int right = 2*(i+1);
if(left
自底向上
的策略,首先构造满足条件左右子树,最后在层层推进将待插入元素使用heap_sort方法,插入到合适的位置。快速排序
分治法
public int[] quick_sort(int[]a,int p,int q){
if(p
|]*****^**************$ // |分割线,*非末尾元素,$待安插元素
|*]****^**************$ // ]算法当前遍历位置
|**]***^**************$ // *表示大于$的数,^表示小于$的数
|***]**^**************$
|****]*^**************$
|*****]^**************$
|*****]^**************$
---------------------------过程当放大
*|****]^**************$
^|****]***************$
---------------------------
^|*****]**************$
...
^|*******************]$
^$|*******************]
第二阶段:非比较排序
计数排序
public int[] count_sort(int[]a,int min,int max){
int[]b = new int[a.length];
int[]count = new int[max-min+1];
/*
基数排序的主要流程
第一轮 计数
第二轮 累加
第三轮 排序
*/
for(int i = 0;i
基数排序
原始
个位
十位
百位
329
72
0
7
20
3
29
457
35
5
3
29
3
55
657
43
6
4
36
4
36
839
45
7
8
39
4
57
436
65
7
3
55
6
57
720
32
9
4
57
7
20
355
83
9
6
57
8
39
for i 最小比较位 to 最大比较位
使用合适稳定的比较排序对目标数组进行排序
桶排序
上一篇:RESTFul API最佳实践
下一篇:排序算法,以php为代码示例