堆基本操作

堆分为大堆和小堆,堆本质上是一个完全二叉树,这里将堆里的元素存在一个数组中,大堆是根结点都大于左右孩子,小堆是根结点都小于左右孩子。
堆的基本操作包括:(以大堆为例)
初始化堆,创建堆,向上调整,向下调整,堆排序。
代码如下:
Heap.h中代码如下:

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int HeapDatatype;
typedef struct Heap
{
    HeapDatatype *arry;
    int capacity;
    int size;
}Heap;
void HeapInit(Heap* hp, HeapDatatype* a, int n);//堆的初始化
void HeapPrint(Heap *hp);//打印堆
void HeapMake(Heap* hp);//大堆的创建
void HeapAdjustUp(Heap*hp, int child);//向上调整
void HeapAdjustDown(Heap*hp, int parent);//向下调整
void HeapPush(Heap *hp, HeapDatatype data);//向堆里插入数据
void HeapPop(Heap *hp);//堆pop

Heap.c

#include"Heap.h"
void HeapInit(Heap* hp, HeapDatatype* a, int n)//堆的创建
{
    assert(a&&hp);
    hp->capacity = n;
    hp->size = n;
    hp->arry = (HeapDatatype*)malloc(sizeof(HeapDatatype)*hp->capacity);
    int i = 0;
    for (i = 0; i < hp->size; i++)
        hp->arry[i] = a[i];
}
void HeapPrint(Heap *hp)//打印堆
{
    int i = 0;
    for (i = 0; i < hp->size; i++)
        printf("%d ", hp->arry[i]);
    printf("\n");
}
int HeapEmpty(Heap* hp)
{
    if (hp->size == 0)
        return 0;
    return 1;
}
int HeapSize(Heap* hp)
{
    return hp->size;
}

void Swap(HeapDatatype *a1, HeapDatatype*a2)
{
    HeapDatatype a = *a1;
    *a1 = *a2;
    *a2 = a;
}
void HeapPop(Heap *hp)//堆pop
{   //堆pop指pop的堆顶元素,将堆顶元素和最后一个数进行交换,size--
    assert(hp);
    Swap(&hp->arry[0], &hp->arry[hp->size - 1]);
    hp->size--;
    HeapAdjustDown(hp, 0);//向下调整
}
void HeapSort(Heap *hp)//堆排序,大堆
{
    //堆排序是将堆顶元素和最后一个交换,打印最后一个元素,
    //并且hp->size--,再调整为大堆,循环前面操作
    int n = hp->size;
    assert(hp);
    while (hp->size > 0)
    {
        Swap(&hp->arry[0], &hp->arry[hp->size - 1]);
        hp->size--;
        BigHeapAdjustDown(hp, 0);//向下调整
    }
    hp->size = n;//如果不重新赋值,则hp->size=0
}
void HeapPush(Heap *hp, HeapDatatype data)//向堆里插入数据
{
    if (hp->size == hp->capacity)//扩容
    {
        hp->arry = (HeapDatatype*)realloc(hp->arry, sizeof(HeapDatatype)*(hp->capacity) * 2);
        /*assert(hp->arry);*/
        hp->capacity *= 2;
    }
    hp->arry[hp->size] = data;
    hp->size++;
    HeapAdjustUp(hp, hp->size - 1);//向上调整
}

void HeapAdjustUp(Heap*hp, int child)//向上调整
{   //调整只会与孩子的祖先有关
    int parent = (child - 1) / 2;
    while (child > 0)
    {
        if (hp->arry[parent] < hp->arry[child])
        {
            Swap(&hp->arry[parent], &hp->arry[child]);
            child = parent;
            parent = (child - 1) / 2;
        }
        else  //如果父亲比孩子大,就没必要调整
            break;
    }
}
void HeapAdjustDown(Heap*hp, int parent)//向下调整
{
    int child = parent * 2 + 1;
    while (parent < hp->size)
    {    //如果左孩子小于右孩子,将child等于右孩子,即child存左右孩子较大坐标
        if (child + 1 < hp->size && hp->arry[child] < hp->arry[child + 1])
            child = child + 1;
        if (child < hp->size &&hp->arry[parent] < hp->arry[child])//根小于孩子
        {
            Swap(&hp->arry[parent], &hp->arry[child]);
            // 调整之后需要以child为跟再调整一次,因为调整后可能导致根小于左右孩子
            parent = child;
            child = parent * 2 + 1;
        }
        else  //说明根大于左右孩子或者child大于hp->size,退出循环
            break;
    }
}

void HeapMake(Heap* hp)//大堆的创建
{
    int i = 0;//从大堆最后一个非叶子结点开始
    for (i = (hp->size - 1 - 1) / 2; i >= 0; i--)
    {
        HeapAdjustDown(hp, i);
    }
}
int main()
{
    Heap hp;
    HeapDatatype a[] = { 10,16,18,12,11,22,15,17,14,19 };
    int sz = sizeof(a) / sizeof(HeapDatatype);
    HeapInit(&hp, a, sz);//堆的初始化
    HeapPrint(&hp);//堆的打印
    HeapMake(&hp);//大堆的创建
    HeapPrint(&hp);//堆的打印
    HeapPush(&hp, 21);//向堆里插入数据
    HeapPrint(&hp);//堆的打印
    HeapPop(&hp);//堆pop
    HeapPrint(&hp);//堆的打印
    HeapSort(&hp);//堆排序  
    system("pause");
    return 0;
}

测试用例:
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值