BinaryHeap 的C++实现

本文介绍了堆的概念,特别是完全二叉树的特性,并详细阐述了如何在C++中实现一个二叉堆数据结构。内容包括堆的节点关系、数组表示及基本操作。提供了BinaryHeap.h的头文件代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       堆是一棵被完全填满的二叉树,底层上的元素从左到右填入,这样的树称为完全二叉树。

一棵高为h的完全二叉树右2^h到2^(h+1) - 1 个结点。完全二叉树的树高为logN。


                    A

               /         \

           B            C

       /       \        /      \

     D        E      F      G

  /      \       /

H        I    J

_________________________________________________

|_ _| _A_ |_B_|_C_|_D_|_E_|_F_|_G_|_H_|_I_|_J_|_ _|_ _|_ _|

   0      1      2      3     4      5     6     7      8     9    10   11   12   13

      对于数组中任意位置 i 上的元素,其左儿子在位置2i上,右儿子在(2i + 1)上。它的父亲则在[i / 2] 上。

一个堆数据结构由一个数组和一个表示当前大小的证书组成。

下面的实现代码分为 BinaryHeap.h 和 main.cpp.

模板编程分文件写编译器支持不一,所以一般在一个文件内实现。

BinaryHeap.h

#ifndef __BINARY_HEAP_H
#define __BINARY_HEAP_H

#include <iostream>
#include <vector>
#include <exception>
#include <cstdlib>
using std::vector;
using std::cout;
using std::endl;
using namespace std;

class UnderflowException : public exception
{
public :
	UnderflowException() : exception()
	{
		cout << "underflow\n";
		exit(0);
	}
};

template <typename T>
class BinaryHeap
{
public:
	explicit BinaryHeap(int capacity = 100);
	explicit BinaryHeap(const vector<T> & items);
	~BinaryHeap();

	bool isEmpty() const;
	const T & findMin() const;

	void insert(const T &x);
	void deleteMin();
	void deleteMin(T & minItem);
	void makeEmpty();
	T  minimum() const;
	void print() const;
private:
	int       currentSize;    // number of elements in heap
	vector<T> array;          // the heap array

	void buildHeap();
	void percolateDown(int hole);
};

template <typename T>
BinaryHeap<T>::BinaryHeap(int capacity)
	: array(capacity + 10)
{
	currentSize = 0;
}

template <typename T>
BinaryHeap<T>::BinaryHeap(const vector<T> & item)
	: array(item.size() + 10), currentSize(item.size())
{
	for(int i = 0; i < item.size(); ++i)
	{
		array[i+1] = item[i];
	}
	buildHeap();
}

template <typename T>
BinaryHeap<T>::~BinaryHeap()
{
	makeEmpty();
	//	(array).swap(array);  // 匿名对象,来释放空间
	array.shrink_to_fit(); // -std=c++11
	cout << "array.capacity() " << array.capacity() <<endl;
	cout << "~BinaryHeap()" << endl;
}

/**
 *  Establish heap order property from an arbitrary arrangement of items. 
 *  Runs in linear time. O(n)
 */
template <typename T>
void BinaryHeap<T>::buildHeap()
{
	for(int i = currentSize / 2; i > 0; --i)
		percolateDown(i);
}

template <typename T>
void BinaryHeap<T>::makeEmpty()
{
	currentSize = 0;
	array.clear();
}

template <typename T>
T BinaryHeap<T>::minimum() const
{ 
	if(isEmpty())
		throw UnderflowException();

	return array[1];
}

template <typename T>
void BinaryHeap<T>::print() const
{
	for(int i = 1 ; i <= currentSize; ++i)
		cout << array[i] << " ";
	cout << endl;
}

template <typename T>
inline bool BinaryHeap<T>::isEmpty() const
{
	return currentSize == 0;
}

/*
 * Insert item x, allowing duplicates
 */
template <typename T>
void BinaryHeap<T>::insert(const T &x)
{
	if(currentSize == array.size() - 1)
	{
		array.resize(array.size() * 2);
	}
	int hole = ++currentSize;
	for( ; hole > 1 && x < array[hole / 2]; hole /= 2)
	{
		array[hole] = array[hole / 2];
	}
	array[hole] = x;
}

/*
 * Remove the minimum item.
 * Throws UnderflowException if empty.
 */
template <typename T>
void BinaryHeap<T>::deleteMin()
{
	if(isEmpty())
		throw UnderflowException();

	array[1] = array[currentSize--];
	percolateDown(1);
}

/*
 * Remove the minimum item and place it in minItem.
 * Throws UnderflowException if empty.
 */
template <typename T>
void BinaryHeap<T>::deleteMin(T & minItem)
{
	if(isEmpty)
		throw UnderflowException();

	minItem = array[1];
	array[1] = array[currentSize--];
	percolateDown(1);
}

template <typename T>
void BinaryHeap<T>::percolateDown(int hole)
{
	int child;
	T tmp = array[hole];

	for( ; (hole << 2) <= currentSize; hole = child)
	{
		child = hole << 2; // hole * 2
		if(child != currentSize && array[child + 1] < array[child])
			child++;
		if(array[child] < tmp)
			array[hole] = array[child];
		else
			break;
	}
	array[hole] = tmp;
}

#endif // #ifndef __BINARY_HEAP_H

main.cpp

#include <iostream>

#include "BinaryHeap.h"

using namespace std;

int main(int argc, char **argv)
{
	BinaryHeap<int> bHeap;
	cout << (bHeap.isEmpty() ? "empty" : "not empty") << endl;
	//bHeap.deleteMin(); // exception: the Heap is empty 
	bHeap.insert(10);
	bHeap.insert(2);
	bHeap.insert(5);
	bHeap.insert(13);
	bHeap.insert(1);
	bHeap.insert(8);
    
	cout << "minimum  " << bHeap.minimum() << endl;
	bHeap.print();
	
	bHeap.deleteMin();
	bHeap.print();
	
	BinaryHeap<int> bHeap2(bHeap);
	cout << "bHeap2" << endl << "	";
	bHeap2.print();

	return 0;
}


makefile非常非常简单,

# 2015-11-15
# Summer

#object = main.o 

main :
	g++ -std=c++11 main.cpp -o main

#main.o: BinaryHeap.h
#g++ -std=c++11 -c main.o main.cpp BinaryHeap.h

.PHONY: clean
clean:
	rm -rf $(object)
cleanAll:
	rm -r main $(object)

不想写mekefile也可以的,编译时输入

g++ -std=c++11 main.cpp -o main
即可

输出内容:

empty
minimum  1
1 2 5 13 10 8 
8 2 5 13 10 
bHeap2
	8 2 5 13 10 
array.capacity() 0
~BinaryHeap()
array.capacity() 0
~BinaryHeap()




以上内容参考《数据结构与算法分析C++描述》。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值