最大堆实现

1、基本概念

堆分为小根堆和大根堆,对于一个小根堆,它是具有如下特性的一棵完全二叉树:

(1)若树根结点存在左孩子或右孩子,则根结点的值(或某个域的值)小于等于左右孩子结点的值(或某个域的值)

(2)以左、右孩子为根的子树又各是一个堆。

大根堆的定义将上面的小于等于改成大于等于即可。

根据根的定义,小根堆的堆顶结点具有最小值,大根堆的堆顶结点具有最大值。

2、堆的存储结构

由于堆是一棵完全二叉树,所以适宜采用顺序存储结构,这样能够充分利用存储空间。

顺序存储结构:

对堆中所有结点进行编号,作为下标存储到指定数组的对应元素中,下标从0开始。按照从上到下,同一层从左到右进行。

设堆中有n个结点,则编号为 0 ~ n-1,则有如下性质:

(1)编号为 0 至 [n/2-1] 的结点为分支结点, 编号为 [n/2] 至 n-1 的结点为叶子结点;

(2)当 n 为奇数则每个分支结点既有左孩子又有右孩子,当 n 为偶数则每个分支结点只有左孩子没有右孩子

(3)对于每个编号为 i 的分支结点,其左孩子结点的编号为 2i+1,右孩子结点的编号为 2i+2

(4)除编号为0的堆顶结点外,对于其余编号为 i 的结点,其双亲结点的编号为 [(i-1)/2]

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

typedef struct Heap
{
	int *key;
	int len;
	int MaxSize;
}Heap_Node;

int Heap_Init(Heap_Node *Node,int len, int MaxSize)
{
	if (len < 0 || MaxSize < 0)
	{
		printf("error");
		return 1;
	}
	Node->key = (int *)malloc(sizeof(int)*MaxSize);
	Node->len = len;
	Node->MaxSize = MaxSize;
	return 0;
}

int Heap_Clear(Heap_Node *Node)
{
    free(Node->key);
	Node->len = 0;
	Node->MaxSize = 0;
	return 0;
}

int Heap_Insert(Heap_Node *Node,int key)                     //最大堆的插入原理:
{															 //将要插入的元素插入到尾部,然后与其双亲结点比较,如果大于双亲结点,则上移
	if (Node == NULL || key == NULL)						 //直至小于双亲结点或者到达头结点为止
	{
		return 1;
	}
	else if (Node->len == 0)
	{
		Node->key[0] = key;
		Node->len++;
		return 0;
	}
	else
	{
		if (Node->len > Node->MaxSize)
		{
			printf("This Heap have already full");
			return 1;
		}
		Node->key[Node->len] = key;  //队尾插入元素
		int j = Node->len;  //插入结点位置
		Node->len++;        //长度加一
		int parent = (j - 1) / 2;  //双亲结点
		
		while (j != 0)
		{
			if (Node->key[parent]< key)
			{
				Node->key[j] = Node->key[parent];
				j = parent;
				parent = (j - 1) / 2;
			}
			else
			{
				break;
			}
		}
		Node->key[j] = key;
		return 0;
	}
}

int Heap_Delete(Heap_Node *Node)                  //最大堆的删除操作原理:
{												  //将首元素删除,然后将尾元素插入到删除首元素的位置,然后与左右子节点中!最大的进行比较!
	int x = Node->key[0];						  //如果其小于子节点,则将其调换位置,直至到达叶子结点
	int lchild, rchild;
	int temp = Node->key[Node->len];
	Node->len--;
	Node->key[0] = temp;
	int t = 0;       //标记要换位置的结点位置                    
	lchild = t * 2;  //其左孩子
	rchild = t * 2 + 1;  //其右孩子
	while (lchild <= Node->len-1 )
	{
		if (Node->key[lchild]>Node->key[rchild] && Node->key[lchild] > temp)
		{
			int m = Node->key[lchild];
			Node->key[lchild] = temp;
			Node->key[t] = m;
			t = lchild;
			lchild = t * 2;
			rchild = t * 2 + 1;
		}
		else if (Node->key[rchild] > Node->key[lchild] && Node->key[rchild] > temp)
		{
			int m = Node->key[rchild];
			Node->key[rchild] = temp;
			Node->key[t] = m;
			t = rchild;
			lchild = t * 2;
			rchild = t * 2 + 1;
		}
		else
		{
			break;
		}
	}
	return x;
}

int Heap_Len(Heap_Node *Node)
{
	return Node->len;
}

int Heap_MaxSize(Heap_Node *Node)
{
	return Node->MaxSize;
}

int main()
{
	int len = 0, MaxSize = 10;
	int t=6;   //要插入的数的个数
	Heap_Node Node;
	int key[8] = { 10,16,23,38,40,55,56,62 };
	Heap_Init(&Node,len,MaxSize);
	Heap_Insert(&Node, key[0]);
	Heap_Insert(&Node, key[1]);
	Heap_Insert(&Node, key[2]);
	Heap_Insert(&Node, key[3]);
	Heap_Insert(&Node, key[4]);
	Heap_Insert(&Node, key[5]);
	Heap_Insert(&Node, key[6]);
	Heap_Insert(&Node, key[7]);
	
	for (int i = 0; i < 8; i++)
	{
		
		int key = Heap_Delete(&Node);
		//printf("key=%d\n", Node.key[i]);
		printf("%d\n", key);
	}
	//Heap_Clear(&Node);
	

	system("pause");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值