#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; //最后一个元素索引
};
双端优先队列deap及其代码实现
最新推荐文章于 2023-12-14 15:09:10 发布