试写二叉最小堆和最大堆

简述:

用一维数组实现二叉最小堆,确保每次根节点的值都是最小的,就是elements[1]的值是最小的。

实现了最小堆 , 如下

BinaryHeap类简述:

BinaryHeap类考虑到泛型,所以用模板实现里面的主要函数包括

AddAfter(Type newElement)    //在数组末尾添加新的元素

Change(Type element, int position)  //修改某个位置的数值,并且从新向上、向下排序

UpMin(int startPos) 从startPos向父节点排序互换,使得父节点都小于其子节点

DownMin(int startPos)  从startPos向父节点排序互换,使得父节点都小于其子节点


下面是最大堆:

相比于最小堆最大堆新增了两个函数

UpMax(int startPos) 从startPos向父节点排序互换,使得父节点都大于其子节点

DownMax(int startPos)  从startPos向父节点排序互换,使得父节点都大于其子节点


下面是代码

BinaryHeap类定义及其实现

BinaryHeap.hpp

#include <iostream>
using namespace std;

#define INITSIZE 10  //初始大小

enum BinaryHeapType{
	// A minimum heap. 最小堆 堆顶值最小

	BINARY_HEAP_TYPE_MIN,

	// A maximum heap. 最大堆 堆顶值最大

	BINARY_HEAP_TYPE_MAX
};


template <class Type>
class BinaryHeap{

private:
	BinaryHeapType heapType;

	Type *elements;

	int currentSize;


	int capacity;
public:

	BinaryHeap(): heapType(BINARY_HEAP_TYPE_MIN){} //默认空构造函数是最小堆,即顶点最小

	BinaryHeap(BinaryHeapType );

	BinaryHeap(Type *, int, BinaryHeapType);

	~BinaryHeap(){
		delete []elements;
	}

	void Swap(Type &a,Type &b){
		Type temp = a;
		a = b;
		b = temp;
	}

	bool IsEmpty() const;  //不改变数据成员的值的函数用const表示

	Type AddAfter(Type ); //增加一个新的元素在末尾

	Type Change(Type , int); //在某个位置增加一个值

	void UpMin(int); //最小堆某个位置的元素上浮

	void DownMin(int); //最小堆某个位置的元素下沉

	void UpMax(int); //最大堆某个位置的元素上浮

	void DownMax(int); //最大堆某个位置的元素上浮

	void Cout(){
		cout << "当前容量(capacity) : " << capacity << endl;
		cout << "当前节点数(currentSize) : " << currentSize << endl;
		cout << "各节点的值为:" << endl;
		for(int i = 1;i <= currentSize; i++)
			cout << elements[i] << " ";
		cout << "\n\n";
	}
};

template <class Type>
BinaryHeap<Type>::BinaryHeap(BinaryHeapType heapType){
	BinaryHeap::heapType = heapType;
	capacity = INITSIZE;
	currentSize = 0;
	elements = new Type[capacity];
}


template <class Type>
BinaryHeap<Type>::BinaryHeap(Type *array , int arraySize , BinaryHeapType heapType){
	BinaryHeap::heapType = heapType;
	capacity = arraySize > INITSIZE ? arraySize * 2 : INITSIZE;
	currentSize = arraySize;
	elements = new Type[capacity];
	//第0位空出
	for(int i = 0;i < arraySize;i++)
		elements[i + 1] = array[i];
}


template <class Type>
bool BinaryHeap<Type>::IsEmpty() const{
	return currentSize == 0 ? true : false;
}


//在BinaryHeap中添加一个值
template <class Type>
Type BinaryHeap<Type>::AddAfter(Type newElement){
	//动态自增长
	if(currentSize + 1 == capacity){
		Type *tempElements = elements;
		capacity <<= 1;  //左移一位
		elements = new Type[capacity];
		for(int i = 0;i <= currentSize;i++ ){
			elements[i] = tempElements[i];
		}
		delete []tempElements;
	}
	elements[++currentSize] = newElement;
	if(heapType == BINARY_HEAP_TYPE_MIN){
		UpMin(currentSize);
	}else{
		UpMax(currentSize);
	}
	return newElement;
}


/**********************************Min最小堆****************************************/
template <class Type>
void BinaryHeap<Type>::UpMin(int startPos){
	//currentPos : 新插入节点的在数组中位置
	int currentPos = startPos;  //初始为最后一个节点
	//comparePos : 需要比较的父节点
	int comparePos = currentPos / 2;
	//向父节点上比较
	while(true){
		if(elements[currentPos] < elements[comparePos]){
			Swap(elements[currentPos], elements[comparePos]);
			currentPos = comparePos;
		}else
			break;
		if(comparePos == 1){
			break;
		}
		comparePos = comparePos / 2;
	}
}


template <class Type>
void BinaryHeap<Type>::DownMin(int startPos){
	int currentPos = startPos; //初始的当前
	int comparePos = 2 * currentPos; //在头部插入的话开始时和elements[1]中值进行比较;
	bool isFinished = false;  //向下调整是否完成 初始为未完成false
	while(!isFinished){
		if((comparePos <= currentSize) && (currentSize % 2 == 1)){ // 所有非叶子节点都有两个儿子
			if(elements[comparePos] > elements[comparePos + 1]){ //找寻左右儿子中最小的
				comparePos++;
			}
			if(elements[currentPos] > elements[comparePos]){
				Swap(elements[currentPos] , elements[comparePos]);
				currentPos = comparePos;
			}else
				isFinished = true;
		}else if((comparePos <= currentSize) && (currentSize % 2 == 0)){ //有一个非叶子节点只有一个儿子
			if((elements[comparePos] > elements[comparePos + 1]) && (comparePos != currentSize)){ //找寻左右儿子中最小的
				comparePos++;
			}else if(comparePos == currentSize){  //最后的一个父节点只有一个左儿子节点,比较完后退出
				if(elements[currentPos] > elements[comparePos]){
					Swap(elements[currentPos] , elements[comparePos]);
					currentPos = comparePos;
				}else
					isFinished = true;
			}
			if(elements[currentPos] > elements[comparePos]){
				Swap(elements[currentPos] , elements[comparePos]);
				currentPos = comparePos;
			}else
				isFinished = true;
		}
	}
}


/**********************************Max最大堆****************************************/
template <class Type>
void BinaryHeap<Type>::UpMax(int startPos){
	//currentPos : 新插入节点的在数组中位置
	int currentPos = startPos;  //初始为最后一个节点
	//comparePos : 需要比较的父节点
	int comparePos = currentPos / 2;
	//向父节点上比较
	while(true){
		if(elements[currentPos] > elements[comparePos]){
			Swap(elements[currentPos], elements[comparePos]);
			currentPos = comparePos;
		}else
			break;
		if(comparePos == 1){
			break;
		}
		comparePos = comparePos / 2;
	}
}


template <class Type>
void BinaryHeap<Type>::DownMax(int startPos){
	int currentPos = startPos; //初始的当前
	int comparePos = 2 * currentPos; //在头部插入的话开始时和elements[1]中值进行比较;
	bool isFinished = false;  //向下调整是否完成 初始为未完成false
	while(!isFinished){
		if((comparePos <= currentSize) && (currentSize % 2 == 1)){ // 所有非叶子节点都有两个儿子
			if(elements[comparePos] < elements[comparePos + 1]){ //找寻左右儿子中最小的
				comparePos++;
			}
			if(elements[currentPos] < elements[comparePos]){
				Swap(elements[currentPos] , elements[comparePos]);
				currentPos = comparePos;
			}else
				isFinished = true;
		}else if((comparePos <= currentSize) && (currentSize % 2 == 0)){ //有一个非叶子节点只有一个儿子
			if((elements[comparePos] < elements[comparePos + 1]) && (comparePos != currentSize)){ //找寻左右儿子中最小的
				comparePos++;
			}else if(comparePos == currentSize){  //最后的一个父节点只有一个左儿子节点,比较完后退出
				if(elements[currentPos] < elements[comparePos]){
					Swap(elements[currentPos] , elements[comparePos]);
					currentPos = comparePos;
				}else
					isFinished = true;
			}
			if(elements[currentPos] < elements[comparePos]){
				Swap(elements[currentPos] , elements[comparePos]);
				currentPos = comparePos;
			}else
				isFinished = true;
		}
	}
}


//改变某个位置的元素将其上移或下移到合适位置
template <class Type>
Type BinaryHeap<Type>::Change(Type element, int position){
	if(position <= currentSize){
		elements[position] = element;
	}
	if(heapType == BINARY_HEAP_TYPE_MIN){
		UpMin(position);
		DownMin(position);
	}else{
		UpMax(position);
		DownMax(position);
	}

	return element;
}


测试代码:

测试最小堆

main.cpp

/*********************最小堆测试代码*************************/
int main() {
	cout << "/*********************最小堆测试代码*************************/" << endl;
	/****************************初始化**********************/
	int a[5];
	for(int i = 0;i < 5;i++){
		a[i] = i;
	}
	BinaryHeap<int> bHeap(a,5,BINARY_HEAP_TYPE_MIN);
	cout << "初始状态:\n";
	bHeap.Cout();
	/****************************在末尾插入新值***************/
	cout << endl;
	for(int i = 0;i < 10;i++){
	    if(i == 5)
			bHeap.AddAfter(-3);
	    else if(i == 6)
			bHeap.AddAfter(-1);
	    else
	    	bHeap.AddAfter(i);
	}
	cout << "在末尾插入几个值后,状态:\n";
	bHeap.Cout();
	/*****************************修改某个位置的值************/
	cout << endl << "修改第4位置的值,改为-3\n堆重新排列后得到  : \n";
	bHeap.Change(-3,4);
	bHeap.Cout();
	return 0;
}

测试输出:



最大堆测试代码:

main.cpp

/*********************最大堆测试代码*************************/
int main() {
	cout << "/*********************最大堆测试代码*************************/" << endl;
	/****************************初始化**********************/
	BinaryHeap<int> bHeap(BINARY_HEAP_TYPE_MAX);
	for(int i = 0;i < 5;i++){
		bHeap.AddAfter(i);
	}
	cout << "初始状态:\n";
	bHeap.Cout();
	/****************************在末尾插入新值***************/
	cout << endl;
	for(int i = 0;i < 10;i++){
	    if(i == 5)
			bHeap.AddAfter(13);
	    else if(i == 6)
			bHeap.AddAfter(12);
	    else
	    	bHeap.AddAfter(i);
	}
	cout << "在末尾插入几个值后,状态:\n";
	bHeap.Cout();
	/*****************************修改某个位置的值************/
	cout << endl << "修改第4位置的值,改为7\n堆重新排列后得到  : \n";
	bHeap.Change(7,4);
	bHeap.Cout();
	return 0;
}

测试输出:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值