百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

歪说基础算法4-2堆探索优先世界的黑科技

toyiye 2024-06-21 12:02 12 浏览 0 评论

嘿,各位小伙伴们!今天我要向大家介绍一个非常有趣的主题——堆。你或许已经听说过堆这个名词,它可不是指一堆东西堆在一起,而是一种数据结构,是优先世界中的一把利器。通过堆,我们可以高效地实现优先队列,还可以进行堆排序,这些都是黑科技中的黑科技。

【1. 回顾上一章节】

在上一章节中,我们学习了二叉树(歪说基础算法3-1:二叉树——探索树的奇妙世界)的基本概念和遍历方式。二叉树是一种常见的数据结构,它由节点组成,每个节点最多有两个子节点,分别称为左子节点和右子节点。我们通过前序、中序和后序遍历可以访问和处理二叉树中的节点。

【2. 优先队列:选择出色的顾客】

想象一下,你是一家饭店的老板,经常需要处理顾客的点餐需求。你希望能够快速而高效地处理顾客的订单,让优先级高的顾客先被满足,这时候就可以用到优先队列。而堆正是实现优先队列的绝佳选择。

在优先队列中,每个元素都有一个优先级,我们希望优先级高的元素能够先被处理。而堆作为一种支持高效插入和删除操作的数据结构,非常适合用来实现优先队列。堆可以保证优先级最高的元素始终位于堆的根节点,这样我们就可以快速获取到优先级最高的元素。

【3. 案例一:餐厅的排队系统】

为了更好地理解堆在优先队列中的应用,我们以餐厅的排队系统为例。假设你开了一家火爆的餐厅,经常有很多顾客排队等候。为了公平有序地安排顾客的入座顺序,你决定使用堆来管理排队的顾客。

每个顾客在进入餐厅时都会被分配一个编号,并且每个顾客都有一个优先级,优先级高的顾客应该先被安排入座。你可以将顾客的信息(编号和优先级)存储在堆中,其中堆顶的顾客就是优先级最高的顾客。每当有新的顾客进入餐厅,你只需将其插入到堆中,堆会自动调整顾客的位置,确保堆顶的顾客优先级最高。

当你要安排顾客入座时,只需从堆顶取出顾客信息,并将其安排入座。这样,你就可以快速而公平地管理餐厅的排队系统,让优先级高的顾客先享用美食。'

【4. 堆的实现方式:二叉堆和斐波那契堆】

现在我们来看看如何实现堆。堆有多种实现方式,其中最常见的是二叉堆和斐波那契堆。二叉堆是一种完全二叉树,可以通过数组来表示,而斐波那契堆则是一种多叉树。

【4.1 二叉堆】

二叉堆是一种满足堆性质的完全二叉树,其中每个节点的值都大于等于(或小于等于)其子节点的值。我们可以使用数组来表示二叉堆,数组中的每个元素对应堆中的一个节点。

为了方便操作,我们一般使用最大堆或最小堆。最大堆是指父节点的值大于等于其子节点的值,而最小堆则相反,父节点的值小于等于其子节点的值。我们以最大堆为例进行解释。

在二叉堆中,堆的根节点存储在数组的第一个位置(索引为0),而任意节点 i 的左子节点存储在数组的 2i+1 位置,右子节点存储在数组的 2i+2 位置。通过这种方式,我们可以快速定位到堆中任意节点的位置。

以下是二叉堆的伪代码实现:

class MaxHeap {
private:
    std::vector<int> heap;

public:
    void insert(int num) {
        heap.push_back(num);
        int i = heap.size() - 1;
        while (i > 0 && heap[i] > heap[parent(i)]) {
            std::swap(heap[i], heap[parent(i)]);
            i = parent(i);
        }
    }

    int extractMax() {
        if (heap.empty()) {
            throw std::out_of_range("Heap is empty.");
        }
        int max = heap[0];
        heap[0] = heap.back();
        heap.pop_back();
        maxHeapify(0);
        return max;
    }

private:
    int parent(int i) {
        return (i - 1) / 2;
    }

    int leftChild(int i) {
        return 2 * i + 1;
    }

    int rightChild(int i) {
        return 2 * i + 2;
    }

    void maxHeapify(int i) {
        int largest = i;
        int l = leftChild(i);
        int r = rightChild(i);
        if (l < heap.size() && heap[l] > heap[largest]) {
            largest = l;
        }
        if (r < heap.size() && heap[r] > heap[largest]) {
            largest = r;
        }
        if (largest != i) {
            std::swap(heap[i], heap[largest]);
            maxHeapify(largest);
        }
    }
};

通过上述代码,我们可以将顾客的信息按照优先级插入到二叉堆中,并使用extractMax()方法从堆中取出优先级最高的顾客。这样,我们就可以按照优先级高低为顾客安排就餐。

【4.2 斐波那契堆】

斐波那契堆是一种基于多叉树的堆结构,相比于二叉堆,它能够在某些操作上表现出更好的性能。斐波那契堆的特点是节点具有多个子节点,而且可以灵活地调整堆的结构。

斐波那契堆由一系列的树组成,每个树都满足最小堆的性质,即每个根节点的值都小于等于其子节点的值。同时,斐波那契堆还具有一些特殊的性质,例如每个节点的度数(子节点数量)不同,节点之间通过双向链表进行连接等。

斐波那契堆的伪代码实现比较复杂,为了简化讲解,这里不提供具体代码。

【5. 堆排序算法:美食飘香】

除了用于优先队列,堆还可以用来进行排序,这就是堆排序算法。堆排序算法利用堆的特性,在时间复杂度为 O(nlogn) 的情况下对数据进行排序。

堆排序的思想很简单:首先将待排序的数据构建成一个堆,然后反复将堆顶元素与堆的最后一个元素交换,并调整堆使其保持堆的性质,重复这个过程直到整个堆排序完成。

【6. 堆在优先队列中的应用】

堆在优先队列中有着广泛的应用。优先队列是一种特殊的队列,其中的元素按照优先级进行排序。堆作为实现优先队列的数据结构,能够高效地处理插入和删除操作,使得优先队列的操作更加快速和灵活。

优先队列在实际生活中有许多应用,比如任务调度、事件管理等。举个例子,假设你是一家快递公司的调度员,你需要根据快递包裹的优先级来决定送货的顺序。通过使用堆作为优先队列,你可以轻松地处理各种快递包裹的调度,让优先级高的包裹优先送达,提高了送货的效率和顾客的满意度。

【7. 代码实现:饮食宝典】

为了更好地理解堆的应用,让我们来实现一个简单的案例——饮食宝典。这个案例将使用C++代码,以堆为基础构建一个能够根据食物热量进行排序的饮食推荐系统。

在这个案例中,我们可以使用公开的食物热量数据源,例如食物营养数据库。首先,我们需要定义一个数据结构来表示食物,包括名称和热量。然后,我们将这些食物数据存储在堆中,根据热量的大小进行排序。

下面是示例的C++代码:

#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>

// 定义食物结构体
struct Food {
    std::string name;
    int calories;
};

// 定义堆中的比较函数,根据热量进行比较
struct CompareFood {
    bool operator()(
      bool operator()(const Food& food1, const Food& food2) {
        return food1.calories < food2.calories;
    }
};

int main() {
    // 创建一个最小堆,用于存储食物数据
    std::priority_queue<Food, std::vector<Food>, CompareFood> foodHeap;

    // 添加食物数据到堆中
    foodHeap.push({"苹果", 52});
    foodHeap.push({"香蕉", 96});
    foodHeap.push({"草莓", 32});
    foodHeap.push({"葡萄", 69});
    foodHeap.push({"橙子", 43});

    // 从堆中取出食物数据并打印
    while (!foodHeap.empty()) {
        Food food = foodHeap.top();
        foodHeap.pop();
        std::cout << "食物名称:" << food.name << ",热量:" << food.calories << "千卡" << std::endl;
    }

    return 0;
}

在这个代码示例中,我们定义了一个最小堆foodHeap,使用自定义的比较函数CompareFood来根据食物的热量进行排序。然后,我们将一些食物数据添加到堆中,并通过不断从堆中取出食物数据来进行打印。由于最小堆的特性,每次取出的食物都是热量最低的食物,这样就可以根据热量进行排序和推荐了。

这个简单的案例展示了堆的实际应用,通过堆的特性,我们可以轻松实现根据热量进行排序的饮食推荐系统。

【8. 总结与展望】

通过本文的介绍,我们学习了堆的特点、堆的实现方式(二叉堆和斐波那契堆)、堆排序算法以及堆在优先队列中的应用。堆作为一种高效的数据结构,可以帮助我们解决许多实际问题,提高算法的效率和性能。

希望通过本文的讲解,你对堆有了更深入的了解。当然,堆还有许多其他的应用和进阶知识,比如堆的合并操作、可并堆等,可以进一步探索和学习。如果你对堆感兴趣,不妨深入学习相关的算法和数据结构,为自己的编程技能增添一把利器。

最后,感谢大家的阅读,希望本文能够通俗易懂、幽默诙谐地介绍了堆的相关知识,并通过案例和代码演示帮助大家更好地理解和应用堆。记得在享受美食的同时,也要关注自己的饮食健康哦!

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码