堆排序

来源:互联网 发布:gdi 高级编程 编辑:程序博客网 时间:2024/06/05 07:48

转自: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) (用于交换数据) 

稳定性:不稳定

三. 算法实现

[cpp] view plaincopy
  1. //交换data1和data2所指向的整形  
  2. void DataSwap(int* data1, int* data2)  
  3. {  
  4.     int temp = *data1;  
  5.     *data1 = *data2;  
  6.     *data2 = temp;  
  7. }  
  8.   
  9.   
  10. /******************************************************** 
  11. *函数名称:SlipDown 
  12. *参数说明:pDataArray 无序数组; 
  13. *          iCurNode为堆中需要调整的节点 
  14. *          iDataNum为数组长度 
  15. *函数返回:分割后的分割数位置 
  16. *函数说明:调整iCurNode处的节点,形成大顶堆     
  17. *********************************************************/  
  18. void SlipDown(int *pDataArray,int iCurNode,int iDataNum)  
  19. {  
  20.     int temp = pDataArray[iCurNode];    //记录需要调整的节点值  
  21.   
  22.     for (int iNextNode = iCurNode*2; iNextNode <= iDataNum; iNextNode = iCurNode*2)  
  23.     {  
  24.         if (iNextNode + 1 <= iDataNum   
  25.             && pDataArray[iNextNode] < pDataArray[iNextNode + 1])    //寻找iCurNode子节点中的大者  
  26.             iNextNode++;  
  27.         if (pDataArray[iNextNode] > temp)    //大的值上移  
  28.             pDataArray[iCurNode] = pDataArray[iNextNode];      
  29.         else    //结束调整  
  30.             break;  
  31.   
  32.         iCurNode = iNextNode;    //更新需要调整的节点  
  33.     }  
  34.   
  35.     pDataArray[iCurNode] = temp;  
  36. }  
  37.   
  38. /******************************************************** 
  39. *函数名称:HeapSort 
  40. *参数说明:pDataArray 无序数组; 
  41. *          iDataNum为无序数据个数 
  42. *说明:    堆排序 
  43. *********************************************************/  
  44. void HeapSort(int* pDataArray, int iDataNum)  
  45. {  
  46.     pDataArray--;    //让原先数组下标0对应1,便于堆中节点的访问  
  47.     for (int i = iDataNum/2; i > 0; i--)    //调整为大顶堆  
  48.         SlipDown(pDataArray, i, iDataNum);  
  49.   
  50.     for (int i = iDataNum; i > 1; i--)    //根据大顶堆进行排序  
  51.     {  
  52.         DataSwap(&pDataArray[i], &pDataArray[1]);  
  53.         SlipDown(pDataArray, 1, i - 1);  
  54.     }  
  55. }  
0 0