数据结构之堆的基本操作

本文介绍了堆数据结构的基础知识,包括堆的性质、初始化、销毁、比较函数、插入、删除、从数组创建堆、获取堆顶元素以及堆排序的实现。通过具体的代码示例展示了如何操作和调整堆,以及如何利用堆进行排序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说的堆,我们就知道有两种堆的方式
这里写图片描述
小堆(大堆)中:任意一个关键码均小于(大于)等于它的左右孩子的关键码,位于堆顶节点的关键码最小(最大),从根节点到每个节点的路径上手族元素组成的序列都是递增(递减)的

堆存储在下标为0开始的数组中,因此在堆中给定下标为i的节点时

如果i=0,节点i是根节点,没有双亲节点;否则节点i的双亲节点为(i-1)/2
如果2*i+1 <= n-1,则节点i的做孩子为节点2*i +1,否则节点i无左孩子
如果2*i +2 <= n-1,则节点i的右孩子为节点2*i +2,否则节点i无右孩子

heap.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

#define HEAPMAXSIZE 1000
typedef char heaptype;
typedef int(*Compare)(heaptype a,heaptype b);
typedef struct heap{
    heaptype data[HEAPMAXSIZE];
    size_t size;
    Compare cmp;
}heap;
void heapinit(heap *hp,Compare cmp);
void heapdestroy(heap *hp);
void heapinsert(heap *hp,heaptype value);
void heapcreat(heap *hp,heaptype arr[],size_t size);
int heapgettop(heap *hp,heaptype *root);
void heaperase(heap *hp);
void heapsort(heap *hp,heaptype arr[],size_t size);

堆的初始化与销毁

具体代码实现

void heapinit(heap *hp,Compare cmp)
{
    if(hp == NULL)
    {
        return;
    }
    hp->cmp = cmp;
    hp->size = 0;
    return;
}
void heapdestroy(heap *hp)
{
    if(hp == NULL)
    {
        return;
    }
    hp->cmp = NULL;
    hp->size = 0;
    return;
}

比较函数

void swap(heaptype *a,heaptype *b)
{
    heaptype t = *a;
    *a = *b;
    *b = t;

}

堆的插入

在已经建成的最小或最大堆后面插入新元素,插入之后,当树中节点不满足堆的性质时,就需要对堆进行重新调整。
我们对这个数组进行尾插,然后我们进行上浮式比较,然后使它满足堆的性质
下面是代码具体实现

void heapinsert(heap *hp,heaptype value)
{
    if(hp == NULL)
    {
        return;
    }
    if(hp->size >= HEAPMAXSIZE)
    {
        return;
    }
    hp->data[hp->size++] = value;
    //adjustup(hp,hp->size -1);
    size_t child = hp->size-1;
    size_t parent = (child-1)/2;
    while(child > 0)
    {
        if(hp->cmp(hp->data[child],hp->data[parent]))
        {
            swap(&hp->data[child],&hp->data[parent]);
            child = parent;//上浮,将交换后的节点继续与它此时的根节点比较交换;
            parent = (child-1)/2;
        }
        else
        {
            break;
        }
    }
    return;

}

堆的删除

当我们要删除堆顶元素的时候,我们采取这样的思路
1.每次将堆中的最后一个元素代替堆顶元素
2.将堆中元素减少一个,也就是删除最后一个元素,意思就是将堆中有效size减一,但是它的size总体大小是不变的
3.此时堆结构可能被破坏,于是我们需要采用下沉式调整,将堆保持它的性质

void adjustdown(heap *hp)
{
    size_t parent = 0;
    size_t child = parent*2 +1;
    while(child > 0 && child + 1 < hp->size && parent >= 0 && parent < hp->size)
    {
        if(!hp->cmp(hp->data[child],hp->data[child+1]))
        {
            child = child+1;
        }
        if(!hp->cmp(hp->data[parent],hp->data[child]))
        {
            swap(&hp->data[parent],&hp->data[child]);
            parent = child;
            child = parent*2 +1;
        }
        else
        {
            break;
        }
    }
    return;
}
void heaperase(heap *hp)
{
    if(hp == NULL)
    {
        return;
    }
    if(hp->size == 0)
    {
        return;
    }
    swap(&hp->data[0],&hp->data[hp->size-1]);
    hp->size--;
    adjustdown(hp);
}

根据一个数组创建一个堆

void heapcreat(heap *hp,heaptype arr[],size_t size)
{
    if(hp == NULL || arr == NULL || size == 0)
    {
        return;
    }
    size_t i = 0;
    for(;i<size;i++)
    {
        heapinsert(hp,arr[i]);
    }
    return;
}

取堆顶元素

int heapgettop(heap *hp,heaptype *root)
{
    if(hp == NULL)
    {
        return 0;
    }
    if(hp->size == 0)
    {
        return 0;
    }
    *root = hp->data[0];
    return 1;
}

堆的排序

给一个数组,用数组里面的元素创建一个堆,然后我们依次删除堆里面的元素,然后此时堆内这个数组就是排好顺序的数组,将这个数组依次赋值给,参数给的数组,就完成了堆的排序

void heapsort(heap *hp,heaptype arr[],size_t size)
{
    if(hp == NULL)
    {
        return;
    }
    heapcreat(hp,arr,size);
    size_t i = 0;
    for(;i < size;i++)
    {
        heaperase(hp);
    }
    for(i = 0;i < size;i++)
    {
        arr[i] = hp->data[i];
    }
}

下面是测试代码和测试结果

#define HEADER printf("\n=============%s=============\n",__FUNCTION__)
void testinsert()
{
    HEADER;
    heap hp;
    heapinit(&hp,less);
    heapinsert(&hp,'g');
    heapinsert(&hp,'f');
    heapinsert(&hp,'d');
    heapinsert(&hp,'e');
    heapinsert(&hp,'a');
    heapinsert(&hp,'c');
    heapinsert(&hp,'b');
    print(&hp);

}
void testcreat()
{
    HEADER;
    heap hp;
    heapinit(&hp,less);
    char arr[10] = "abcdefg";
    size_t size = strlen(arr);
    heapcreat(&hp,arr,size);
    print(&hp);

}
void testgettop()
{
    HEADER;
    heap hp;
    heapinit(&hp,less);
    heapinsert(&hp,'g');
    heapinsert(&hp,'f');
    heapinsert(&hp,'d');
    heapinsert(&hp,'e');
    heapinsert(&hp,'a');
    heapinsert(&hp,'c');
    heapinsert(&hp,'b');
    print(&hp);
    heaptype top;
    int ret = heapgettop(&hp,&top);
    printf("expected ret is 1,actul is %d\n",ret);
    printf("expected top is a,actul is %c\n",top);
}
void testerase()
{
    HEADER;
    heap hp;
    heapinit(&hp,less);
    heapinsert(&hp,'g');
    heapinsert(&hp,'f');
    heapinsert(&hp,'d');
    heapinsert(&hp,'e');
    heapinsert(&hp,'a');
    heapinsert(&hp,'c');
    heapinsert(&hp,'b');
    print(&hp);
    heaperase(&hp);
    print(&hp);
    //heaptype top;
    //int ret = heapgettop(&hp,&top);
    //printf("expected ret is 1,actul is %d\n",ret);
    //printf("expected top is b,actul is %c\n",top);

}
void testsort()
{
    HEADER;
    heap hp;
    heapinit(&hp,less);
    char arr[10] = "abcdefg";
    size_t size = strlen(arr);
    heapsort(&hp,arr,size);
    printf("\n");
    size_t i = 0;
    for(;i < size;i++)
    {
        printf("%c",arr[i]);
    }
    printf("\n");

}
int main()
{
    testinsert();
    testcreat();
    testgettop();
    testerase();
    testsort();
    return 0;
}

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值