C++ Heap 堆的實現(最小堆&最大堆)
阿新 • • 發佈:2018-12-05
堆 heap
堆也叫優先佇列,堆是一種特殊的完全二叉樹資料結
堆分為兩種,最大堆,最小堆。
最大堆:根節點大於左右兩個子節點的完全二叉樹
最小堆:根節點小於左右兩個子節點的完全二叉樹
堆可以用陣列來儲存,
a[i]處存根節點,a[2 * i]存左子樹的根節點 ; a[2 * i + 1]存右子樹的根節點。i從1開始!!
實現
#pragma once
#include<vector>
//using namespace std;
enum heaptype
{
MAXHEAP, MINHEAP,
};
template<class T>
class Myheap
{
private:
std::vector<T>_vecdata;
int _size;//元素數量
int _capacity;//整個堆的大小
heaptype _type;
public:
Myheap(T data[],int len,heaptype);
Myheap(int capacity, heaptype);//一個空堆
virtual ~Myheap();
bool push(T data);
bool pop(int index);
void print();
bool full()
{
if (_size >= _capacity)
{
return true;
}
return false;
}
bool empty()
{
//檢查的是堆是否為空而不是_capacity的大小
return _size == 0;
}
private:
void _swap(int i, int j);
//元素下沉
void _sink(int index);
//元素上浮
void _floating(int index);
};
template <class T>
Myheap<T>::Myheap(T data[], int len, heaptype type):_size (0),_capacity(len),_type(type)
{
_vecdata.resize(_capacity);
//將data陣列中元素加入堆中
for (int i = 0; i < len; i++)
push(data[i]);
}
template <class T>
Myheap<T>::Myheap(int capacity, heaptype type):_size(0),_capacity(capacity), _type(type) //建立一個capacity空間大小的空堆
{
_vecdata.resize(_capacity);
}
template <class T>
Myheap<T>::~Myheap()
{
//vector自動析構
}
template<class T>
bool Myheap<T>::push(T data)
{
if (full()){
throw("The heap is full !!\n");
return false;
}
else
{
_vecdata[_size] = data;
++_size;
_floating(_size);
//將當期位置的資料進行判斷上浮(這裡的位置從1開始算,而非0)
//這是為了更方便計算左結點和右結點的位置
//當前節點: i 左結點: 2i 右結點: 2i+1
return true;
}
}
template<class T>
void Myheap<T>::_floating(int index)
{
//只有一個元素&空堆不需要進行操作
if (_size == 1)
return;
if (_type == MINHEAP)
{
for (int i = index; i > 0; i *= 0.5)
{
//小根堆的上浮
//大根堆判斷條件相反
if (_vecdata[i - 1] < _vecdata[i*0.5 - 1])
_swap(i - 1, i*0.5 - 1);
else
break;
}
}
else if(_type==MAXHEAP)
{
for (int i = index; i > 0; i *= 0.5)
{
//大根堆的上浮
if (_vecdata[i - 1] > _vecdata[i*0.5 - 1])
_swap(i - 1, i*0.5 - 1);
else
break;
}
}
return;
}
template<class T>
void Myheap<T>::_swap(int i, int j)
{
T temp = _vecdata[i];
_vecdata[i] = _vecdata[j];
_vecdata[j] = temp;
return ;
}
template<class T>
void Myheap<T>::_sink(int index)
{
int i = index;
if (_type == MINHEAP)
{
while (i * 2 <= _size)
{
//與左結點比
if (_vecdata[i - 1] > _vecdata[i * 2 - 1])
{
_swap(i - 1, i * 2 - 1);
//交換後,index位置的結點與其右結點比
if (i * 2 + 1 <= _size && _vecdata[i - 1] > _vecdata[i * 2])
_swap(i - 1, i * 2);
i = i * 2;
}
//與右結點比
else if (i * 2 + 1 <= _size && _vecdata[i - 1] > _vecdata[i * 2])
{
_swap(i - 1, i * 2);
i = i * 2 + 1;
}
else
break;
}
}
else if (_type == MAXHEAP)
{
while (i * 2 <= _size)
{
//與左結點比
if (_vecdata[i - 1] < _vecdata[i * 2 - 1])
{
_swap(i - 1, i * 2 - 1);
//交換後,index位置的結點與其右結點比
if (i * 2 + 1 <= _size && _vecdata[i - 1]< _vecdata[i * 2])
_swap(i - 1, i * 2);
i = i * 2;
}
//與右結點比
else if (i * 2 + 1 <= _size && _vecdata[i - 1] < _vecdata[i * 2])
{
_swap(i - 1, i * 2);
i = i * 2 + 1;
}
else
break;
}
}
}
template<class T>
void Myheap<T>::print() {
for (int i=0;i<_size;i++)
std::cout << _vecdata[i]<< " ";
std::cout << endl;
return;
}
template<class T>
bool Myheap<T>::pop(int index)
{
if (empty())
{
throw("This is an empty heap !!\n");
return false;
}
_vecdata[index] = _vecdata[_size - 1];
--_size ;
_sink(index+1);
return true;
}
測試
//堆也叫優先佇列,堆是一種特殊的完全二叉樹資料結
//堆分為兩種,最大堆,最小堆。
//最大堆:根節點大於左右兩個子節點的完全二叉樹
//最小堆:根節點小於左右兩個子節點的完全二叉樹
//堆可以用陣列來儲存,
//a[i]處存根節點,a[2 * i]存左子樹的根節點 ; a[2 * i + 1]存右子樹的根節點。i從1開始!!
#include<iostream>
#include"Myheap.h"
using namespace std;
int main()
{
int minheapbuffer[10] = { 9,8,7,6,5,4,3,2,1,0 };
int maxheapbuffer[10] = { 0,1,2,3,4,5,6,7,8,9 };
Myheap<int>minheap(minheapbuffer,10,MINHEAP);
Myheap<int>maxheap(maxheapbuffer, 10,MAXHEAP);
//小頂堆
minheap.print();
minheap.pop(1);
minheap.print();
minheap.push(1);
minheap.print();
cout << endl;
//大頂堆
maxheap.print();
maxheap.pop(0);
maxheap.print();
maxheap.push(10);
maxheap.print();
system("pause");
return 0;
}
程式碼:
https://github.com/ChristmasError/Data_Structure/tree/master/堆 Heap