堆排序

堆排序概述


堆排序定义

n个关键字序列k(1), k(2), ..., k(n)称为堆,当且仅当该序列满足如下性质(简称为堆性质)
  • k(i) <= k(2i) && k(i) <= k(2i+1)
  • k(i) >= k(2i) && k(i) >= k(2i+1)
若将此序列所存储的向量R[1..n]看做是一颗完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树:树中任一非叶结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字。



大根堆和小根堆

  • 根结点(亦称堆顶)的关键字是堆里所有结点关键字中最小者的堆称为小根堆
  • 根节点(亦称堆顶)的关键字是堆里所有结点关键字中最大者,称为大根堆

堆排序特点

  • 堆排序(heap sort)是一树形选择排序
  • 在排序过程中,将R[l..n]看成是一棵完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系,在当前无序区中选择关键字最大(或最小)的记录

堆排序

堆排序推荐阅读《算法导论》,这里把算法导论里的伪代码用c语言实现,并且优化算法结构

保持堆性质(非递归c语言)

/**
 * Description:从节点i开始,维护以i为根节点的子树,使以i为根的子树为最大堆(非递归)
 */
void MaxHeapIfy(int *A, int i, int n)
{
	int l, r, largest, temp, loc;

	for(largest = i; largest <= n;)
	{
		l = 2 * largest;
		r = 2 * largest + 1;
		loc = largest;

		if(l <= n && A[l] > A[largest])
		{
			largest = l;
		}
		if(r <= n && A[r] > A[largest])
		{
			largest = r;
		}

		//如果最大值不是根节点,那么交换A[loc], A[largest]
		if(largest != loc)
		{
			temp = A[largest];
			A[largest] = A[loc];
			A[loc] = temp;
		}else
		{
			break;
		}
	}
}

建堆

我们采用自底向上地用MaxHeapIfy来将一个数组A变成一个大根堆。子数组A([n/2]+1 .. n)均为叶子节点,所以我们只需要自底向上遍历非叶子节点即可
/**
 * Description:建立大根堆
 */
void BuildMaxHeap(int *A, int n)
{
	int i;
	for(i = n / 2; i >= 1; i --)
	{
		MaxHeapIfy(A, i, n);
	}
}

堆排序算法

/**
 * Description:堆排序
 */
void HeapSort(int *A, int n)
{
	int temp, i, j;
	BuildMaxHeap(A, n);

	for(i = n, j = 1; i >= 2; i --, j ++)
	{
		temp = A[i];
		A[i] = A[1];
		A[1] = temp;
		MaxHeapIfy(A, 1, n - j);
	}
}


排序练习


题目

题目描述:
    对输入的n个数进行排序并输出。
输入:
    输入的第一行包括一个整数n(1<=n<=100)。
    接下来的一行包括n个整数。
输出:
    可能有多组测试数据,对于每组数据,将排序后的n个整数输出,每个数后面都有一个空格。
    每组测试数据的结果占一行。
样例输入:
4
1 4 3 2
样例输出:
1 2 3 4 


ac代码(堆排序)

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

void max_heapify(int *A, int i, int n);
void build_heap(int *A, int n);
void heap_sort(int *A, int n);

int main()
{
	int i, n, A[102];

	while(scanf("%d", &n) != EOF)
	{
		for(i = 1; i <= n; i ++)
			scanf("%d", &A[i]);

		heap_sort(A, n);

		for(i = 1; i <= n; i ++)
		{
			printf("%d ", A[i]);
		}
		printf("\n");
	}

	return 0;
}

void heap_sort(int *A, int n)
{
	int i, j, exchange;
	build_heap(A, n);

	for(i = n, j = 1; i >= 2; i --, j ++)
	{
		exchange = A[1];
		A[1] = A[i];
		A[i] = exchange;
		max_heapify(A, 1, n - j);
	}
}

void max_heapify(int *A, int i, int n)
{
	int large, loc, left, right, temp;

	for(large = i; large <= n;)
	{
		left = large * 2;
		right = large * 2 + 1;
		loc = large;

		if(left <= n && A[left] > A[large])
			large = left;
		if(right <= n && A[right] > A[large])
			large = right;

		if(large != loc)
		{
			temp = A[large];
			A[large] = A[loc];
			A[loc] = temp;

		}else
		{
			break;
		}
	}
}

void build_heap(int *A, int n)
{
	int i;

	for(i = n / 2; i >= 1; i --)
	{
		max_heapify(A, i, n);
	}
}


posted @ 2013-02-25 23:28  java程序员填空  阅读(191)  评论(0编辑  收藏  举报