C++ 优先队列的实现(大堆)

优先队列是一种支持插入新元素和删除最大元素的数据结构。它和我们之前学过的队列和栈很相似,优先队列是队列和栈的拓展。而堆是支持优先队列的操作的一种数据结构。实现堆的方法有好几种,第一:我们可以使用链表,以O(1)时间插入,以O(N)时间删除。第二:使用二叉树,二叉树的所有操作需要O(log N),但是插入和删除操作却会导致二叉树严重的不平衡,那AVL树呢?插入和删除的操作需要O(log N),而且不会破坏树的平衡性,可以是可以,但是太过复杂。那怎么实现呢?我们往往使用基于数组实现的堆的数据结构。为什么呢?堆是一颗完全二叉树(也就是说插入和删除操作的时间复杂度都为O(log N{\color{Blue} })),这也是堆的结构性。堆也有堆序性,也就说堆中任意节点的键值都大于它的孩子的键值。我们往往把这种堆叫大堆。那么堆一般在哪里使用呢?操作系统中使用优先级调度算法堆进程进行调度等等。现在就让我们看看堆怎么实现吧!!

我们首先应该知道位置为k的节点,其父节点为[k/2],其左孩子的位置为2k.其右孩子的位置为2k+1.

堆的接口:

               

class Heap {
public:
	Heap(std::vector<int>& _heap) :heap(_heap) {};
public:
	void Build_Heap();
	bool IsEmpty()const;
	void Insert(const ElemType key);
	void Delete();
	void Display()const;
	bool Find(const ElemType key)const;
	ElemType FindMax()const;
	void Heap_Sort();
private:
	std::vector<ElemType>heap;
	void swap(int i, int j);
	void Heapify(int i, size_t size);
};

堆的删除操作:我们删除堆中的最大元素时,堆中少一个元素,这个很简单,但是这时堆的根节点为空,我们必须移入一个元素来填充这个空穴。怎么移入呢?我们可以把空穴的两个孩子中最大的元素移入其中,慢慢的向下移动,知道堆中的最后一个元素可以放入空穴中,此过程叫做下滤。

void Heap::Delete() {
	if (!IsEmpty()) {
		int i = 0;
		int child = 0;
		auto lastelem = heap[heap.size()-1];//最后的元素
		for (i = 1; i * 2 <= heap.size(); i = child) {
			child = i * 2;
			if ((child != heap.size()-1) && (heap[child] < heap[child + 1]))
				++child;
			if (lastelem >= heap[child])
				break;
			else
				heap[i] = heap[child];
		}

		heap[i] = lastelem;
	}

}

堆的插入操作:为将元素插入堆中,我们先在最后位置的下一个位置创建一个空穴,然后通过比较待插入元素与空穴的父节点的键值,进行向上移动,最后将待插入元素放入此空穴中,此过程叫上移。堆中的0位置相当于标记,让其为无穷大,可以让循环结束。

void Heap::Insert(const ElemType key) {
	if (!IsEmpty()) {
		int i = 0;
		auto j = heap.size() - 1;
		for (i = j; heap[i / 2] < key; i /= 2)
			heap[i] = heap[i / 2];

		heap[i] = key;
	}
}

堆的建立与排序:

void Heap::swap(int i, int j) {
	if (!IsEmpty()) {
		auto temp = heap[i];
		heap[i] = heap[j];
		heap[j] = temp;
	}
}

void Heap::Heapify(int i, size_t size) {

	if (i > size)
		return;
	auto c1 = i * 2;
	auto c2 = i * 2 + 1;
	auto max = i;
	if (c1<size && heap[c1]>heap[max])
		max = c1;
	if (c2<size && heap[c2]>heap[max])
		max = c2;
	if (max != i) {
		swap(max, i);
		Heapify(max, size);
	}
	
}

void Heap::Build_Heap() {
	auto last_node = heap.size();
	auto parernt_last_node = (last_node) / 2;
	for (int i = parernt_last_node; i >= 1; --i) {
		Heapify(i, heap.size());
	}
}

void Heap::Heap_Sort() {
	if (!IsEmpty()) {
		Build_Heap();
		for (int i = heap.size() - 1; i >= 0; --i) {
			swap(i, 0);
			Heapify(0, i);
		}
	}
}

此堆建立与排序,参考我的另一篇博客。

完整代码如下:

#include<iostream>
#include<vector>
#include<memory>
typedef int ElemType;
const int MAX = 999;

class Heap {
public:
	Heap(std::vector<int>& _heap) :heap(_heap) {};
public:
	void Build_Heap();
	bool IsEmpty()const;
	void Insert(const ElemType key);
	void Delete();
	void Display()const;
	bool Find(const ElemType key)const;
	ElemType FindMax()const;
	void Heap_Sort();
private:
	std::vector<ElemType>heap;
	void swap(int i, int j);
	void Heapify(int i, size_t size);
};

void Heap::swap(int i, int j) {
	if (!IsEmpty()) {
		auto temp = heap[i];
		heap[i] = heap[j];
		heap[j] = temp;
	}
}

void Heap::Heapify(int i, size_t size) {

	if (i > size)
		return;
	auto c1 = i * 2;
	auto c2 = i * 2 + 1;
	auto max = i;
	if (c1<size && heap[c1]>heap[max])
		max = c1;
	if (c2<size && heap[c2]>heap[max])
		max = c2;
	if (max != i) {
		swap(max, i);
		Heapify(max, size);
	}
	
}

void Heap::Display()const {
	if (!IsEmpty()) {
		for (int i = 1; i < heap.size(); ++i) {
			std::cout << heap[i] << std::endl;
		}
	}
}

void Heap::Build_Heap() {
	auto last_node = heap.size();
	auto parernt_last_node = (last_node) / 2;
	for (int i = parernt_last_node; i >= 1; --i) {
		Heapify(i, heap.size());
	}
}

bool Heap::IsEmpty()const {
	return heap.size() == 0;
}

bool Heap::Find(const ElemType key)const {
	if (!IsEmpty()) {
		for (int i = 1; i < heap.size(); ++i) {
			if (key == heap[i])
				return true;
		}

		return false;
	}
}

ElemType Heap::FindMax()const{
	if (!IsEmpty()) {
		return heap[1];
	}

}

void Heap::Insert(const ElemType key) {
	if (!IsEmpty()) {
		int i = 0;
		auto j = heap.size() - 1;
		for (i = j; heap[i / 2] < key; i /= 2)
			heap[i] = heap[i / 2];

		heap[i] = key;
	}
}

void Heap::Delete() {
	if (!IsEmpty()) {
		int i = 0;
		int child = 0;
		auto lastelem = heap[heap.size()-1];
		for (i = 1; i * 2 <= heap.size(); i = child) {
			child = i * 2;
			if ((child != heap.size()-1) && (heap[child] < heap[child + 1]))
				++child;
			if (lastelem >= heap[child])
				break;
			else
				heap[i] = heap[child];
		}

		heap[i] = lastelem;
	}

}

void Heap::Heap_Sort() {
	if (!IsEmpty()) {
		Build_Heap();
		for (int i = heap.size() - 1; i >= 0; --i) {
			swap(i, 0);
			Heapify(0, i);
		}
	}
}

int main(void) {
	std::vector<ElemType>vec{ MAX,4,7,2,5,8,3,6,9};
	Heap heap(vec);
	heap.Build_Heap();
	heap.Display();
	std::cout << "----------" << std::endl;
	heap.Insert(12);
	heap.Display();

	std::cout << "--------------" << std::endl;
	heap.Delete();
	heap.Display();
	std::cout << "-------------------" << std::endl;
	heap.Heap_Sort();
	heap.Display();
}

参考 《数据结构与算法分析——C语言描述》

发布了50 篇原创文章 · 获赞 11 · 访问量 4091

猜你喜欢

转载自blog.csdn.net/qq_43145594/article/details/102536408