【数据结构】堆

在C语言中,堆(Heap)是一个非常重要的数据结构,它主要用于实现优先队列。堆可以被看作是一棵完全二叉树,其中每个父节点的值都大于或等于(最大堆)或小于或等于(最小堆)其子节点的值。这里,我们将主要讨论最大堆的实现和基本原理。

堆的基本操作

堆的主要操作包括:

  1. 插入(Push/Heapify Up):将一个新的元素插入到堆中,并保持堆的性质。
  2. 删除最大元素(Pop/Heapify Down):删除堆顶元素(最大元素),并将堆的最后一个元素移到堆顶,然后重新调整堆以恢复其性质。

堆的存储

堆通常使用数组来存储,因为数组可以通过索引快速访问父节点和子节点。对于一个索引为 i 的节点,其父节点的索引是 (i-1)/2,左子节点的索引是 2*i+1,右子节点的索引是 2*i+2

示例代码

以下是一个简单的最大堆实现示例,包括堆的插入和删除操作:

#include <stdio.h>
#include <stdlib.h>

#define MAX_SIZE 100

void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

void heapifyUp(int arr[], int n, int i) {
    while (i > 0 && arr[parent(i)] < arr[i]) {
        swap(&arr[parent(i)], &arr[i]);
        i = parent(i);
    }
}

void heapifyDown(int arr[], int n, int i) {
    int largest = i;
    int left = 2 * i + 1;
    int right = 2 * i + 2;

    if (left < n && arr[left] > arr[largest])
        largest = left;
    if (right < n && arr[right] > arr[largest])
        largest = right;
    if (largest != i) {
        swap(&arr[i], &arr[largest]);
        heapifyDown(arr, n, largest);
    }
}

void insert(int arr[], int *n, int element) {
    if (*n >= MAX_SIZE)
        return;
    arr[*n] = element;
    (*n)++;
    heapifyUp(arr, *n, *n - 1);
}

int deleteMax(int arr[], int *n) {
    if (*n <= 0)
        return INT_MIN; // 假设最小可能值是INT_MIN
    int popped = arr[0];
    arr[0] = arr[*n - 1];
    (*n)--;
    heapifyDown(arr, *n, 0);
    return popped;
}

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

int main() {
    int heap[MAX_SIZE] = {0};
    int n = 0;

    insert(heap, &n, 15);
    insert(heap, &n, 10);
    insert(heap, &n, 20);
    insert(heap, &n, 8);
    insert(heap, &n, 12);

    printf("Max element is %d\n", deleteMax(heap, &n));
    printf("Max element is %d\n", deleteMax(heap, &n));

    return 0;
}

注意事项

  • 堆的实现非常依赖于数组索引与树节点之间的关系。
  • 堆的插入和删除操作都是对数时间复杂度(O(log n)),这使得堆在需要频繁访问最大或最小元素的场景中非常有用。
  • 在实际应用中,堆常用于实现堆排序算法,以及作为优先级队列的基础数据结构。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值