二叉堆

一、定义
1、二叉堆是一棵被完全填满的二叉树(除了底层,底层的元素从左到右依次填入);
2、二叉堆具有堆序性质(即具有最小权值的堆元素处在树根位置,父节点权值小于等于子节点的权值);

二、二叉堆实现
因为二叉堆的堆序性质,所有可用来实现按权值优先输出的优先队列。此外,因为二叉堆是满二叉树,所以当用数组来存储堆元素时,父子节点间有银行关系,若父节点在数组中的位置为i,则左子节点在数组中的位置为2*i,右子节点在数组中的位置为2*i+1,如下图所示:
这里写图片描述
这里写图片描述

三、二叉堆的基本操作
二叉堆的基本操作有入队(添加元素)、出队(删除最小元素),上滤,下滤;
入队:先假设新入队的元素插在最后面,然后根据二叉堆的堆序性质逐渐上滤,知道找到正确位置;
出队:因为具有最小权值的元素在树根出,所以要把树根元素出队,但是此时树根就空了,根据堆序性质,需要从左、右儿子中选择一个儿子填上,逐渐上滤,直到满足条件。

四、其他堆操作:
改变堆元素的权值:此时更新完元素权值后,同时需要更新元素所处堆位置,如果增大权值,则要执行下滤操作,降低权值,则需要执行上滤操作。
求第k小堆元素:执行出队操作k此,第k次出队的元素就是第k小的元素。

附录

#include<stdio.h>
#include<stdlib.h>
typedef struct HeapStruct* PriorityQueue;
struct HeapStruct{
    int capacity;//堆的容量 
    int size;//现在堆的大小 
    int *element;//堆元素 
};
PriorityQueue Initialize(int MaxElements);//初始化堆 
void Insert(PriorityQueue H,int x);//插入堆元素 
int DeleteMin(PriorityQueue H);//出堆 
int IsEmpty(PriorityQueue H);
int IsFull(PriorityQueue H);
void DecreaseKey(PriorityQueue H,int position,int deta);
void IncreaseKey(PriorityQueue H,int position,int deta);
int IsEmpty(PriorityQueue H){
    return H->size==0;
} 
int IsFull(PriorityQueue H){
    return H->size==H->capacity;
}
PriorityQueue Initialize(int MaxElement){
    PriorityQueue H;
    H=(PriorityQueue)malloc(sizeof(struct HeapStruct));
    if(H==NULL)
        printf("Out of space!!!");
    H->size=0;
    H->capacity=MaxElement;
    H->element=(int*)malloc(sizeof(int)*(MaxElement+1));
    if(H->element==NULL)
        printf("Out of space!!!");
    H->element[0]=-1000;
    return H;
}
void Insert(PriorityQueue H,int x){
    int i;
    if(IsFull(H)){
        printf("The binheap is full!!");
        return;
    }
    H->size++;
    for(i=H->size;i>1;i/=2){
        if(H->element[i/2]>x)
            H->element[i]=H->element[i/2];
        else
            break;
    }
    H->element[i]=x;
}
int DeleteMin(PriorityQueue H){
    int min,last,i,child;
    min=H->element[1];
    last=H->element[H->size];
    H->size--;
    for(i=1;i*2<=H->size;i=child){
        child=i*2;
        if(child+1<=H->size&&H->element[child]>H->element[child+1])
            child++;
        if(H->element[child]<last)
            H->element[i]=H->element[child];
        else{
            break;
        }
    }
    H->element[i]=last;
    return min;
}
//降低某个堆元素的权值,提高执行等级 
void DecreaseKey(PriorityQueue H,int position,int deta){
    H->element[position]-=deta;
    int i=position;
    int key=H->element[position];
    while(H->element[i/2]>key){
        H->element[i]=H->element[i/2];
        i/=2;
    }
    H->element[i]=key;
}
//增加某个堆元素的权值,降低执行等级 
void IncreaseKey(PriorityQueue H,int position,int deta) {
    H->element[position]+=deta;
    int i,child;
    int key=H->element[position];
    for(i=position;i*2<=H->size;i=child){
        child=2*i;
        if(child+1<=H->size&&H->element[child]>H->element[child+1])
            child++;
        if(H->element[i]>H->element[child])
            H->element[i]=H->element[child];
        else
            break;
    } 
    H->element[i]=key;
}
int main(){
    int N,n,k,t;
    PriorityQueue H;
    scanf("%d",&N);//堆的容量 
    H=Initialize(N);//初始化堆 
    for(int i=1;i<=N;i++){
        scanf("%d",&n);
        Insert(H,n);
    }
    for(int i=1;i<=H->size;i++)
        printf("%d ",H->element[i]);//将堆元素输出
    printf("\n");
    /*printf("\n请输入要查找的第k小的值(k<N):");
    scanf("%d",&k);
    for(int i=1;i<=k;i++)
        t=DeleteMin(H);
    printf("%d",t);*/
    IncreaseKey(H,5,20);
    for(int i=1;i<=H->size;i++)
        printf("%d ",H->element[i]);//将堆元素输出
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值