优先队列(堆)C++实现源码

堆是一棵完全二叉树,最小元素在根结点上,任意子树也是一个堆。对于堆中的任意一个位置i上的元素,其左儿子在2i位置上,右儿子在2i+1位置上,它的父节点在 2/i 位置上。

堆的插入:

为了保持堆为完全二叉树,在堆的最后一个位置创建空结点,如果空结点的父节点大于要插入的结点,就将父节点移入空结点中,依此类推,直到要插入的结点能放入移空的位置中。

堆的删除(删除根结点,也就是最小的元素):

将根结点两个子结点中较小者提至根结点,再将那个较小的子节点的两个子节点的较小者提升,依此类推,直到将最后一个结点移入最近移空的结点中。

注:为了方便实现,堆的第一个元素是从1开始的,而非从0开始。

Heap.h

#include "Utility.h"

#define MinData (-32767)

struct HeapStruct
{
	int Capacity;
	int Size;
	int *Elements;
};

typedef struct HeapStruct *PriorityQueue;

PriorityQueue Initialize( int MaxElements)
{
	PriorityQueue H;

	H = (HeapStruct *)malloc(sizeof(HeapStruct));
	if( H == NULL )
		cout << "空间不足!" << endl;

	H->Elements = (int *)malloc( (MaxElements + 1) * sizeof(int) );
	if( H->Elements == NULL )
		cout << "空间不足!" << endl;

	H->Capacity = MaxElements;
	H->Size = 0;
	H->Elements[ 0 ] = MinData;

	return H;
}

void MakeEmpty( PriorityQueue H )
{
	H->Size = 0;
}

int IsFull( PriorityQueue H)
{
	return H->Size == H->Capacity; // 注意: “==” 不是 “=” !
}

int IsEmpty( PriorityQueue H )
{
	return H->Size == 0;
}

void Insert( int x, PriorityQueue H )
{
	int i;
	if( IsFull( H ) )
	{
		cout << "队列已满!" << endl;
		return;
	}

	// i/2 为 i结点的父节点
	//H->Size = H->Size + 1;
	for( i = ++H->Size; H->Elements[ i/2 ] > x; i /= 2 ) //运算符优先级会不会有问题 ++i > ->
	{
		//
		H->Elements[ i ] = H->Elements[ i/2 ];
	}
	
	H->Elements[ i ] = x;
	//test
	cout << i << ": " << H->Elements[ i ] << endl;
}

int DeleteMin( PriorityQueue H )
{
	int i, Child;
	int MinElement, LastElement;

	if( IsEmpty( H ) )
	{
		cout << "队列为空!" << endl;
		return H->Elements[ 0 ];
	}

	MinElement = H->Elements[ 1 ];
	LastElement = H->Elements[ H->Size-- ];

	for( i = 1; i * 2 <= H->Size; i = Child )
	{
		Child = i * 2;

		//找较小的那个儿子
		if( Child != H->Size && H->Elements[ Child + 1 ] < H->Elements[ Child ] )
			Child++;  //Child++较小的

		if( LastElement > H->Elements[ Child ] )
			H->Elements[ i ] = H->Elements[ Child ];  //较小元素上升至父节点
		else
			break;
	}
	H->Elements[ i ] = LastElement;
	return MinElement;
}

int FindMin( PriorityQueue H )
{
	if( !IsEmpty( H ) )
		return H->Elements[ 1 ];
	cout << "队列为空!" << endl;
	return H->Elements[ 0 ];
}

void PrintHeap( PriorityQueue H )
{
	if( IsEmpty( H ) )
		cout << "队列为空!" << endl;
	else{
		for( int i = 1; i <= H->Size; i++ )
			cout << i << ": " << H->Elements[ i ] << endl;
	}
}

Heap.cpp

#include "Heap.h"

#define MaxSize (1000)

void main()
{
	char cmd;
	PriorityQueue H;
	int i,j;

	int n;

	do{
		cout << "-----------------------------------------------" << endl;
		cout << "0: 创建堆;" << endl;
		cout << "1: 插入数据;" << endl;
		cout << "2: 打印最小元素;" << endl;
		cout << "3: 删除最小元素;" << endl;
		cout << "4: 打印堆中所有元素;" << endl;
		cout << "q: 退出。" << endl;
		cout << "-----------------------------------------------" << endl;
		cout << endl;
		cout << "选择操作:" ;
		cin >> cmd; 

		switch( cmd )
		{
			case '0':
				H = Initialize( MaxSize );
				if( H != NULL ){
					cout << "初始化成功!" << endl;
				}else{
					cout << "初始化失败!" << endl;
				}
				break;

			case '1':
				cout << "输入要插入元素的个数:";
				cin >> n;
				while( n-- )
				{
					cout << "输入要插入元素:";
					cin >> j;
					Insert( j, H );
				}
				break;

			case '2':
				cout << "最小元素:" << FindMin( H ) << endl;
				break;

			case '3':
				cout << "最小元素:" << DeleteMin( H ) << "被删除!" << endl;
				break;
				
			case '4':
				PrintHeap( H );
				break;

			default:
				break;
		}

	}while( cmd != 'q');

	system("PAUSE");
}



你可能感兴趣的:(算法)