1.现象
在用自己写的minheap
时,minheap
存入指针结构体,但结构体内部重载了比较运算符,但却不能得出正确结果
结构体定义如下:
struct person {
int age;
int weight;
person() {}
person(int a, int w) :age(a), weight(w) {}
bool operator<(const person& p)const {
return age < p.age;
}
bool operator>(const person& p)const {
return age > p.age;
}
bool operator<=(const person& p)const {
return age <= p.age;
}
bool operator>=(const person& p)const {
return age >= p.age;
}
};
minheap
存入结构体指针:
MinHeap<person*> h;
person* p1 = new person(16, 45);
person* p2 = new person(17, 44);
h.Insert(p1);
h.Insert(p2);
person* p;
h.RemoveMin(p);
cout << p->age << endl;
得到的结果:
17
但若存放结构体,得到的结果却是正确的:
MinHeap<person> h;
person p1(16, 45);
person p2(17, 44);
h.Insert(p1);
h.Insert(p2);
person p;
h.RemoveMin(p);
cout << p.age << endl;
结果:
16
2.原因
原因是因为minheap里存放的是结构体指针,对于指针默认比较的是指针的地址,故会选择地址最小的那个指针,由于每次分配的地址不同,故每次得到的结果可能会不一样:
MinHeap<person*> h;
person* p1 = new person(16, 45);
person* p2 = new person(11, 44);
person* p3 = new person(12, 45);
h.Insert(p1);
h.Insert(p2);
h.Insert(p3);
person* p;
h.RemoveMin(p);
cout << p->age << endl;
cout << "p1:" << p1 << endl;
cout << "p2:" << p2 << endl;
cout << "p3:" << p3 << endl;
结果:
11
p1:00D31658
p2:00D31578
p3:00D315B0
可见选择的是地址最小的。
3.源码:
#include<iostream>
#include<vector>
using namespace std;
const int DefaultSize = 2000;
template<typename T>
class MinHeap
{
public:
//构造函数:建立空堆
MinHeap(int sz = DefaultSize)
{
maxHeapSize = (DefaultSize < sz) ? sz : DefaultSize;
heap = new T[maxHeapSize];
currentSize = 0;
}
//构造函数通过一个数组建立堆
MinHeap(T arr[], int n)
{
maxHeapSize = (DefaultSize < n) ? n : DefaultSize;
heap = new T[maxHeapSize];
for (int i = 0; i < n; i++)
{
heap[i] = arr[i];
}
currentSize = n;
int currentPos = (currentSize - 2) / 2; //找最初调整位置:最后分支结点
while (currentPos >= 0) //自底向上逐步扩大形成堆
{
siftDowm(currentPos, currentSize - 1); //局部自上向下下滑调整
currentPos--; //再向前换一个分支结点
}
}
//将x插入到最小堆中
bool Insert(const T& x)
{
if (currentSize == maxHeapSize)
{
cout << "Heap Full!" << endl;
return false;
}
heap[currentSize] = x; //插入
siftUp(currentSize); //向上调整
currentSize++; //堆计数+1
return true;
}
bool RemoveMin(T& x)
{
if (!currentSize)
{
cout << "Heap Empty!" << endl;
return false;
}
x = heap[0]; //返回最小元素
heap[0] = heap[currentSize - 1]; //最后元素填补到根结点
currentSize--;
siftDowm(0, currentSize - 1); //自上向下调整为堆
return true;
}
int size() {
return currentSize;
}
T* top() {
return &heap[0];
}
bool isEmpty() {
return currentSize == 0;
}
void output()
{
for (int i = 0; i < currentSize; i++)
{
cout << heap[i];
}
cout << endl;
}
protected:
//最小堆的下滑调整算法
void siftDowm(int start, int end) //从start到end下滑调整成为最小堆
{
int cur = start;
int min_child = 2 * cur + 1; //先记max_child是cur的左子女位置
T temp = heap[cur];
while (min_child <= end)
{
if (min_child<end && heap[min_child]>heap[min_child + 1]) //找到左右孩子中最小的一个
min_child++;
if (temp <= heap[min_child])
break;
else
{
heap[cur] = heap[min_child];
cur = min_child;
min_child = 2 * min_child + 1;
}
}
heap[cur] = temp;
}
//最小堆的上滑调整算法
void siftUp(int start) //从start到0上滑调整成为最小堆
{
int cur = start;
int parent = (cur - 1) / 2;
T temp = heap[cur];
while (cur > 0)
{
if (heap[parent] <= temp)
break;
else
{
heap[cur] = heap[parent];
cur = parent;
parent = (parent - 1) / 2;
}
}
heap[cur] = temp; //回放temp中暂存的元素
}
private: //存放最小堆中元素的数组
T* heap;
int currentSize; //最小堆中当前元素个数
int maxHeapSize; //最小堆最多允许元素个数
};
struct person {
int age;
int weight;
person() {}
person(int a, int w) :age(a), weight(w) {}
bool operator<(const person& p)const {
return age < p.age;
}
bool operator>(const person& p)const {
return age > p.age;
}
bool operator<=(const person& p)const {
return age <= p.age;
}
bool operator>=(const person& p)const {
return age >= p.age;
}
};
int main() {
MinHeap<person*> h;
person* p1 = new person(16, 45);
person* p2 = new person(11, 44);
person* p3 = new person(12, 45);
h.Insert(p1);
h.Insert(p2);
h.Insert(p3);
person* p;
h.RemoveMin(p);
cout << p->age << endl;
cout << "p1:" << p1 << endl;
cout << "p2:" << p2 << endl;
cout << "p3:" << p3 << endl;
}
4.采用stl minheap存放结构体指针
包含在头文件#include<queue>
中,自定义结构体cmp即可,若存放结构体指针,函数里面的参数应该也是指针。
struct cmp
{
// 函数里面的参数应该也是指针
bool operator()(const person* a, const person* b)
{
return a->age > b->age;
}
};
int main() {
priority_queue<person*, vector<person*>, cmp> h;
person* p1 = new person(16, 40);
person* p2 = new person(15, 50);
person* p3 = new person(17, 45);
h.push(p1);
h.push(p2);
h.push(p3);
cout << h.top()->age << endl;
cout << "p1:" << p1 << endl;
cout << "p2:" << p2 << endl;
cout << "p3:" << p3 << endl;
}
结果:
15
p1:00E70E18
p2:00E711D0
p3:00E70D70