C++实现堆、最大堆、最小堆 -- 堆排序插入删除操作

堆是一种经过排序的完全二叉树,其中任一非终端节点的数据值均不大于(或不小于)其左孩子和右孩子节点的值。
最大堆和最小堆是 二叉堆 的两种形式。
最大堆:根结点的键值是所有堆结点键值中最大者。
最小堆:根结点的键值是所有堆结点键值中最小者。
而最大-最小堆集结了最大堆和最小堆的优点,这也是其名字的由来。
最大-最小堆是最大层和最小层交替出现的 二叉树 ,即最大层结点的儿子属于最小层,最小层结点的儿子属于最大层。
以最大(小)层结点为根结点的子树保有最大(小)堆性质:根结点的键值为该子树结点键值中最大(小)项。 
                                                                                                                                                                                               
一:堆
  我们构建一个堆类,用最大堆和最小堆来继承他。
#ifndef _HEAP_H
#define _HEAP_H

#include <iostream>
using namespace std;

enum{DEFAULT_SIZE = 10};

template <typename T>
class Heap{
public:
	Heap() = default;
	virtual ~Heap() = default;
public: 
	virtual void show_heap()const = 0;
	virtual bool insert_heap(const T&) = 0;
	virtual bool remove_heap(T &) = 0;
};

//public interface

#endif   /*Heap.h*/

二:最大堆
  下面是最大堆的实现:
#ifndef _MAXHEAP_H
#define _MAXHEAP_H

#include <iostream>

#include "Heap.h"

template <typename T>
class MaxHeap : public Heap<T>{
public:
	MaxHeap(int);
	MaxHeap(const T [], const int);
	~MaxHeap();
public:
	bool insert_heap(const T&);
	bool remove_heap(T &);

	void show_heap()const;
protected:
	void sift_down(int, int);
	void sift_up(int);
private:
	T *heap;
	int size;
	int capacity;
};

//public interface

template <typename T>
MaxHeap<T>::MaxHeap(int sz = DEFAULT_SIZE)
{
	capacity = sz > DEFAULT_SIZE ? sz : DEFAULT_SIZE;
	heap = new T[capacity];
	assert(heap != NULL);
	size = 0;
}

template <typename T>
MaxHeap<T>::MaxHeap(const T arr[], const int arrSize)
{
	capacity = arrSize > DEFAULT_SIZE ? arrSize : DEFAULT_SIZE;
	heap = new T[capacity];
	assert(heap != NULL);
	size = arrSize;

	for(int i=0; i<size; ++i)
		heap[i] = arr[i];
	
	int curPos = size/2 - 1;
	while(curPos >= 0){
		sift_down(curPos, size-1);
		--curPos;
	}
	
}

template <typename T>
MaxHeap<T>::~MaxHeap()
{
	delete []heap;
	heap = NULL;
	capacity = size = 0;
}

template <typename T>
bool MaxHeap<T>::insert_heap(const T& val)
{
	if(size >= capacity)
		return false;
	
	heap[size] = val;
	sift_up(size);
	++size;
	return true;
}

template <typename T>
bool MaxHeap<T>::remove_heap(T &val)
{
	if(size <= 0)
		return false;
	
	val = heap[0];
	heap[0] = heap[size-1];
	--size;
	sift_down(0, size-1);
	return true;
}

template <typename T>
void MaxHeap<T>::show_heap()const
{
	for(int i=0; i<size; ++i)
		std::cout << heap[i] << " ";
	std::cout << std::endl;
}

//protected interface

template <typename T>
void MaxHeap<T>::sift_down(int start, int end)
{
	int i = start;
	int j = i*2 + 1;

	T tmp = heap[i];
	while(j <= end){
		if(j+1 <= end && heap[j] < heap[j+1])
			++j;
		if(tmp < heap[j])
			heap[i] = heap[j];
		else
			break;

		i = j;
		j = j*2 + 1;
	}
	heap[i] = tmp;
}

template <typename T>
void MaxHeap<T>::sift_up(int start)
{
	int j = start;
	int i = (start-1) / 2;

	T tmp = heap[j];
	while(j > 0){
		if(tmp < heap[i])
			break;
		else
			heap[j] = heap[i];
		
		j = i;
		i = (i-1) / 2;
	}
	heap[j] = tmp;
}

#endif   /*MaxHeap.h*/

三:最小堆
  下面是最小堆的实现:
#ifndef _MINHEAP_H
#define _MINHEAP_H

#include <assert.h>

#include "Heap.h"

template <typename T>
class MinHeap : public Heap<T>{
public:
	MinHeap(int);
	MinHeap(const T [], const int );
	~MinHeap();
public:
	bool insert_heap(const T&);
	bool remove_heap(T &);
	
	void show_heap()const;
protected:
	void sift_down(int, int);
	void sift_up(int);
private:
	T* heap;
	int size;
	int capacity;
};

//interface

template <typename T>
MinHeap<T>::MinHeap(int sz = DEFAULT_SIZE)
{
	capacity = sz > DEFAULT_SIZE ? sz : DEFAULT_SIZE;
	heap = new T[capacity];
	assert(heap != NULL);
	size = 0;
}

template <typename T>
MinHeap<T>::MinHeap(const T arr[], const int arrSize)
{
	capacity = arrSize > DEFAULT_SIZE ? arrSize : DEFAULT_SIZE;
	heap = new T[capacity];
	assert(heap != NULL);
	size = arrSize;

	for(int i=0; i<arrSize; ++i)
		heap[i] = arr[i];
	
	int curPos = arrSize/2 - 1;
	while(curPos >= 0){
		sift_down(curPos, arrSize-1);
		--curPos;
	}
}

template <typename T>
MinHeap<T>::~MinHeap()
{
	delete []heap;
	heap = NULL;
	capacity = size = 0;
}

template <typename T>
bool MinHeap<T>::insert_heap(const T& val)
{
	if(size >= capacity)
		return false;
	
	heap[size] = val;
	sift_up(size);
	++size;
	return true;
}

template <typename T>
bool MinHeap<T>::remove_heap(T& val)
{
	if(size <= 0)
		return false;
	
	val = heap[0];
	heap[0] = heap[size-1];
	--size;
	sift_down(0, size-1);
	return true;
}

template <typename T>
void MinHeap<T>::show_heap()const
{
	for(int i=0; i<size; ++i)
		std::cout << heap[i] << " ";
	std::cout << std::endl;
}

//protected interface

template <typename T>
void MinHeap<T>::sift_down(int start, int end)
{
	int i = start;
	int j = start*2 + 1;

	T tmp = heap[i];
	while(j <= end){
		if(j+1 < end && heap[j] > heap[j+1])
			++j;
		if(tmp < heap[j])
			break;
		else
			heap[i] = heap[j];
		
		i = j;
		j = j*2 + 1;
	}
	heap[i] = tmp;
}

template <typename T>
void MinHeap<T>::sift_up(int start)
{
	int j = start;
	int i = (start-1) / 2;

	T tmp = heap[j];
	while(j > 0){
		if(tmp > heap[i])
			break;
		else
			heap[j] = heap[i];
		j = i;
		i = (i-1) / 2;
	}
	heap[j] = tmp;
}

#endif

四:测试如下:
#include "MinHeap.h"
#include "MaxHeap.h"
#include <iostream>
using namespace std;

int main()
{
	int array[] = {23, 9, 34, 2, 56, 89, 35, 54};
	
	cout << "***************************MinHeap***************************" << endl;
	MinHeap<int> min_heap(array, sizeof(array)/sizeof(int));
	
	min_heap.show_heap();
	min_heap.insert_heap(1);
	min_heap.show_heap();
	for(int i=0; i<9; ++i){
		int val;
		min_heap.remove_heap(val);
		cout << val << " ";
	}
	cout << endl;
	
	MaxHeap<int> max_heap(array, sizeof(array)/sizeof(int));
	cout << "***************************MaxHeap**************************" << endl; 
	max_heap.show_heap();
	max_heap.insert_heap(99);
	max_heap.show_heap();
	for(int i=0; i<9; ++i){
		int val;
		max_heap.remove_heap(val);
		cout << val << " ";
	}
	cout << endl;
	
	return 0;
}
结果如下:




  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值