简单用c语言中数组实现堆

一、堆的实现(数组版本)

1、简单概述

堆分为大堆、小堆,很显然堆是二叉树中的完全二叉树,一般来说既然是二叉树不应该用链表实现吗?其实数组也可以用来实现堆,数组的0号位置对应根,1号和2号当0号的左右儿子,3号4号当1号的左右儿子,5号6号当2号的左右儿子,以此类推一个逻辑上的树就出来了。

2、数组实现小堆

小堆什么是小堆呢?很简单就是父节点要小于等于儿子节点,大堆反之父节点要大于儿子节点,具体实现很简单,底层用顺序表然后使数组满足小堆的规律即可。

2.1实现

我们要建立一个(1)头文件.h存放堆声明函数,结构体,再建立一个堆的 (2).c文件来具体实现.h函数声明。,最后还需要一个(3)test.c文件用于测试实现的堆函数,总共要建三个文件。

具体实现如下:
.h文件内容

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

typedef int hdtp;
typedef struct heap{
    hdtp* a;
    int cap;
    int size;
}hp;

void hpInit(hp* p);
void hpDestory(hp* p);
void hpPush(hp* p,hdtp x);
void Print(hp* p);
void hpPop(hp* p);
void hptop(hp* p);

.c函数实现文件如下

#include"heap.h"

void hpInit(hp* p){
    assert(p);
    p->a=NULL;
    p->cap=p->size=0;
}

void hpDestory(hp *p){
    assert(p);
    assert(p->a);
    free(p->a);
    p->a=NULL;
    p->cap=p->size=0;
}

void Swap(hdtp* p1,hdtp* p2){
    hdtp tmp;
    tmp=*p1;
    *p1=*p2;
    *p2=tmp;
}

void hpPush(hp *p, hdtp x){
    assert(p);
    //开空间
    if(p->size==p->cap){
        int newcap=p->cap==0?4:p->cap*2;
        hdtp* tmp=realloc(p->a,sizeof(hdtp)*newcap);
        if(tmp==NULL){
            perror("malloc failed\n");
            return;
        }
        p->a=tmp;
        p->cap=newcap;
    }
    
    p->a[p->size++]=x;
    //向上调整
    int child=p->size-1;
    int parent=(child-1)/2;
    while(child!=0){
        if(p->a[child]<p->a[parent]){
            Swap(&p->a[child],&p->a[parent]);
            child=parent;
            parent=(parent-1)/2;
        }
        else {
            break;
        }
    }
    
}

void Print(hp* p){
    assert(p);
    for(int i=0;i<p->size;i++){
        printf("%d ",p->a[i]);
    }
    printf("\n");
}

void hpPop(hp *p){
    assert(p);
    assert(p->size);
    //堆顶交换
    Swap(&p->a[0],&p->a[p->size-1]);
    p->size--;
    //向下调整
    int parent=0;
    int child=parent*2+1;
    while(child<p->size){
        if((child+1<p->size)&&(p->a[child]>p->a[child+1])){
            child++;
        }
        if(p->a[child]<p->a[parent]){
        Swap(&p->a[child],&p->a[parent]);
        parent=child;
        child=child*2+1;
        }
        else{
            break;
        }
    }
}

void hptop(hp* p){
    assert(p);
    assert(p->size);
    printf("%d \n",p->a[0]);

}

test.c测试文件如下

#include"heap.h"
int main(){
    hp t;
    hpInit(&t);
    int a[]={4,6,2,1,5,2,8,9};
    for(int i=0;i<sizeof(a)/sizeof(hdtp);i++){
         hpPush(&t,a[i]);
    }
   // hpPop(&t);
    Print(&t);
    printf("\n");
    for(int i=0;i<sizeof(a)/sizeof(hdtp);i++){
       // hpPop(&t);
        hptop(&t);
        hpPop(&t);
    }
    return 0;
}
3、简单思路概述

这里堆的实现比较简单具体实现的思路都在内容中,(1)思路中一定要确定孩子节点跟父节点运算关系,(2)注意的是删除节点时是删除根节点并不是删除最末叶子节点,删除后需要重新调整成堆,(3)增加节点也一样,需要增加完后调整成堆。

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值