堆(heap)
什么是堆
-
定义
堆(heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。
-
性质
- 结构性:用数组表示的完全二叉树。
- 有序性:任意节点的关键字(权值)是其子树所有节点的最大值(或最小值)
- 父节点大于子节点:最大堆(MaxHeap)
- 父节点小于子节点:最小堆(MinHeap)
-
应用
- 优先队列
“优先队列” (Priority Queue)是特殊的“队列”,从队列中取出元素的顺序是依照元素的优先权(关键字)大小,而不是元素进入队列的先后顺序。
- 堆排序
-
举例
- 堆:最大堆或最小堆
- 不是堆:不是完全二叉树或节点权值不符合要求
最小堆的操作
- 数据名称:最小堆(MinHeap)
- 数据对象集:
一个有
N
>
0
N \gt 0
N>0个元素的最小堆是一棵完全二叉树,每个节点上的元素值不大于其子节点元素的值。 - 操作集:
对于任意最多有MaxSize个元素的最小堆
H
∈
M
i
n
H
e
a
p
H \in MinHeap
H∈MinHeap元素
i
t
e
m
∈
E
l
e
m
e
n
t
T
y
p
e
item \in ElementType
item∈ElementType,主要操作有:
- MinHeap Create(int Maxsize): 创建一个空的最小堆。
- void Destroy(MinHeap):释放堆的空间。
- Boolean IsFull(MinHeap H): 判断最小堆是否已满。
- Boolean IsEmpty(MinHeap H): 判断最小堆是否为空。
- void Insert(MinHeap H,ElementType item): 将元素item插入最小堆H。
- ElementType DeleteMin(MinHeap H): 返回最小堆H中最小元素(高优先级)。
操作集的实现(C语言)
-
数组表示的完全二叉树
数组下标为0的位置放一个比所有堆中元素都要小的元素(可以是ElementType的最小值),称为“哨兵”。从下标为1的位置开始存放堆中元素。因为是完全二叉树,所以父亲节点与其左右子节点下标满足一些关系。
例:
由子节点找父节点:父节点下标=子节点下标 / 2
由父节点找左子节点:左子节点下标=父节点下标 * 2
由父节点找右子节点:右子节点下标=父节点下标 * 2 + 1
-
存储结构
typedef struct HeapStruct{
ElementType *Element;
int Size;
int MaxSize;
}HeapStruct,*MinHeap;
-
操作集的实现
-
MinHeap Create(int MaxSize): 创建一个空的最小堆
MinHeap Create(int MaxSize)
{
MinHeap H = (MinHeap)malloc(sizeof(struct HeapStruct));
H->Elenment = (ElementType *)malloc((MaxSize + 1) * sizeof(ElementType));
H->Size = 0;
H->MaxSize=MaxSize;
H->Elenment[0] = INT_MIN;
return H;
}
-
void Destroy(MinHeap H): 释放堆申请的空间
void Destroy(MinHeap H)
{
free(H->Elenment);
free(H);
}
-
boolean IsFull(MinHeap H): 判断最小堆是否已满
boolean IsFull(MinHeap H)
{
return (H->Size == H->MaxSize);
}
-
boolean IsEmpty(MinHeap H): 判断最小堆是否为空
boolean IsEmpty(MinHeap H)
{
return (H->Size == 0);
}
-
void Insert(MinHeap H,ElementType item): 将元素item插入最小堆H
void Insert(MinHeap H, ElementType item)
{
int i = 0;
if (IsFull(H))
{
printf("Heap is full\n");
return;
}
H->Size++;
for (i = H->Size; H->Element[i / 2] > item; i = i / 2)
{
H->Element[i] = H->Element[i / 2];
}
H->Element[i] = item;
}
-
ElementType Delete(MinHeap H): 返回最小堆H中最小元素(高优先级)
ElementType Delete(MinHeap H)
{
int parent=0,child=0;
ElementType item,temp;
if (IsEmpty(H))
{
printf("Heap is Empty\n");
return H->Element[0];
}
item = H->Element[1];
temp = H->Element[H->Size];
H->Size--;
for (parent = 1; parent *2 <= H->Size; parent = child)
{
child = parent *2;
if (child != H->Size && (H->Element[child] > H->Element[child + 1]))
{
child++;
}
if (temp > H->Element[child])
{
H->Element[parent] = H->Element[child];
}
else
{
break;
}
}
H->Element[parent] = temp;
return item;
}
-
MinHeap BuildMinHeap(ElementType *Elenment, int Size): 创建一个非空的堆
已知堆中元素,但是不知道其在数组中的排列顺序,可以有两种创建堆的方法:一是先创建一个空堆,再使用Insert()函数将元素一个个插入堆中。二是直接将数组复制到堆节点的Element数组中,然后进行排序。
第二种方法比第一种方法时间复杂度更低。
MinHeap BuildMinHeap(ElementType *Element, int Size,int MaxSize)
{
MinHeap H = NULL;
int i = 0, parent = 0, child = 0;
ElementType Temp;
H = CreateMinHeap(MaxSize);
if (Size > H->MaxSize)
{
printf("最小堆存储空间不足,建立最小堆失败\n");
return NULL;
}
for (i = 0; i < Size; i++)
{
H->Element[i + 1] = Element[i];
}
H->Size = Size;
for (parent = H->Size / 2; parent >= 1; parent--)
{
Temp = H->Element[parent];
for (; parent * 2 <= H->Size; parent = child)
{
child = parent * 2;
if (child != H->Size && (H->Element[child] > H->Element[child + 1]))
{
child++;
}
if (Temp > H->Element[child])
{
H->Element[parent] = H->Element[child];
}
else
{
break;
}
}
H->Element[parent] = Temp;
}
return H;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)