优先级队列

前言

  • 用最大堆实现的最大优先级队列一般用来进行作业调度的问题
  • 用最小堆实现的最小优先级队列一般用于贪心等

概念

优先级队列是一种用来维护一组元素构成的集合S的数据结构,这一组元素中的每一个都有一个关键字key。
这里以最大堆实现的最大优先级队列为例,支持如下操作:
  • extract_max(A, n) : 去掉并返回A中的具有最大关键字的元素
  • increase_key(A, i, key) : 将元素A[i]关键字变为key并且保持最大优先级队列的性质

实现


extract_max

/**
 * 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;
		}
	}
}

/**
 * Description:去掉并返回A中具有最大关键字的元素
 */
int heapExtractMax(int *A, int n)
{
	int max = A[1];

	A[1] = A[n];
	MaxHeapIfy(A, 1, n - 1);

	return max;
}

heap_increase_key

/**
 * Description:将元素x的关键字的值增加到k
 * heapIncreaseKey && maxHeapIfy 区别:
 * heapIncreaseKey : 是当前结点的值增大了,因此要向上将父结点与该结点交换
 * maxHeapIfy : 是保持当前结点为根的树是对,因此将当前结点与两个子结点比较,向下逐层恢复堆的性质。
 */
void heapIncreaseKey(int *A, int i, int key)
{
	int parent, exchange;

	for(A[i] = key, parent = i / 2; i >= 1 && A[parent] < A[i] && parent >= 1)
	{
		exchange = A[parent];
		A[i] = A[parent];
		A[i] = exchange;
		i = parent;
		parent = i / 2;
	}
}


练习(哈夫曼树)

用最小堆实现求哈夫曼树的wpl

题目

题目描述:
哈夫曼树,第一行输入一个数n,表示叶结点的个数。需要用这些叶结点生成哈夫曼树,根据哈夫曼树的概念,这些结点有权值,即weight,题目需要输出所有结点的值与权值的乘积之和。
输入:
输入有多组数据。
每组第一行输入一个数n,接着输入n个叶节点(叶节点权值不超过100,2<=n<=1000)。
输出:
输出权值。
样例输入:
5  
1 2 2 5 9
样例输出:
37

ac代码

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

#define MAX 1001

void minHeapIfy(int *A, int i, int n);
void buildMinHeap(int *A, int n);
int heapExtractMin(int *A, int n);
void minHeapInsert(int *A, int i, int key);

int main()
{
	int i, j, n, huff[MAX], power, lchild, rchild, parent;

	while(scanf("%d", &n) != EOF)
	{
		//接收参数输入
		for(i = 1; i <= n; i ++)
			scanf("%d", &huff[i]);

		//构建一个最小堆
		buildMinHeap(huff, n);

		//获取wpl
		for(i = 1, j = n, power = 0; i < n; i ++)
		{
			lchild = heapExtractMin(huff, j);
			j -= 1;
			rchild = heapExtractMin(huff, j);
			
			parent = lchild + rchild;
			power += parent;
		
			minHeapInsert(huff, j, parent);
		}

		printf("%d\n", power);
	}

	return 0;
}

/**
 * Description:构建最小堆
 */
void buildMinHeap(int *A, int n)
{
	int i;

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

/**
 * Description:调整以i为根的最小堆
 */
void minHeapIfy(int *A, int i, int n)
{
	int l, r, min, loc, temp;

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

		if(l <= n && A[l] < A[min])
			min = l;
		if(r <= n && A[r] < A[min])
			min = r;

		if(min != loc)
		{
			temp = A[min];
			A[min] = A[loc];
			A[loc] = temp;
		}else
		{
			break;
		}
	}
}



int heapExtractMin(int *A, int n)
{
	int min = A[1];
	A[1] = A[n];
	minHeapIfy(A, 1, n);

	return min;
}


/**
 * Description:
 * (1)将元素插入到最小优先队列
 * (2)因为每次i == length(A),都是在对尾插入,因此只考虑i的parent,不考虑i的children
 */
void minHeapInsert(int *A, int i, int key)
{
	int parent, change;

	for(A[i] = key, parent = i / 2; parent >= 1 && A[parent] > A[i];)
	{
		change = A[parent];
		A[parent] = A[i];
		A[i] = change;
		i = parent;
		parent = i / 2;
	}
}


posted @ 2013-02-26 16:13  java程序员填空  阅读(126)  评论(0编辑  收藏  举报