双端优先队列deap及其代码实现

#pragma once
#include <iostream>
#include <cmath>
using namespace std;

class Deap
{
public:

	//测试用函数
	void print()
	{
		cout << "deap:";
		for (int i = 2; i <= deapIndex; ++i)
			cout << deap[i] << " ";
		cout << endl;
	}

	Deap(int size)
	{
		maxSize = size;
		deap = new int[size + 2];
		deapIndex = 1;
	}

	void push(int value)
	{
		if (deapIndex == maxSize + 1)//deap满
		{
			cout << "deap已满!" << endl;
			exit(0);
		}
		++deapIndex;
		if (deapIndex == 2)//第一个元素
			deap[deapIndex] = value;
		else
		{
			if (maxHeap(deapIndex))//要插入到最大堆
			{
				int i = minPartner(deapIndex);//在最小堆的对应元素
				if (value < deap[i])
				{
					deap[deapIndex] = deap[i];
					minInsert(i, value);
				}
				else
					maxInsert(deapIndex, value);
			}
			else//要插入到最小堆
			{
				int i = maxPartner(deapIndex);//在最大堆的对应元素
				if (value > deap[i]) 
				{
					deap[deapIndex] = deap[i];
					maxInsert(i, value); 
				}
				else
					minInsert(deapIndex, value);
			}
		}
	}

	bool maxHeap(int index)//是否在最大堆
	{
		int left = pow(2, log2_floor(index)) + pow(2, log2_floor(index) - 1);//左端点
		int right = pow(2, log2_ceil(index));//右端点

		if (index >= left && index < right)
			return true;
		else
			return false;
	}

	int minPartner(int index)//在最小堆的对应元素
	{
		return index - pow(2, log2_floor(index) - 1);
	}

	int maxPartner(int index)//在最大堆的对应元素
	{
		if (index == 2) 
			return 3;
		else
			return (index + pow(2, log2_floor(index) - 1)) / 2;
	}

	void minInsert(int index,int value)//在最小堆index的地方插入value
	{
		deap[index] = value;
		
		while (index > 2)
		{
			int parentIndex = index / 2;

			if (deap[index] < deap[parentIndex])//比父节点小
			{
				//交换
				int temp = deap[index];
				deap[index] = deap[parentIndex];
				deap[parentIndex] = temp;
				index = parentIndex;
			}
			else
				break;
		}
	}

	void maxInsert(int index, int value)//在最大堆index的地方插入value
	{
		deap[index] = value;

		while (index > 3)
		{
			int parentIndex = index / 2;

			if (deap[index] > deap[parentIndex])//比父节点大
			{
				//交换
				int temp = deap[index];
				deap[index] = deap[parentIndex];
				deap[parentIndex] = temp;
				index = parentIndex;
			}
			else
				break;
		}
	}

	int popMin()//弹出并返回最小元素
	{
		//把末尾元素放到最小堆顶部
		int res = deap[2];
		deap[2] = deap[deapIndex];
		--deapIndex;

		//向下调整最小堆
		int curIndex = 2;
		int leftChild = curIndex * 2;
		int rightChild = curIndex * 2 + 1;

		while (leftChild <= deapIndex || rightChild <= deapIndex)
		{
			// 如果最小值不是当前节点,交换节点并递归向下调整
			int smallestIndex = curIndex;
			if (leftChild <=deapIndex && deap[leftChild] < deap[smallestIndex])
				smallestIndex = leftChild;
			if (rightChild<=deapIndex && deap[rightChild] < deap[smallestIndex])
				smallestIndex = rightChild;

			// 如果最小值不是当前节点,交换节点并递归向下调整
			if (smallestIndex != curIndex)
			{
				int temp = deap[smallestIndex];
				deap[smallestIndex] = deap[curIndex];
				deap[curIndex] = temp;
				//更新调整节点
				curIndex = smallestIndex;
				leftChild = curIndex * 2;
				rightChild = curIndex * 2 + 1;
			}
			else
				break;
		}

		//如果比最大堆对应元素大,交换,调整最大堆
		int i = maxPartner(curIndex);//在最大堆的对应元素
		if (deap[curIndex] > deap[i])
		{
			int t = deap[curIndex];
			deap[curIndex] = deap[i];
			maxInsert(i, t);
		}
		
		return res;
	}

	int findMin()//返回最小元素
	{
		return deap[2];
	}

	int findMax()//返回最大元素
	{
		if (deapIndex == 2)
			return deap[2];
		else
			return deap[3];
	}
	
	bool empty()
	{
		return deapIndex == 1;
	}
	
	int log2_ceil(int n)
	{
		return (int)ceil(log2(n));
	}

	int log2_floor(int n)
	{
		return (int)floor(log2(n));
	}

private:
	int* deap; //最大最小堆
	int maxSize; //deap大小
	int deapIndex; //最后一个元素索引
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值