一、堆的实现(数组版本)
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)增加节点也一样,需要增加完后调整成堆。