转自:http://blog.csdn.net/cjf_iceking/article/details/7928254
堆是一种完全二叉树结构,并且其满足一种性质:父节点存储值大于(或小于)其孩子节点存储值,分别称为大顶堆、小顶堆。堆一般采用数组进行存储(从下标为1开始),则父节点位置为i,那么其左孩子为2*i,右孩子为2*i + 1。
一. 算法描述
堆排序主要分为两个过程:
(1)先使长度为N数组形成一个N个节点组成的大顶堆
(2)然后将堆顶数据与末尾数据交换,再对N-1长的堆调整为大顶堆;反复进行,直到堆节点数为1结束堆排序。
从无序数组形成大顶堆过程如下图所示:
大顶的堆的形成要由下到上,子节点先形成大顶堆后,再考虑父节点,这样做逻辑比较清晰;形成大顶堆后在按照步骤2就可以完成堆排序。
二. 算法分析
平均时间复杂度:O(nlog2n)
空间复杂度:O(1) (用于交换数据)
稳定性:不稳定
三. 算法实现
- //交换data1和data2所指向的整形
- void DataSwap(int* data1, int* data2)
- {
- int temp = *data1;
- *data1 = *data2;
- *data2 = temp;
- }
- /********************************************************
- *函数名称:SlipDown
- *参数说明:pDataArray 无序数组;
- * iCurNode为堆中需要调整的节点
- * iDataNum为数组长度
- *函数返回:分割后的分割数位置
- *函数说明:调整iCurNode处的节点,形成大顶堆
- *********************************************************/
- void SlipDown(int *pDataArray,int iCurNode,int iDataNum)
- {
- int temp = pDataArray[iCurNode]; //记录需要调整的节点值
- for (int iNextNode = iCurNode*2; iNextNode <= iDataNum; iNextNode = iCurNode*2)
- {
- if (iNextNode + 1 <= iDataNum
- && pDataArray[iNextNode] < pDataArray[iNextNode + 1]) //寻找iCurNode子节点中的大者
- iNextNode++;
- if (pDataArray[iNextNode] > temp) //大的值上移
- pDataArray[iCurNode] = pDataArray[iNextNode];
- else //结束调整
- break;
- iCurNode = iNextNode; //更新需要调整的节点
- }
- pDataArray[iCurNode] = temp;
- }
- /********************************************************
- *函数名称:HeapSort
- *参数说明:pDataArray 无序数组;
- * iDataNum为无序数据个数
- *说明: 堆排序
- *********************************************************/
- void HeapSort(int* pDataArray, int iDataNum)
- {
- pDataArray--; //让原先数组下标0对应1,便于堆中节点的访问
- for (int i = iDataNum/2; i > 0; i--) //调整为大顶堆
- SlipDown(pDataArray, i, iDataNum);
- for (int i = iDataNum; i > 1; i--) //根据大顶堆进行排序
- {
- DataSwap(&pDataArray[i], &pDataArray[1]);
- SlipDown(pDataArray, 1, i - 1);
- }
- }