堆结构实现

堆结构介绍

堆是一种数据结构,在逻辑上是一颗完全二叉树,在存储上是一个数组。堆有大顶堆、和小顶堆之分,大顶堆:对于每个父节点而言,其左右子节点都是小于父节点的,所以根节点也就是堆顶保存的是堆内最大的元素;小顶堆:每个父节点的值都是小于子节点的,堆顶保存堆内最小的元素。

堆的存储

上面已经介绍了堆是用数组来存储的,但是怎么来存呢?其实就是把一棵完全二叉树按层遍历后的顺序依次放入一个数组里面是一样的,比如下面的一颗完全二叉树:
image.png
对应存储数组:
image.png
除此之外我们还需要知道父节点和子节点在数组中索引的一些关系:
当前节点索引为i则:
左子节点索引:2 * i + 1
右子节点索引:2 * i + 2
父节点索引:(i - 1) / 2

堆的基本操作(这里以大顶堆为例)

上浮: 将当前位置i对应的元素向上移动,如果父节点小于当前值就交换,此时当前位置就更新到父节点的位置,然后继续和父节点判断重复此过程直到不能交换为止。
对应代码:

void seekUp(int i)
{
	while (i >= 0)
	{
		if (heap[i] > heap[(i - 1) / 2])
			swap(heap[i], heap[(i - 1) / 2]);
		else
		    return;
		i = (i - 1) / 2;
	}
}

下沉: 将当前位置i对应的元素向下移动,如果子节点大于当前值就交换(如果左右子节点值都大于父节点则选值最大的子节点),此时当前位置就更新到所交换的子节点的位置,然后继续和子节点节点判断重复此过程直到不能交换为止。

void seekDown(int i)
{
	while (i < n)
	{
        int maxIdx = i;
        int leftIdx = i * 2 + 1;
        int rightIdx = i * 2 + 2;
        if(leftIdx < n && heap[leftIdx] > heap[maxIdx]) maxIdx = leftIdx;
        if(rightIdx < n && heap[rightIdx] > heap[maxIdx]) maxIdx = rightIdx; 
        if(maxIdx != i) swap(heap[maxIdx], heap[i]);
        else return;
	}
}

删除: 将数组的最后一个元数赋值为堆顶然后进行下层操作

void deleteHeap()
{
	heap[0] = heap[--n];
	seekDown(0);
}

插入: 在数组的末尾添加一个元数然后进行上浮操作

void insertHeap(int val)
{
	heap[n++]=val;
	seekUp(n-1);
}

整体代码

class HEAD
{
public:
	HEAD() { n = 0; heap.resize(1000, 0); }
	HEAD(vector<int> v) :heap(v) { n = v.size(); }
	//插入
	void insertHeap(int val)
	{
		heap[n++] = val;
		seekUp(n - 1);
	}
	//删除
	void deleteHeap()
	{
		heap[0] = heap[--n];
		seekDown(0);
	}
	//获取顶端的值
	int getVal()
	{
		if (n == 0)
			return INT_MIN;
		return heap[0];
	}
	//下沉
	void seekDown(int i)
	{
		while (i < n)
		{
			int maxIdx = i;
			int leftIdx = i * 2 + 1;
			int rightIdx = i * 2 + 2;
			if (leftIdx < n && heap[leftIdx] > heap[maxIdx]) maxIdx = leftIdx;
			if (rightIdx < n && heap[rightIdx] > heap[maxIdx]) maxIdx = rightIdx;
			if (maxIdx != i) swap(heap[maxIdx], heap[i]);
			else return;
		}
	}
	//上浮
	void seekUp(int i)
	{
		while (i >= 0)
		{
			if (heap[i] > heap[(i - 1) / 2])
				swap(heap[i], heap[(i - 1) / 2]);
			else
				return;
			i = (i - 1) / 2;
		}
	}
	void printHeap()
	{
		for (int i = 0; i < n; i++)
			cout << heap[i] << " ";
		cout << endl;
	}
private:
	vector<int> heap;
	int n;
};
int main()
{
	HEAD h;
	h.insertHeap(5);
	h.insertHeap(14);
	h.insertHeap(4);
	h.printHeap();
	h.deleteHeap();
	h.printHeap();
	return 0;
}

运行结果:

14 5 4
5 4
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值