堆的概念:

如果有一个关键码的集合K = {k0, k1, k2 ,·······, kn-1},把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足: ki <= k2*i + 1 且ki <= k2*i + 2 (ki >= k2*i + 1 且ki >= k2*i + 2) i= 0, 1, 2, 3······,则称这个推为最小堆(或最大堆)。(堆的底层其实就是一个数组,而后面所说的左右孩子其实就是相对与图中,ki 这个节点的左右孩子其实就是下标为 ki*2+1,和ki*2+2的数)

                        

最小堆: 任一节点的关键码都小于或等于他孩子节点的关键码,位于堆顶节点的关键码最小。从根节点到每个节点的路径上数组元素组成的序列都是递增的。

最大堆: 任一节点的关键码都大于或等于他孩子节点的关键码,位于堆顶节点的关键码最大。从根节点到每个节点的路径上数组元素组成的序列都是递减的。

假设有一组数组 int array[] = { 53, 117, 78, 9, 45, 65, 87, 23 };先按照二叉树的方式插入每一个节点插入后:


如果将array数组中的数按照最小堆排序则:

从int idx= (sizeof(array)/sizeof(array[0]) - 1)>>1的元素处开始调整,然以后依次--idx处的节点调整,一直到堆顶。此时idx的值为3则从标号为3的节点开始调整。





从上面的示意图中可以看出每次检测的时候都是从他的左右孩子中取一个较小值和其进行比较如果满足小堆的性质则进行下一个节点的检测,如果不满足则交换他们的值,然后继续检测他的孩子节点是否还满足小堆的性质一直到这个子树的叶子节点,完成之后才进行下一个节点的检测。最后将节点的个数加一

节点的插入

每次插入一个节点都是在叶子节点出插入,然后进行向上调整(向上调整就是和刚才小堆的调整一样从新插入的节点的双亲节点处开始检测,如果满足则直接退出,如果不满足则继续进行向上调整,直到根节点)



节点的删除

节点的删除其实就是删除根节点(因为根节点才是最小或者最大的节点删除其他节点没有意义),而删除根节点不好删除,此时我们就需要一种相对与替换法的方法,就是将根节点和最后一个叶子节点交换然后让节点的个数减1。然后进行向下调整(此时的向下调整和向上调整刚好相反,从根节点开始和他的左右孩子中较小的一个进行比较,取其中较小的一个和他进行交换,然后继续向下调整(而这里的调整我认为只调整和他交换的那个节点的子树因为另外的那个节点的子树并没有调整所以还是满足的堆的性质的),直到叶子节点。)



#include "iostream"
using namespace std;
#include <vector>
#include <assert.h>

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

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

// 小堆
template<class T, class Compare = Less<T>>
class Heap
{
public:
	Heap()
	{}

	Heap(const T array[], int size)
	{
		_heap.reserve(size);
		for (int i = 0; i < size; ++i)
			_heap.push_back(array[i]);
		int index = (_heap.size() - 1)>>1;
		for (; 0 <= index; --index)
			_AdjustDown(index);
	}
	void Insert(const T& data)
	{
		_heap.push_back(data);
		int index = (_heap.size() - 1) >> 1;
		//堆的插入每次都在已经建成的而最小堆的后面插入,但插入之后,有可能破坏了堆的结构,这时就需要对堆自下而上的对其调整。
		_AdjustUp(index);
	}
	
	void Remove()
	{
		assert(!_heap.empty());
		std::swap(_heap[0], _heap[_heap.size() - 1]);
		_heap.pop_back();
		//堆的删除是:从堆中删除堆顶元素。移除堆顶元素之后,用堆的最后一个节点填补取 走的堆顶元素,并将堆的实际元素个数减1。
		//但用最后一个元素取代堆顶元素之后有可能破坏堆,因此需要将对自顶向下调整,使其满足最大或最小堆。
		_AdjustDown(0);
	}

	size_t Size()const
	{
		return _heap.size();
	}

	bool Empty()const
	{
		return _heap.empty();
	}
	
	const T& Top()const
	{
		return _heap[0];
	}

protected:
	void _AdjustDown(size_t parent)
	{
		size_t child = parent * 2 + 1;
		while (child < _heap.size())
		{
			Compare com;
			if ((child + 1) < _heap.size() && com(_heap[child + 1], _heap[child]))
				child += 1;
			if (com(_heap[child], _heap[parent]))
			{
				std::swap(_heap[parent], _heap[child]);
				parent = child;
				child = child * 2 +1;
			}
			else
				return;
		}
	}
	
	void _AdjustUp(size_t child)
	{
		size_t parent = (child - 1)>>1;
		while (child != 0)
		{
			if (Compare()(_heap[child], _heap[parent]))
			{
				std::swap(_heap[child], _heap[parent]);
				child = parent;
				parent = (child - 1) >> 1;;
			}
			else
				return;
		}
	}
private:
	std::vector<T> _heap;
};

template<class T, class Compare = Less<T>>
class PriorityQueue
{
public:
	PriorityQueue()
	{}

	void Push(const T& data)
	{
		_hp.Insert(data);
	}

	void Pop()
	{
		_hp.Remove();
	}

	const T& Top()const
	{
		_hp[0];
	}

	size_t Size()const
	{
		_hp.Size();
	}

	bool Empty()const
	{
		_hp.Empty();
	}

protected:
	Heap<T, Compare> _hp;
};


int main()
{
	int array[] = { 53, 117, 78, 9, 45, 65, 87, 23 };
	//PriorityQueue<int> Pq;
	//Pq.Push(1);
	Heap<int,Greater<int>> hp(array,sizeof(array)/sizeof(array[0]));//创建大堆
	
	//hp.Insert(1);
	//hp.Remove();
	return 0;
}





                
下载方式:https://pan.quark.cn/s/c9b9b647468b ### 初级JSP程序设计教程核心内容解析#### 一、JSP基础概述JSP(JavaServer Pages)是由Sun Microsystems公司创建的一种动态网页技术规范,主要应用于构建动态网站及Web应用。JSP技术使得开发者能够将动态数据与静态HTML文档整合,从而实现网页内容的灵活性和可变性。##### JSP的显著特性:1. **动态与静态内容的分离**:JSP技术支持将动态数据(例如数据库查询结果、实时时间等)嵌入到静态HTML文档中。这种设计方法增强了网页的适应性和可维护性。2. **易用性**:开发者可以利用常规的HTML编辑工具来编写静态部分,并通过简化的标签技术将动态内容集成到页面中。3. **跨平台兼容性**:基于Java平台的JSP具有优良的跨操作系统运行能力,能够在多种不同的系统环境中稳定工作。4. **强大的后台支持**:JSP能够通过JavaBean组件访问后端数据库及其他资源,以实现复杂的数据处理逻辑。5. **执行效率高**:JSP页面在初次被请求时会被转换为Servlet,随后的请求可以直接执行编译后的Servlet代码,从而提升了服务响应的效率。#### 二、JSP指令的运用JSP指令用于设定整个JSP页面的行为规范。这些指令通常放置在页面的顶部,向JSP容器提供处理页面的相关指导信息。##### 主要的指令类型:1. **Page指令**: - **语法结构**:`<%@ page attribute="value" %>` - **功能**:定义整个JSP页面的运行特性,如设定页面编码格式、错误处理机制等。 - **实例**: ...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值