二叉堆的插入,删除和逐层输出

代码主要借鉴《Data Structures and Algorithm Analysis in C (Second Edition)》。

插入操作就是现在最底部创建一个空穴,然后上滤。

删除操作用下滤实现,注意要考虑一个节点只有一个儿子的情况(这种情况只可能出现在堆的最后)。

逐层输出利用stl的queue实现,实现的过程类似bfs。

/*                                  something about heap                             */

#include <cstdio>
#include <queue>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;

typedef struct heaap{
	int ele[5000];
	int level[5000];
	int size;
	int max;
}hea;

typedef hea* heap;

heap initial()
{
	heap newheap;
	newheap = (heap) malloc (sizeof(hea));
	newheap->size = 0;
	return newheap;
}

void insert(int key, heap target)
{
	int i;
	if(target->size == 0)
	{
		target->size++;
		target->ele[target->size] = key;
		target->level[target->size] = 1;
		return ;
	}
	for(i = ++target->size; target->ele[i/2] > key; i /= 2)
		target->ele[i] = target->ele[i/2];
	target->level[target->size] = log(target->size)/log(2) + 1;         //每插入一个元素,就会在堆的最下方产生一个新的穴,为了逐层输出,我们需要确定它在第几层。因为二叉堆是完全二叉树,多以第n个节点在第[log(n)/log(2)+1向下取整]层上。
	//printf("level = %d\n",target->level[target->size]);
	target->ele[i] = key;
	return ;
}

void print(heap tar)
{
	if(tar->size == -1)
	{
		printf("BLANK HEAP\n");
		return ;
	}
	else
	{
		queue<int> que;
		que.push(1);
		int level = tar->level[1];
		while(!que.empty())
		{
			int temp = que.front();
			que.pop();
			if(level != tar->level[temp])
			{
				printf("\n");
				level = tar->level[temp];
			}
			printf("%d ",tar->ele[temp]);
			if(temp * 2 <= tar->size)
				que.push(temp * 2);
			if(temp * 2 + 1 <= tar->size)
				que.push(temp * 2 + 1);
		}
	}
	printf("\n\n");
}

int topandpop(heap tar)
{
	int i, child;
	int minele, lastele;
	if(tar->size == 0)
	{
		printf("PriorityQueue is Empty\n");
		return 0;
	}
	minele = tar->ele[1];
	lastele = tar->ele[tar->size--];
	for(i = 1; i*2 <= tar->size; i = child)
	{
		child = i*2;
		if(child != tar->size && tar->ele[child+1] < tar->ele[child])
			child++;
		if(lastele > tar->ele[child])
			tar->ele[i] = tar->ele[child];
		else
			break;
	}
	tar->ele[i] = lastele;
	return minele;
}
				
int main()
{
	//freopen("ztest.txt","r",stdin);
	printf("Call For a PriorityQueue\n");
	heap newheap = initial();
	int n;
	while(scanf("%d", &n) && n)
		insert(n, newheap);
	printf("\n\n");
	print(newheap);
	printf("1 is delete minimum and pop it while 0 is quit\n");
	while(scanf("%d", &n) && n)
	{
		printf("\n\ntop : %d\n\n",topandpop(newheap));
		print(newheap);
	}
	return 0;
}
	

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
建立堆的基本步骤: 1. 申请一块连续的内存空间,用来存放堆元素。 2. 将元素依次插入到堆中,并调整堆的结构,使其满足堆的性质。 插入元素的操作: 1. 将新元素插入到堆的末尾。 2. 从插入位置开始,向上层比较,如果父节点的值小于新元素的值,则将父节点的值下移,直到找到新元素的正确位置,将新元素插入删除元素的操作: 1. 将堆顶元素删除,并将堆末尾元素移到堆顶。 2. 从堆顶开始,向下层比较,选择较大(或较小)的子节点进行交换,直到找到正确位置。 堆的输出: 堆可以按照层次遍历的顺序输出所有元素,也可以按照任意顺序输出元素。 以下是一个简单的C语言堆的实现代码: ```c #include <stdio.h> #include <stdlib.h> #define MAX_SIZE 100 typedef struct { int *data; int size; } Heap; void swap(int *a, int *b) { int temp = *a; *a = *b; *b = temp; } Heap *create() { Heap *h = (Heap *)malloc(sizeof(Heap)); h->data = (int *)malloc(MAX_SIZE * sizeof(int)); h->size = 0; return h; } void insert(Heap *h, int x) { int i = ++h->size; while (i != 1 && h->data[i / 2] < x) { h->data[i] = h->data[i / 2]; i /= 2; } h->data[i] = x; } int delete(Heap *h) { int max = h->data[1]; int last = h->data[h->size--]; int parent = 1, child = 2; while (child <= h->size) { if (child < h->size && h->data[child] < h->data[child + 1]) { child++; } if (last >= h->data[child]) { break; } h->data[parent] = h->data[child]; parent = child; child *= 2; } h->data[parent] = last; return max; } void print(Heap *h) { for (int i = 1; i <= h->size; i++) { printf("%d ", h->data[i]); } printf("\n"); } int main() { Heap *h = create(); insert(h, 3); insert(h, 1); insert(h, 4); insert(h, 1); insert(h, 5); insert(h, 9); insert(h, 2); insert(h, 6); insert(h, 5); print(h); delete(h); print(h); delete(h); print(h); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值