二叉堆的基本操作

  二叉堆也就是一棵完全二叉树。堆顶最大则为大根堆,堆顶最小则为小根堆,这里实现的是小根堆。


1.定义
用一个数组来存储数据,size代表当前堆的元素个数,capacity代表这个堆的总长度。

typedef int eletype; 
typedef struct heapstruct
{
    int capacity;
    int size;
    eletype *arr; 
}Heap;

2.新建一个二叉堆
给二叉堆分配空间,给存储数据用的数组分配空间,每次分配空间都有可能分配失败,所以需要一个特判,分配失败就退出,然后将capacity设为max,因为还没有插入过,所以size刚开始为0。

Heap *CreateHeap(int max)
{
    Heap *H;
    H = malloc(sizeof(Heap));
    if (H == NULL) {
        printf("Out of space\n");
        return NULL;
    }
    H->arr = malloc(sizeof(eletype) * (max + 1));
    if (H->arr == NULL) {
        printf("Out of space\n");
        return NULL;
    }
    H->capacity = max;
    H->size = 0;
    H->arr[0] = 0; 
​​​​​​​    return H;
}

3.插入
写一个函数,percolateUP用来找到合适位置,意思是上滤找到合适的插入位置,然后将size+1代表元素数量增加了1个,然后在最开头需要进行一个特判,如果这个堆满了,代表无法在进行插入了,所以要返回失败。

int isFull(Heap h){
	return h->capacity==h->size;
}
void percolateUP(int k,Heap h){
	int x;
	x=h->arr[k];
	int i;
	for(i=k;i>1&&h->arr[i]<h->arr[i/2];i/=2) h->arr[i]=h->arr[i/2];
	h->arr[i]=x;
}
int insertHeap(int x,Heap h){
	if(isFull(h)) return 0;
	h->arr[(h->size+1)]=x;
	h->size++;
	percolateUP(h->size,h);
	return 1;
}

4.删除最小元素(堆顶)
为了保证删除后仍是一个完整的二叉堆,要将原堆顶以下的数据进行适当的上滤,和插入差不多,将size--,代表元素数量减1(毕竟删除了一个数字)。

eletype DeleteMin(Heap *H)
{
    if (H->size == 0) {
        printf("Heap is empty\n");
        return 0;
    }
    eletype min = H->arr[1];
    eletype last = H->arr[H->size--]; 
    int i, child;
    for(i = 1; i * 2 <= H->size; i = child) {
        child = i * 2;
        if (child != H->size && H->arr[child + 1] < H->arr[child])
            child++;
        if (last > H->arr[child])
            H->arr[i] = H->arr[child];
        else
            break;
    }
    H->arr[i] = last;
    return min;
}

5、判断堆是否为空

看他的元素个数是否为0

int isEmpty(Heap *H)
{
    if (H->size == 0) {
        printf("Heap is empty\n");
        return 0;
    }
}

6、判断堆是否满了

 就看size和capacity是否相等

int isFull(Heap h){
	return h->capacity==h->size;
}

7、输出堆

按顺序输出即可

void printHeap(Heap h){
	for(int i=1;i<=h->capacity;i++) 
      cout<<h->arr[i]<<" ";
}

  堆的基本操作就讲到这里了,希望大家尽快学会哦! 

总代码:
 

#include<bits/stdc++.h>
using namespace std;
typedef int Elem;
struct heap{
	Elem *data;
	int capacity;
	int size;
};
typedef struct heap* Heap;
Heap initHeap(int max){
	Heap h;
	h=(Heap)malloc(sizeof(struct heap));
	if(!h) return NULL;
	h->data=(Elem*)malloc(sizeof(Elem)*(max+1));
	if(!h->data) return NULL;
	h->capacity=max;
	h->size=0;
	for(int i=1;i<=max;i++) h->data[i]=0;
	return h;
}
void printHeap(Heap h){
	for(int i=1;i<=h->capacity;i++) cout<<h->data[i]<<" ";
}
int isEmpty(Heap h){
	return h->size==0;
}
int isFull(Heap h){
	return h->capacity==h->size;
}
void percolateUP(int k,Heap h){
	Elem x;
	x=h->data[k];
	int i;
	for(i=k;i>1&&h->data[i]<h->data[i/2];i/=2) h->data[i]=h->data[i/2];
	h->data[i]=x;
}
int insertHeap(Elem x,Heap h){
	if(isFull(h)) return 0;
	h->data[(h->size+1)]=x;
	h->size++;
	percolateUP(h->size,h);
	return 1;
}
void percolateDown(int k,Heap h){
	Elem x;
	x=h->data[k];
	int i,child;
	for(i=k;i*2<=h->size;i=child){
		child=i*2;
		if(child!=h->size&&h->data[child]>h->data[child+1]) child++;
		if(h->data[i]>h->data[child]) h->data[i]=h->data[child];
	}
	h->data[i]=x;
}
int removeHeap(Elem *px,Heap h){
	if(isEmpty(h)) return 0;
	*px=h->data[1];
	h->data[1]=h->data[h->size];
	h->size--;
	percolateDown(1,h);
	return 1;
}
int main(){
	Heap h;
	int n;
	cin>>n;
	h=initHeap(10);
	int a[n];
	for(int i=0;i<n;i++){
		cin>>a[i];
		insertHeap(a[i],h);
	}
	printHeap(h);
	cout<<endl; 
	while(1){
		int f;
		cout<<"1代表插入,0代表删除:";
		cin>>f;
		if(f==1){
			int t;
			cout<<"请输入要插入的数字:";
			cin>>t;
			insertHeap(t,h);
		}
		else if(f==0){
			int t;
			removeHeap(&t,h);
			cout<<"删除的数为:"<<t<<endl;
		}
		else{
			cout<<"没有此命令!"<<endl;
			continue; 
		}
		printHeap(h);
	} 
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙星尘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值