堆排序
堆排序
堆的基础知识我们已经在《堆的基础知识》:http://blog.csdn.net/ii1245712564/article/details/45505799里面介绍过了,这次我们将介绍堆的用途之一:堆排序
在诸多的排序算法里面里面,堆排序算是比较快速的了,排序时间消耗为:
我们这里给出一个堆排序的基本思路:
这里我们就按照上面的流程图思路来对每一步骤进行构建
建堆
加入给定我们一个数组
还记得我们在文章《堆的基础知识》里面提到过一个维护堆性质的函数MAX-HEAPIFY(A,i)
吗?MAX-HEAPIFY(A,i)
这个函数是在节点i的左子树和右子树均满足最大堆的性质下进行的。
但是我们在数组PARENT(i)
是一定小于i
的,所以在我们用MAX-HEAPIFY(A,i)
维护节点i
的性质的时候,其子树是一定具有最大堆的性质的,因为其子树LEFTCHILD(i)
和RIGHTCHILD(i)
的最大堆性质是早于其父节点i
构建的,且其运行时间为
下面我们给出建堆的伪代码:
BUILD-MAX-HEAP(A)
for i = A.heapSize/2 downto 1
MAX-HEAPIFY(A,i)
于是我们就可以将数组
好了,在我们构建出最大堆以后,我们需要做的就是来进行堆排序的核心操作啦!
堆排序操作
给定我们一个最大堆1
进行堆性质的维护,之后堆顶元素就成了剩下元素里面最大的,再次提出该元素,重复上面的动作,直到堆只剩下一个元素即可,这个就是堆排序的核心思想了。
为了怎么空间的可重用性,我们不妨将堆顶元素和堆尾部的元素交换,然后让堆大小减小一,当整个操作完毕后,数组
下面我们用伪代码实现:
HEAPSORT(A)
BUILD-MAX-HEAP(A)
while A.heapSize > 1
exchange(A,A.heapSize,1)
A.heapSize = A.heapSize-1
MAX-HEAPIFY(A,1)
代码实现
/*************************************************
* @Filename: heapSort.cc
* @Author: qeesung
* @Email: [email protected]
* @DateTime: 2015-05-06 10:32:10
* @Version: 1.0
* @Description: 堆排序
**************************************************/
#include <iostream>
using namespace std;
// 二叉树的基本操作
#define PARENT(i) ((i)>>1)
#define LEFTCHILD(i) ((i)<<1)
#define RIGHTCHILD(i) (((i)<<1)+1)
void printArray(int * array);
/**
* 交换数组两个位置的元素
* @param array 数组
* @param pos1 位置1
* @param pos2 位置2
*/
void exchange(int * array , int pos1 , int pos2)
{
if(array == NULL)
return;
int temp = array[pos1];
array[pos1] = array[pos2];
array[pos2] = temp;
}
/**
* 维护最大堆的性质
* @param array 传入的堆数组,注意此数组是从位置1开始,位置0存放堆的大小
* @param pos 需要更新的位置
*/
void maxHeapify(int * array , int pos)
{
if(array == NULL)
return;
if(pos > array[0])// 超出堆的大小
return;
int leftChild = LEFTCHILD(pos);
int rightChild = RIGHTCHILD(pos);
// 找到最大的那个
int maxPos = pos;
if(leftChild <= array[0] && array[leftChild] > array[pos] )
maxPos = leftChild;
if(rightChild <= array[0] && array[rightChild] > array[maxPos])
maxPos = rightChild;
// 交换父节点与子节点
if(maxPos != pos)
{
exchange(array , maxPos , pos);
maxHeapify(array , maxPos);
}
}
/**
* 堆排序
* @param array 传入需要排序的数组,注意此数组是从位置1开始,位置0存放数组数组元素的个数
*/
void heapSort(int * array)
{
if(array == NULL)
return;
// 首先构建最大堆
for(int k = array[0]/2 ; k >=1 ; --k)
{
maxHeapify(array , k);
}
int arraySize = array[0];
//下面开始每次都取出堆里面堆顶位置的元素,再次进行堆性质维护
for(int k = array[0] ; k >=2 ; --k)
{
exchange(array , 1, k);
array[0] -= 1;
maxHeapify(array , 1);
}
array[0] = arraySize;
}
void printArray(int * array)
{
if(array == NULL)
return;
int arraySize = array[0];
for(int k = 1 ; k <= arraySize ; ++k)
{
cout<<array[k]<<"\t";
}
cout<<endl;
}
int main(int argc, char const *argv[])
{
int array[]={0,4,1,3,2,16,9,10,14,8,7};
array[0] = sizeof(array)/sizeof(int) - 1;
cout<<"before sort:"<<endl;
printArray(array);
heapSort(array);
cout<<"after sort:"<<endl;
printArray(array);
return 0;
}
运行结果为:
before sort:
4 1 3 2 16 9 10 14 8 7
after sort:
1 2 3 4 7 8 9 10 14 16
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。