堆排序

什么是堆

image 

image

 

如何构造堆

功能:将一段数据转换为max-heap.(父节点不小于子节点的完全二叉树。)

 

基本步骤:

从某一子树开始进行下溯操作。

开始的子树:Distance parent = (len - 2)/2;   最后的叶节点不必执行下溯。

该子树执行完下溯后parent—;

 

下溯:将空洞节点(这里是parent,即开始执行下溯的节点)与较大子节点对调,并持续下放,

直到叶节点为止。

 

image


 

如何进行堆排序

image

 

关键是取走根节点后的重新构造!

方法:

image 

 

 

堆排序算法实现

/*堆排序*/
#include <iostream>
#include <vector>
using namespace std;

template<typename Comparable>
void heapSort(vector<Comparable> &a)
{
	/*构造堆,因为叶节点无需下溯,所以从a.size()/2开始下溯*/
	for (int i = a.size()/2; i >= 0; i--) {
		percDown(a, i, a.size());
	}

	/*堆排序:删除根节点形成空洞,最后编号叶节点与空洞节点对调,然后从根节点处下溯*/
	for (int j = a.size() - 1; j > 0; j--) {
		swap(a[0], a[j]);
		percDown(a, 0, j);
	}

}

/*返回节点i的左孩子编号2i*/
inline int leftChild(int i)
{
	return (2 * i);
}

/**
 * i是开始下溯的编号;
 * n是堆的最大长度。
 */
template<typename Comparable>
void percDown(vector<Comparable> &a, int i, int n)
{
	int child;		//当前与节点i比较的孩子编号。
	Comparable tmp;

	for (tmp = a[i]; leftChild(i) < n; i = child) {
		child = leftChild(i);

		/*比较左右孩子,找出孩子值最大的孩子编号*/
		if (child != n-1 && a[child] < a[child + 1]) {
			child++;
		}

		/*节点与最大孩子比较*/
		if (tmp < a[child]) {
			a[i] = a[child];
		} else {
			break;
		}
	}

	a[i] = tmp;
}
int main()
{
	int array[9] = {50, 10, 90, 30, 70, 40, 80, 60, 20};
	vector<int> intVec(array, array + 9);
	heapSort(intVec);

	for (vector<int>::iterator iter = intVec.begin(); iter != intVec.end(); iter++) {
		cout << *iter << endl;
	}

}
posted @ 2013-03-02 11:49  helloweworld  阅读(268)  评论(0编辑  收藏  举报