对二叉堆的简单分析,c和c++的简单实现

简介: 这篇文章提供了对二叉堆数据结构的简单分析,并展示了如何在C和C++中实现最小堆,包括初始化、插入元素、删除最小元素和打印堆的函数,以及一个示例程序来演示这些操作。
   上文:[Redis的实现五:二叉堆的数据结构和TTL、c,c++的实现-CSDN博客](https://blog.csdn.net/m0_63251896/article/details/135691889?spm=1001.2014.3001.5501 "Redis的实现五:二叉堆的数据结构和TTL、c,c++的实现-CSDN博客")

   **概述**:二叉堆是一种基于完全二叉树结构的数据结构,常被用作优先队列的实现方式。它有两种类型:最大堆和最小堆,分别用于支持在堆中的元素中找到最大值或最小值。

以下是二叉堆的一些简单分析:

  1. 结构特点:

    • 二叉堆是一颗完全二叉树,这意味着除了最后一层,其他层都是完全填充的,而且最后一层的节点都尽量靠左排列。
    • 在最大堆中,每个节点的值都大于或等于其子节点的值;在最小堆中,每个节点的值都小于或等于其子节点的值。
  2. 数组表示:

    • 二叉堆可以使用数组来表示。对于给定索引 i,其左子节点的索引为 2i+1,右子节点的索引为 2i+2,父节点的索引为 (i-1)/2
    • 这种数组表示使得堆的访问和修改操作更加高效。
  3. 堆的操作:

    • 插入:将新元素添加到堆的末尾,然后通过一系列交换操作,使得堆的性质得以保持。
    • 删除:删除堆顶元素后,将堆的最后一个元素移到堆顶,然后通过一系列交换操作,使得堆的性质得以保持。
    • 堆化:通过自上而下的或自下而上的方式,确保堆的性质得以保持。
  4. 时间复杂度:

    • 插入和删除操作的时间复杂度为O(log n),其中n是堆中元素的个数。
    • 构建堆的时间复杂度为O(n),其中n是堆中元素的个数。
  5. 应用:

    • 优先队列:由于能够快速找到最大值或最小值,二叉堆常被用作优先队列的基础数据结构。
    • 堆排序:利用最大堆或最小堆实现的堆排序算法是一种高效的排序算法。

总体而言,二叉堆是一种简单而强大的数据结构,通过有效地维护元素的顺序,它支持高效的插入、删除和查找最值等操作。

完整代码:

#include <stdio.h>

#define MAX_HEAP_SIZE 100

// 定义最小堆结构
struct MinHeap {
    int arr[MAX_HEAP_SIZE];
    int size;
};

// 函数声明
void initHeap(struct MinHeap* heap);
void insertElement(struct MinHeap* heap, int value);
void deleteMin(struct MinHeap* heap);
void printHeap(struct MinHeap* heap);

int main() {
    struct MinHeap heap;
    initHeap(&heap);

    // 添加元素
    insertElement(&heap, 5);
    insertElement(&heap, 3);
    insertElement(&heap, 8);
    insertElement(&heap, 1);

    // 打印堆
    printf("堆的元素:");
    printHeap(&heap);

    // 删除最小元素
    deleteMin(&heap);

    // 打印堆
    printf("删除最小元素后的堆:");
    printHeap(&heap);

    return 0;
}

// 初始化堆
void initHeap(struct MinHeap* heap) {
    heap->size = 0;
}

// 向堆中插入元素
void insertElement(struct MinHeap* heap, int value) {
    if (heap->size == MAX_HEAP_SIZE) {
        printf("堆已满\n");
        return;
    }

    // 将新元素添加到末尾
    heap->arr[heap->size] = value;
    heap->size++;

    // 上移操作,维护堆的性质
    int currentIndex = heap->size - 1;
    while (currentIndex > 0) {
        int parentIndex = (currentIndex - 1) / 2;
        if (heap->arr[currentIndex] < heap->arr[parentIndex]) {
            // 交换元素,保持堆的性质
            int temp = heap->arr[currentIndex];
            heap->arr[currentIndex] = heap->arr[parentIndex];
            heap->arr[parentIndex] = temp;
        } else {
            break; // 堆的性质已满足
        }
        currentIndex = parentIndex;
    }
}

// 删除堆中的最小元素
void deleteMin(struct MinHeap* heap) {
    if (heap->size == 0) {
        printf("堆为空\n");
        return;
    }

    // 将最后一个元素替换到根节点
    heap->size--;
    heap->arr[0] = heap->arr[heap->size];

    // 下移操作,维护堆的性质
    int currentIndex = 0;
    while (1) {
        int leftChild = 2 * currentIndex + 1;
        int rightChild = 2 * currentIndex + 2;
        int minIndex = currentIndex;

        if (leftChild < heap->size && heap->arr[leftChild] < heap->arr[minIndex]) {
            minIndex = leftChild;
        }
        if (rightChild < heap->size && heap->arr[rightChild] < heap->arr[minIndex]) {
            minIndex = rightChild;
        }

        if (minIndex != currentIndex) {
            // 交换元素,保持堆的性质
            int temp = heap->arr[currentIndex];
            heap->arr[currentIndex] = heap->arr[minIndex];
            heap->arr[minIndex] = temp;
            currentIndex = minIndex;
        } else {
            break; // 堆的性质已满足
        }
    }
}

// 打印堆的元素
void printHeap(struct MinHeap* heap) {
    for (int i = 0; i < heap->size; i++) {
        printf(" %d", heap->arr[i]);
    }
    printf("\n");
}
   这段代码实现了一个最小堆数据结构,并提供了初始化堆、插入元素、删除最小元素和打印堆的功能。下面是对代码的解析:
  1. 定义了一个名为MinHeap的结构体,包含一个整型数组arr和一个整型变量size,用于存储堆的元素和当前堆的大小。

  2. 函数声明部分包括了四个函数:initHeapinsertElementdeleteMinprintHeap。这些函数分别用于初始化堆、向堆中插入元素、删除最小元素和打印堆的元素。

  3. main函数是程序的入口点。首先创建了一个MinHeap类型的变量heap,然后调用initHeap函数进行初始化。

  4. 接下来,通过循环调用insertElement函数向堆中插入了四个元素:5、3、8和1。

  5. 然后,调用printHeap函数打印堆的元素,输出结果为:5 3 8 1。

  6. 接着,调用deleteMin函数删除堆中的最小元素,即删除元素1。

  7. 最后,再次调用printHeap函数打印堆的元素,输出结果为:5 3 8。

    总结起来,这段代码实现了一个简单的最小堆数据结构,并演示了如何向堆中插入元素、删除最小元素以及打印堆的元素。
目录
相关文章
|
5月前
|
算法 安全 编译器
【C++ 泛型编程 进阶篇】C++模板参数推导的场景分析
【C++ 泛型编程 进阶篇】C++模板参数推导的场景分析
86 0
【C++ 泛型编程 进阶篇】C++模板参数推导的场景分析
|
5月前
|
存储 Java 编译器
java和c++的主要区别、各自的优缺点分析、java跨平台的原理的深度解析
java和c++的主要区别、各自的优缺点分析、java跨平台的原理的深度解析
566 0
|
16天前
|
程序员 编译器 C++
【C++核心】C++内存分区模型分析
这篇文章详细解释了C++程序执行时内存的四个区域:代码区、全局区、栈区和堆区,以及如何在这些区域中分配和释放内存。
38 2
|
4月前
|
存储 程序员 编译器
C/C++堆栈详细分析,新老程序员必会
C/C++堆栈详细分析,新老程序员必会
120 1
|
4月前
|
存储 自然语言处理 安全
C++ STL标准库 《string原理与实战分析》
C++ STL标准库 《string原理与实战分析》
70 0
|
1天前
|
NoSQL Redis C++
Redis的实现五:二叉堆的数据结构和TTL、c,c++的实现
这篇文章详细探讨了二叉堆的数据结构及其在C和C++中的实现,特别强调了二叉堆在Redis中实现TTL(生存时间)功能的重要性,并通过代码示例展示了如何在Redis中使用二叉堆来管理键的过期时间。
6 0
|
1月前
|
Ubuntu Linux Shell
C++ 之 perf+火焰图分析与调试
简介 在遇到一些内存异常的时候,经常这部分的代码是很难去进行分析的,最近了解到Perf这个神器,这里也展开介绍一下如何使用Perf以及如何去画火焰图。 1. Perf 基础 1.1 Perf 简介 perf是Linux下的一款性能分析工具,能够进行函数级与指令级的热点查找。利用perf剖析程序性能时,需要指定当前测试的性能时间。性能事件是指在处理器或操作系统中发生的,可能影响到程序性能的硬件事件或软件事件 1.2 Perf的安装 ubuntu 18.04: sudo apt install linux-tools-common linux-tools-4.15.0-106-gen
24 2
|
5月前
|
算法 安全 大数据
【C/C++ 随机函数行为】深入探索C++中的随机数:std::random_device与rand的行为分析(二)
【C/C++ 随机函数行为】深入探索C++中的随机数:std::random_device与rand的行为分析
158 0
|
4月前
|
自然语言处理 C语言 C++
程序与技术分享:C++写一个简单的解析器(分析C语言)
程序与技术分享:C++写一个简单的解析器(分析C语言)
|
4月前
|
大数据 C++ 索引
C++ STL标准库 《vector向量原理与实战分析》
C++ STL标准库 《vector向量原理与实战分析》
45 0