堆排序
2015-11-17 08:55
162 查看
转载自:/article/2357990.html 堆
堆是一个完全二叉树的数组对象。树每一层都是满的,最后一层可能除外(从一个节点的左子树开始填)。
给定节点i,可以很容易计算父节点和子节点的位置。
Parent(i)=floor(i/2):i/2再向下取整
LeftChild(i)=2*(i+1)-1:因为i从0开始,这和c语言的数组从0开始相对应。可以用左移运算代替*,即LeftChild(i)=(i+1)<<1-1;
RightChild(i)=2*(i+1):RightChild(i)=(i+1)<<1;
堆排序
堆排序的时间复杂度是O(nlgn),是比较有效率的一种。其使用的是最大堆。最大堆的意思是父节点的值>=孩子的值。那么第0个节点必定是该堆的最大值。所以,堆排序的思想就是每次循环把最大值移走,然后从剩下的节点重新建立最大堆。
第一步:建立堆的结构体。
[cpp]
typedefstructheap_t{
int*arr;//pointforanarraytostoreheapvalue.
intheapMaxIndex;//heapelementmaxindexnumber
intarrLength;//arraylengthofarr
}Heap;
其中arr指针指向的是存放堆数据的数组。
heapMaxIndex是数组最大的序号。如数组定义为a[10],那么heapMaxIndex的值应该为9.
第二步:保持堆的性质。
这一步是堆排序的基础。这里将功能写成一个函数名为voidmaxHeapify(Heap*hp,unsignedintnodei),这个函数用于让一个数组变成一个符合堆性质的数组。时间复杂度为O(h),h是堆所属二叉树树的高度=lgn(n是节点个数)。
思想是:从一个节点i,和他的孩子leftchild(i),rightChild(i)中找到最大的,然后其索引存放在largest中。如果i是最大的。那么i为根的子树已经是最大堆,程序结束。
否则i的某个子节点有最大元素,那么i的值和largest的值交换。下标为largest的节点在交换后作为父节点,那么他可能又违反堆性质,因此递归调用该函数。
[cpp]
voidmaxHeapify(Heap*hp,unsignedintnodei)
{
unsignedintl=(nodei+1)<<1-1;//leftchild=2i-1,-1?:arr[0..n-1]
unsignedintr=(nodei+1)<<1;//rightchild=2i
unsignedintlargest=0;
intheapMaxI=hp->heapMaxIndex;
if(l<=heapMaxI&&hp->arr[l]>hp->arr[nodei])
largest=l;
else
largest=nodei;
if(r<=heapMaxI&&hp->arr[r]>hp->arr[largest])
largest=r;
if(largest!=nodei)
{
//exchange
inttmp;
tmp=hp->arr[largest];
hp->arr[largest]=hp->arr[nodei];
hp->arr[nodei]=tmp;
maxHeapify(hp,largest);
}else{
return;
}
}
相关文章推荐
- 用VS2010打开VS2012项目解决方案
- Cocos2D:塔防游戏制作之旅(十)
- CentOS 7中没有ifconfig命令,而且不能发现eth0
- Cocos2D:塔防游戏制作之旅(十)
- Cocos2D:塔防游戏制作之旅(十)
- Ⅰ.2.2 如何调用Qt对象的函数
- ubuntu14.04,安装JDK1.8(JAVA程序需要的开发、运行环境)
- ubuntu14.04,安装JDK1.8(JAVA程序需要的开发、运行环境)
- ubuntu14.04,安装JDK1.8(JAVA程序需要的开发、运行环境)
- 网购假货必将葬身人民差评的汪洋大海
- java yeild相关
- Ⅰ.2.1 如何访问Qt对象
- 通过文件对话框导入图像问题
- java synchronized详解
- 在CentOS上安装PostgreSQL9.4.5
- 构建高并发高可用的电商平台架构实践
- FZU 1894,单调队列入门
- AppRtc在云服务器部署日记
- 未能加载文件或程序集“XXX”或它的某一个依赖项。试图加载格式不正确的程序
- c#复习内容