赞
踩
类型名称:最大堆(MaxHeap)
数据对象集:完全二叉树,每个结点的元素值不小于其子结点的元素值
操作集:最大堆 H ∈ MaxHeap,元素item ∈ ElementType,主要操作有:
- MaxHeap Create( int MaxSize ):创建一个空的最大堆
- Boolean IsFull( MaxHeap H ):判断最大堆H是否已满
- Insert( MaxHeap H, ElementType item ):将元素item插入最大堆H
- Boolean IsEmpty( MaxHeap H ):判断最大堆H是否为空
- ElementType DeleteMax( MaxHeap H ):返回H中最大元素(高优先级)
typedef int ElementType; // 定义堆元素的数据类型
typedef struct HeapStruct
{
ElementType *Elements; // 存储堆元素的数组
int Size; // 堆当前元素的个数
int Capacity; // 堆的最大容量
} HeapStruct; //
typedef HeapStruct* MaxHeap; // MaxHeap 指向一个最大堆
MaxHeap Create(int MaxSize)
{
MaxHeap H = (MaxHeap)malloc(sizeof(HeapStruct));
H->Elements = (ElementType *)malloc(sizeof(ElementType) * (MaxSize + 1));
H->Size = 0;
H->Capacity = MaxSize;
H->Elements[0] = MaxData; // 定义“哨兵”为一个值,其大于堆中所有可能元素的值
return H;
}
H->Elements[i] = H->Elements[i / 2];
直接过滤结点(更新子节点为父节点内容,并且更新待插入结点的位置)void Insert(MaxHeap H, ElementType item) { /* 将元素 item 插入最大堆 H,其中 H->Elements[0] 已经定义为哨兵 */ /* H->Elements[0] 是哨兵元素,不小于堆中的最大元素,控制循环结束 */ if (Full(H)) // heap is full,then 无法插入元素 return; int i; // i 用于记录待插入结点最终在二叉树中的位置 /* 初始化 i 指向插入后堆中的最后一个元素的位置 */ /* item > H->Elements[i / 2] 判断待插入结点和其父节点的大小关系 如果 item 更大,则将父节点移动到当前待插入结点的位置,同时更新子节点的位置 i */ for (i = ++H->Size; item > H->Elements[i / 2]; i /= 2) H->Elements[i] = H->Elements[i / 2]; // 过滤结点 H->Elements[i] = item; // 将 item 插入到应有的位置 }
ElementType DeleteMax(MaxHeap H) { /* 从最大堆 H 中取出键值最大的元素,并删除一个结点 */ if (Empty(H)) // heap is empty,then 无法删除元素 return; int Parent, Child; // 分别表示父节点和子节点的数组下标 ElementType maxItem = H->Elements[1]; // 取出根节点的最大值 ElementType temp = H->Elements[H->Size--]; // 用最大堆中最后一个元素从根节点开始过滤下层结点 /* 如果 temp 要和儿子比较,前提是要有儿子 */ /* Parent * 2 <= H->Size 表示至少有左儿子 */ /* 表示更新 Parent 的位置 */ for (Parent = 1; Parent * 2 <= H->Size; Parent = Child) { Child = Parent * 2; // if (Parent * 2 <= H->Size + 1) // 表示有右儿子 // Child = H->Elements[Child] > H->Elements[Child + 1] ? Child : Child + 1; /* Child != H->Size 表明 Parent 位置的结点有右儿子 */ if ((Child != H->Size) && (H->Elements[Child] < H->Elements[Child + 1])) Child++; // 更新 Child 为 Parent 位置结点的儿子中值最大的哪个 // 即 Child 指向左右子节点的较大者 /* 如果 Parent 位置的结点的值 < 它最大的儿子的结点值,则将儿子结点拉上来做父节点,Parent 更新到对应的儿子节点的位置 */ if (temp < Child) // 移动 temp 元素到下一层 H->Elements[Parent] = H->Elements[Child]; else break; } H->Elements[Parent] = temp; return maxItem; }
/* 根据的完全二叉树建立一个堆 */ /* 向下过滤,H 是一个二叉树,其以 H->Elements[p] 为根节点的子树的子树是堆。 通过向下过滤,使得 H->Elements[p] 对应的子树也变成堆 */ /* 传入的参数 H 确保是一颗完全二叉树,并且对应子树 H->Elements[p] 的对应的子树都是堆 */ void FilterDown(MaxHeap H, int p) { int Parent, Child; // 分别表示父节点和子节点的数组下标 ElementType temp = H->Elements[p]; for (Parent = 1; Parent * 2 <= H->Size; Parent = Child) { Child = Parent * 2; /* Child != H->Size 表明 Parent 位置的结点有右儿子 */ if ((Child != H->Size) && (H->Elements[Child] < H->Elements[Child + 1])) Child++; // 更新 Child 为 Parent 位置结点的儿子中值最大的哪个 // 即 Child 指向左右子节点的较大者 /* 如果 Parent 位置的结点的值 < 它最大的儿子的结点值,则将儿子结点拉上来做父节点,Parent 更新到对应的儿子节点的位置 */ if (temp < Child) // 移动 temp 元素到下一层,即向下过滤 H->Elements[Parent] = H->Elements[Child]; else break; } H->Elements[Parent] = temp; } /* 建立二叉树,根据传入的完全二叉树,调整使得其满足最大堆的有序性质,转换为最大堆 */ void BuildHeap(MaxHeap H) { /* 从最后一个有孩子的结点开始(或者说是最后一个结点的父节点),遍历到第一个结点 */ for (int i = H->Size / 2; i > 0; i++) FilterDown(H, i); }
/* 堆已满或为空的判断 */
bool Full(MaxHeap H)
{
return H->Size == H->Capacity;
}
bool Empty(MaxHeap H)
{
return H->Size == 0;
}
“哨兵”是在创建堆(Create 函数)时设置的:H->Elements[0] = MaxData?【√】
有个堆,其元素在数组中的序列为:58、25、44、18、10、26、20、12,如果调用 DeleteMax 函数删除其最大值函数,则程序中的 for 循环刚退出时变量 Parent 的值为?【6】
建堆时,最坏情况下需要挪动元素次数是的等于树中各结点的高度和。问,对于元素个数为 12 的堆,其结点的高度和是多少?【10】
在最大堆 {97,76,65,50,49,13,27} 中插入 83 后,该最大堆为 【{97,83,65,76,49,13,27,50}】
对由同样 n 个整数构成的二叉搜索树和最小堆,
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。