C++实现堆排序

堆排序是合并排序和插入排序排序方法共同的长处。它的时间复杂度O(nlgn),这也是一个地方排序算法:在任何时候,外阵中拥有唯一不变的输入数组存储的元素。引进第一家引进什么样的堆堆。

1.建堆:堆数据结构是一种数组对象,它能够被视为一颗全然二叉树。例如以下图。

右边数组表示的堆能够用左边的全然二叉树来表示。当中若父节点相应数组下标为i。则其左孩子相应数组下标为2*i。右孩子为2*i+1。

C++实现堆排序

C++实现堆排序

C++实现堆排序

详细代码例如以下:

void buildMaxHeap(int a[] , int heapSize){

for(int i = heapSize/2;i >= 1;--i)

max_heapify(a,i,heapSize); //本行代码调用max_heapify函数来保持最大堆性质,接下来会介绍到。heapSize为堆大小。

}

2.保持根堆性质:接下来介绍大根堆与小根堆的差别。

大根堆某个节点的值最多是和其父节点一样大。小根堆的组织刚好相反。在堆排序中我们使用的是大根堆。

为了保持大根堆的性质。我们如果从下标为i的数组元素開始。将其值与它的左孩子和右孩子相比較,找出最大值相应的下标largest,如果largest恰好与i相等。则说明节点i保持了最大堆性质。

否则交换下标为largest和i所相应的数组元素值,而且对下标为largest的元素继续进行“保持根堆性质”的操作。这么说可能有些太缺乏生动性,那么一起来看看这个过程吧:C++实现堆排序

C++实现堆排序

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveXVfc3VuOTA=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

能够看到图中节点值为4的节点的保持根堆性质过程。代码例如以下:

void max_heapify(int a[],int i,int heapSize){

int lindex = 2*i,rindex = 2*i + 1,largest = 0;

if(lindex <= heapSize && a[lindex-1] > a[i-1])//推断左孩子和节点i的值谁大。将大值得下标保存为largest

largest = lindex;

else

largest = i;



if(rindex <= heapSize && a[rindex-1] > a[largest-1])//推断右孩子和节点largest的值谁大

largest = rindex;



if(largest != i){//假设largest不等于i

swap(a[i-1] , a[largest-1]);//交换

max_heapify(a,largest,heapSize);//继续对下标为largest、大小为heapSize的节点进行“保持根堆性质”

}

}

下面是swap函数:

void swap(int& first , int& second){

int tem = 0;

tem = first;

first = second;

second = tem;

}

3.堆排序算法:我用一个图来直观表示吧!

C++实现堆排序

过程大致是将大根堆的根节点与最后一个叶子节点交换,然后缩小数组范围(即将heapSize减小),将最大值排除掉,最后对新的根节点进行“保持堆性质方法”。依次类推,代码例如以下:

C++实现堆排序

void heapSort(int a[] , int heapSize){

buildMaxHeap(a , heapSize);//建堆

for(int i = heapSize;i >= 2;--i){

swap(a[0] , a[i-1]);//将根节点与最后的叶子节点交换

--heapSize;//缩小堆范围

max_heapify(a,1,heapSize);//保持堆性质



}

}

版权声明:本文博客原创文章。博客,未经同意,不得转载。

上一篇:PHP打印测试,PHP调试技巧


下一篇:Java探秘之基本数据类型和包装类(int,Integer)(一)