数据结构----堆(C语言实现版本)

一.堆概念讲解

堆总是一颗完全二叉树(树,会在接下来的文章里讲解):这就导致了堆用顺序表更加好表示。

堆可以分为大堆与小堆。(与顺序表(可以看前几篇文章)相比,新加的两个算法是一个向上调整,与向下调整,除此之外并无其他。)

接下来是一个小堆的实现,堆的搭建是一个难点,这篇文章先不讲解,之间给push出一个堆。

二.代码实现部分
heap.h 头文件
#pragma once
​
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
​
typedef int HPDataType;
typedef struct Heap
{
    HPDataType* _a;
    int _size;
    int _capacity;
​
}Heap;
​
// 堆的构建
void HeapInit(Heap* hp);
​
// 堆的销毁
void HeapDestory(Heap* hp);
​
// 堆的插入
void HeapPush(Heap* hp, HPDataType x);
​
// 堆的删除
void HeapPop(Heap* hp);
​
// 取堆顶的数据
HPDataType HeapTop(Heap* hp);
​
// 堆的数据个数
int HeapSize(Heap* hp);
​
// 堆的判空
bool HeapEmpty(Heap* hp);

heap.c 实现文件
#include"heap.h"
​
// 堆的构建
void HeapInit(Heap* hp)
{
    assert(hp);
​
    hp->_a = NULL;
    hp->_capacity = 0;
    hp->_size = 0;
​
}
​
// 堆的销毁
void HeapDestory(Heap* hp)
{
    assert(hp);
    free(hp->_a);
​
    hp->_a = NULL;
    hp->_capacity = hp->_size = 0;
​
}
​
void Swap(HPDataType* x,HPDataType* y)
{
    HPDataType tmp = *x;
    *x = *y;
    *y = tmp;
}
​
//向上调整
void AdjustUp(Heap* hp,int child)
{
    int parent = (child -1) / 2;
    
​
    while (hp->_a[parent] > hp->_a[child])
    {
        Swap(&hp->_a[parent], &hp->_a[child]);
        child = parent;
        parent = (child - 1) / 2;
    }
​
}
​
// 堆的插入
void HeapPush(Heap* hp, HPDataType x)
{
    assert(hp);
    if (hp->_capacity == hp->_size)
    {
        int newCapacity = hp->_capacity == 0 ? 4:hp->_capacity * 2;
        HPDataType* tmp = (HPDataType*)realloc(hp->_a, sizeof(HPDataType) * newCapacity);
        if (tmp == NULL)
        {
            printf("realloc failed");
            exit(-1);
        }
​
        hp->_a = tmp;
        hp->_capacity = newCapacity;
        
    }
    
    hp->_a[hp->_size] = x;
    hp->_size++;
    
    AdjustUp(hp,hp->_size-1);
​
}
​
​
//向下调整
void AdjustDown(Heap*hp,int parent)
{
    int child = parent * 2 + 1;
​
    while ( child < hp->_size)
    {
        if (child + 1< hp->_size && hp->_a[child + 1] <hp->_a[child])
        {
            child++;
        }
    
        if (hp->_a[child] < hp->_a[parent])
        {
            Swap(&hp->_a[child], &hp->_a[parent]);
            parent = child;
            child = parent * 2 + 1;
        }
        else
        {
            break;
        }
    }
​
}
​
// 堆的删除
void HeapPop(Heap* hp)
{
    assert(hp);
    assert(hp->_size > 0);
​
    Swap(&hp->_a[hp->_size - 1],&hp->_a[0]);
    hp->_size--;
    
    AdjustDown(hp, 0);
​
}
​
// 取堆顶的数据
HPDataType HeapTop(Heap* hp)
{
    assert(hp);
    assert(hp->_size > 0);
​
    return hp->_a[0];
​
}
​
​
// 堆的数据个数
int HeapSize(Heap* hp)
{
    assert(hp);
​
    return hp->_size;
​
}
​
// 堆的判空
bool HeapEmpty(Heap* hp)
{
    assert(hp);
​
    return hp->_size == 0;
​
}

test.c 文件
#include<stdio.h>
#include"heap.h"
​
int main()
{
    int a[] = { 4,6,2,1,5,8,2,9};
    Heap hp;
    HeapInit(&hp);
​
    for (int i = 0; i < sizeof(a) / sizeof(int); ++i)
    {
        HeapPush(&hp, a[i]);
    }
    
    for (int i = 0; i < hp._size; ++i)
    {
        printf("%d ",hp._a[i]);
    }
    
    printf("\n");
    
    int k = 3;
    while (k--)
    {
        printf("%d\n", HeapTop(&hp));
        HeapPop(&hp);
    }
    
    while (!HeapEmpty(&hp))
    {
        printf("%d ", HeapTop(&hp));
        HeapPop(&hp);
    }
    
    printf("\n");
    
    HeapDestory(&hp);
    
    return 0;
​
}
三.算法的讲解(以 test.c 里面的例子举例) ,建立小堆

AdjustUp( ) //像上调整算法

AdjustDown( ) //向下调整算法

            图有点丑,希望能帮助大家理解,下一篇文章会是二叉树的,以及堆的构建。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值