1. 程式人生 > >C++ Heap 堆的實現(最小堆&最大堆)

C++ Heap 堆的實現(最小堆&最大堆)

堆 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