C++数据结构之:堆Heap

摘要:

  it人员无论是使用哪种高级语言开发东东,想要更高效有层次的开发程序的话都躲不开三件套:数据结构,算法和设计模式。数据结构是相互之间存在一种或多种特定关系的数据元素的集合,即带“结构”的数据元素的集合,“结构”就是指数据元素之间存在的关系,分为逻辑结构和存储结构。
  此系列专注讲解数据结构数组、链表、队列、栈、树、哈希表、图,通过介绍概念以及提及一些可能适用的场景,并以C++代码简易实现,多方面认识数据结构,最后为避免重复造轮子会浅提对应的STL容器。本文介绍的是堆Heap。

(开发环境:VScode,C++17)

关键词C++数据结构Heap

声明:本文作者原创,转载请附上文章出处与本文链接。

正文:

介绍:

  堆比较特殊,通常被看作一棵完全二叉树的数组对象。被用于实现“优先队列”(priority queues),优先队列是一种数据结构,可以自由添加数据,但取出数据时要从最小值开始按顺 序取出。在堆的树形结构中,各个顶点被称为“结点”(node),数据就存储在这些结点中。
在这里插入图片描述

  上面叫大顶堆,如果每一个节点小于子树中每个节点的值,那就叫小顶堆。

特性:

只要满足下面两个特点的树形结构就是堆:

  • 堆是一个完全二叉树(所谓完全二叉树就是除了最后一层其他层的节点个数都是满的)。
  • 堆中每一个节点的值都必须大于(大顶堆/最大堆)等于或者小于(小顶堆/最小堆)其子树中每一个节点的值。
应用:
  • 堆排序:堆排序是一种基于堆的排序算法,利用最大堆(或最小堆)的性质来排序数据,时间复杂度为O(n log n),且不需要额外的存储空间,是一种非常高效的排序方法。
  • 图算法:在许多图算法中,如计算最短路径的Dijkstra算法和构建最小生成树的Prim算法,堆被用作优先队列来选择下一个要处理的顶点。
  • 动态数据流的中值查找:堆可以用来快速计算动态数据流的中值或其他顺序统计量。
  • 带权调度问题:在处理带权任务调度问题时,可以使用最小堆来安排任务的执行顺序,以最小化等待时间或优化其他指标。
  • Top K问题:堆经常用于解决Top K问题,即从一组数据中找到最大或最小的K个元素。
  • 频率统计和数据压缩:在频率统计和数据压缩领域,如Huffman编码算法,使用最小堆来构建Huffman树,以实现高效的编码方案。
代码实现:
#ifndef CHEAP_H
#define CHEAP_H
#include <iostream>
#include <algorithm>
#include <vector>
#include <cassert>

using namespace std;
template <typename T>
class MaxHeap
{
public:
	void heapify(int i);							// 辅助函数:调整堆  
    void push(const T& element); 					// 添加元素到堆中
    T pop();										// 移除并返回堆顶元素  
  
    T top() const; 									// 返回堆顶元素
    bool empty() const { return heap.empty(); }  	// 检查堆是否为空  
    size_t size() const { return heap.size(); }   	// 返回堆的大小  

private:
    vector<T> heap;
};

template <typename T>
inline void MaxHeap<T>::heapify(int i)
{
	int left = 2 * i + 1;
	int right = 2 * i + 2;
	int largest = i;
	if (left < heap.size() && heap[left] > heap[largest]) {
		largest = left;
	}
	if (right < heap.size() && heap[right] > heap[largest]) {
		largest = right;
	}
	if (largest != i) {
		swap(heap[i], heap[largest]);
		heapify(largest); // 递归调整子堆
	}
}

template <typename T>
inline void MaxHeap<T>::push(const T &element)
{
	heap.push_back(element);
	// 从新添加的节点开始向上调整堆
	int i = heap.size() - 1;
	while (i > 0 && heap[(i - 1) / 2] < heap[i]) { 
		swap(heap[i], heap[(i - 1) / 2]);
		i = (i - 1) / 2;
	}
}

template <typename T>
inline T MaxHeap<T>::pop()
{
    if(heap.empty())
		return T();
	T top = heap[0];
	heap[0] = heap.back();
	heap.pop_back();

	// 从堆顶开始向下调整堆
	heapify(0);
	return top;
}

template <typename T>
inline T MaxHeap<T>::top() const
{
	if(heap.empty())
		return T();
	return heap[0];
}

#endif // !CHEAP_H
#include "cheap.h"
using namespace std;

int main() 
{
    MaxHeap<int> maxHeap;
    maxHeap.push(20);
    maxHeap.push(18);
    maxHeap.push(15);
	maxHeap.push(8);
	maxHeap.push(10);
	maxHeap.push(5);
	maxHeap.push(3);
    cout << "Top element: " << maxHeap.top() << endl;
    maxHeap.pop();
    cout << "Top element after pop: " << maxHeap.top() << endl;
    return 0;
};

在这里插入图片描述

对应STL:
  • priority_queue:

    priority_queue 默认在 vector 上使用堆算法将 vector 中元素构造成大顶堆的结构,用户也可以通过自定义模板参数中的 class Compare 来实现一个小顶堆。因此 priority_queue 就是堆 ,所有需要用到堆的位置,都可以考虑使用 priority_queue。

推荐阅读

C/C++专栏:https://blog.csdn.net/weixin_45068267/category_12268204.html
(内含其它数据结构及对应STL容器使用)

  • 31
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值