简单排序算法时间空间复杂度分析及应用(5)-堆排序
堆排序,属于选择排序的一种,两层嵌套循环,内循环结束后确定最大或最小的值,然后和外循环的节点交换值,待外循环结束后,整个数组排序完成。
在所有的排序算法中,核心问题是:循环体有几个?嵌套循环?外循环体的起始节点和最终节点?内循环的?算法的最初状态以及最终状态(包括确定区域,非确定区域,区元,循环节点位置)?算法单元操作(指:在每个循环节点都会进行的操作)?
当我们把上面这些搞清楚后(其实一个算法作用过程中也就这些概念),那我们就对这个算法算是详细了解了,你就可以在1分钟内在工作中对这个算法运用自如,你也可以对算法进行优劣比较和改进。当然还有其他细化的算法中的概念,循环方向,确定节点和非确定节点等等。
堆排序,选择排序,冒泡排序 ,直接插入排序,二分插入排序这四种算法,都有两种区域,确定区域和非确定区域,外循环都是对整个体进行循环,但是在内循环中,堆排序,选择排序,冒泡排序都是对非确定区域进行循环;但是插入排序是对确定区域进行循环操作。
数据集合的排列顺序对这几个算法性能无影响的是:堆排序。
算法代码:
/*
* 堆排序
*/
public static void heapSort(){
for(int i = array.length - 1 ; i > 0 ; -- i)
{
for(int j = (i+1)/2 - 1 , max , k ; j >= 0 ; -- j)
{
//进行堆排序将最大的值选出来到根节点
if((j+1)*2 <= i )//如果循环得第一个节点存在右子节点
max = array[(j+1)*2] > array[(j+1)*2-1] ? (j+1)*2 : (j+1)*2 -1;
else
max = (j+1)*2-1;
max = array[j] > array[max] ? j : max;//父节点和最大的子节点比较
if(max != j)//如果最大的不是父节点自身,就将最大的子节点的值和父节点交换
{
k = array[max];
array[max] = array[j];
array[j] = k;
}
}
算法描述(算法描述我是引用其他大神,我所有的博客重点不是对算法概念的讲解,这些算法的描述请自己网上查阅,我写这些
算法的分析及应用技术博客是在这些算法概念和应用实践的基础上总结的新的理解方式:对算法结构进行剖析,而剖
析所创建的新概念在前几篇博客内都集中提到过,算法的图文解析也有标注这些概念。我的目的是:让大家对算法养
成一种潜意识观点,算法是立体的,是有结构(架构)的,和建筑物一样,有设计图,有柱子,有砖头,有钢筋... , 是能被识别的,
且能轻松运用的。):
最大堆的堆调整我们会这么做:
1、在对应的数组元素A[i], 左孩子A[LEFT(i)], 和右孩子A[RIGHT(i)]中找到最大的那一个,将其下标存储在largest中。
2、如果A[i]已经就是最大的元素,则程序直接结束。
3、否则,i的某个子结点为最大的元素,将A[largest]与A[i]交换。
4、再从交换的子节点开始,重复1,2,3步,直至叶子节点,算完成一次堆调整。
算法分析:外循环方向是由右向左,内循环同外循环一样;外循环起始节点是数组的最后一个元素,最终节点是数组的
第二个元素;内循环的起始节点是外循环的循环节点的父节点,最终节点是根节点;算法中的元操作是内循环中
循环节点取自己和两个或一个子节点(内循环的起始节点可能只有左子节点)的最大值;
以上就堆排序算法的全部过程解析结果。
复杂度分析: 最差时间复杂度O(n log n) ,最好时间复杂度O(n log n),平均时间复杂度O(n log n),最差空间复杂度是O(n )