最大堆实现
程序员文章站
2024-01-16 23:09:10
...
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;
}