简述:
用一维数组实现二叉最小堆,确保每次根节点的值都是最小的,就是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;
}
测试输出: