自定义minheap存结构体指针无法比较

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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值