最大堆最小堆的建立

堆是一种数据结构,它是一颗完全二叉树,最大堆和最小堆是二叉堆的两种形式。

最大堆:每个父亲结点的键值都大于孩子结点

最小堆:每个父亲结点的键值都小于孩子结点


下面看一下我的实现方式↓

#pragma once
#include 
   
   
    
    
using namespace std;

template
    
    
     
     
struct Great
{
   bool	operator()(const T& left ,const T& right)const
	{
	   return left > right;
	}
};

template
     
     
      
      
struct Less
{
	bool	operator()(const T& left, const T& right)const
	{
		return left < right;
	}
};

template
      
      
       
       >
class Heap 
{
public:
	Heap()
	{}

	Heap(T* a, size_t n)      //用一个数组构建堆的构造函数
	{
		_arr.reserve(n);
		for (int i = 0; i < n; i++)
		{
			_arr.push_back(a[i]);
		}

		//调整堆
		for (int i = (_arr.size() - 2) / 2; i >= 0; --i)
		{
			AdjustDown(i);
		}
	}

	void AdjustDown(int root)      //向下调整算法
	{
		Comp com;
		int parent = root;
		int child = parent * 2 + 1;
		while (child < _arr.size())
		{
			if (child + 1 < _arr.size() && com(_arr[child + 1] , _arr[child]))
			{
				child++;
			}
			if (com(_arr[child],_arr[parent]))
			{
				swap(_arr[child], _arr[parent]);
				parent = child; child = parent * 2 + 1;
			}
			else break;    //循环到孩子小于父亲便可停止
		}
	}     
	void AdjustUp(int child)    //向上调整算法
	{
		Comp com;
		int parent = (child - 1) / 2;
		while (parent >= 0)
		{
			if (com(_arr[child], _arr[parent]))
			{
				swap(_arr[parent], _arr[child]);
				child = parent;
				parent = (child - 1) / 2;
			}
			else
				break;
		}
	}

	void Push(const T& x)    //从堆尾插入一个数据  (数组尾)
	{
		_arr.push_back(x);
		AdjustUp(_arr.size() - 1);
	}
	void Pop()             //删除堆顶数据  (数组头)
	{
		swap(_arr[0], _arr[_arr.size() - 1]);
		_arr.pop_back();
		AdjustDown(0);
	}
	size_t Size()   //返回大小
	{
		return _arr.size();
	}

	bool Empty()  //是否为空
	{
		return _arr.empty();
	}
	T& Top()   //返回 堆顶数据
	{
		assert(_arr.size() > 0);
		return _arr[0];
	}
protected:
	vector
       
       
         _arr; //一个vector 堆的底层是一个数组; }; 
       
      
      
     
     
    
    
   
   


其中 向上调整与向下调整是建立一个最大最小堆的关键;调整时的比较大小是利用一个仿函数进行选择默认为大堆;

堆的作用挺大,比如优先级队列,top K问题 ,或者选择排序都用到堆的结构。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值