堆排序 c 实现 及 c++模板实现

(英语:heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质:

  •   1.堆中某个节点的值总是不大于或不小于其父节点的值;

  •   2.堆总是一棵完全树。

将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。

堆的定义如下:n个元素的序列{k1,k2,ki,…,kn}当且仅当满足下关系时,称之为堆。

" ki<=k2i,ki<=k2i+1;或ki>=k2i,ki>=k2i+1.(i=1,2,…,[n/2])"

若将和此次序列对应的一维数组(即以一维数组作此序列的存储结构)看成是一个完全二叉树,则堆的含义表明,完全二叉树中所有非终端结点的值均不大于(或不小于)其左、右孩子结点的值。由此,若序列{k1,k2,…,kn}是堆,则堆顶元素(或完全二叉树的根)必为序列中n个元素的最小值(或最大值)。

 

堆的基本思想其实也很简单,就是三个元素(父节点和俩个子节点)之间比较大小,若是最大堆,就是最大的那个数移到父节点;若是最小堆,就把最小的那个数移到父节点那个位置。

最小堆QQ截图20130819183206最大堆QQ截图20130819183400

对一个序列都经过这样的处理,序列的第一个就是最小(最小堆)的元素,然后把第一个元素移除,把最后一个元素复制过来,或者把第一个元素和最后一个元素交换,然后再对剩下的元素就行处理,直到整个序列处理完,序列就是一个有序的了。

对a[10] = {4, 1, 3, 5, 2, 6, 7, 0, 9, 8}进行一次处理:

1.                                                                                                         2.

QQ截图20130819185001 QQ截图20130819185235

3.                                                                                                           4.

image image

5.

image

堆排序的大致过程就这样,然后就是0和8交换位置,再把总数减1,在进行上述过程。

c实现:

#include<stdio.h>
#include<stdlib.h>

void fixDown(int *a, int numTotal, int pos)
{
	int compareIndex = pos * 2 + 1;//左字节点的下标

	while (2 * pos + 1 < numTotal) {
		compareIndex = 2 * pos + 1;

		if ((compareIndex + 1 < numTotal) && (a[compareIndex] > a[compareIndex + 1])) //左右子节点的最小的那个数的下标
			compareIndex += 1;
		/*
		 *父节点大于子节点的话,就交换,不然就break
		 */
		if (a[pos] > a[compareIndex]) {
			int temp = a[pos];
			a[pos] = a[compareIndex];
			a[compareIndex] = temp;
		}
		else 
			break;
		pos = compareIndex;//向下继续比较
	}
}

int main(void)
{
	int a[10] = {4, 1, 3, 5, 2, 6, 7, 0, 9, 8};
	int numTotal = sizeof(a) / sizeof(int);
	int i;

	/*
	 *建一个堆
	 */
	for (i = (numTotal - 1) / 2; i >= 0; i--) {
		fixDown(a, numTotal, i);
	}

	while (numTotal > 0) {
		/*
		 *交换第一个和最后一个元素
		 */
		int temp = a[0];
		a[0] = a[numTotal - 1];
		a[numTotal - 1] = temp;

		fixDown(a, --numTotal, 0);
	}

	for (i = 0; i < 10; i++) {
		printf("%d ", a[i]);
	}
	
	printf("\n");

	return 0;
}


c++模板实现:

#include<iostream>
#include<functional>
#include<algorithm>
#include<iterator>

using namespace std;

template <typename Randomiterator, typename Comparator>
void adjust_heap(Randomiterator begin, Randomiterator end, Randomiterator pos, Comparator comp) 
{
	typedef typename std::iterator_traits<Randomiterator>::difference_type diff_t;
	const diff_t numTotal = distance(begin, end);
	diff_t position = distance(begin, pos);

	while ((2 * position + 1 < numTotal)) {
		diff_t compIndex = 2 * position + 1;
		
		if ((compIndex + 1 < numTotal) && (comp(begin[compIndex], begin[compIndex + 1])))
			compIndex += 1;
		if (comp(begin[compIndex], begin[position]))
			break;
		std::swap(begin[compIndex], begin[position]);
		position = compIndex;
	}
}

template <typename Randomiterator, typename Comparator>
void Heapsort(Randomiterator begin, Randomiterator end, Comparator comp)
{
	typedef typename std::iterator_traits<Randomiterator>::difference_type diff_t;
	diff_t numTotal = distance(begin, end);
	if (begin == end || begin + 1 == end)
		return;

	Randomiterator itr;
	for (itr = begin + (numTotal - 1)/2; itr >= begin; itr--)
		adjust_heap(begin, end, itr, comp);
	while (end - begin > 0) {
		std::swap(begin[0], begin[distance(begin, end - 1)]);
		adjust_heap(begin, --end, begin, comp);
	}
}

template <typename Randomiterator>
void heapsort(Randomiterator begin, Randomiterator end) {
	Heapsort(begin, end, std::less<typename std::iterator_traits<Randomiterator>::value_type>());
}

int main(void)
{
	int a[10] = {4, 1, 3, 5, 2, 6, 7, 0, 9, 8};
	heapsort(&a[0], &a[10]);
	int i;

	for (i = 0; i < 10; i++) 
		cout << a[i] << ' ';
	cout << endl;
}
posted @ 2013-08-19 19:21  露天坝  阅读(591)  评论(0编辑  收藏  举报