堆的操作集
什么是堆
- 优先队列( Priority Queue):特殊的“队列” ,取出元素的顺序是
依照元素的优先权(关键字) 大小,而不是元素进入队列的先后顺序
问题:如何组织优先队列?
一般的数组、链表?
有序的数组或者链表?
二叉搜索树? AVL树
-
产生了堆这种数据结构,知道基本操作集
-
增查的操作方式,创建的方法
测试代码
/*!
* \file 堆的操作集.cpp
*
* \author ranjiewen
* \date 2017/04/06 23:25
*
*
*/
#include <stdio.h>
#include <stdlib.h>
typedef struct HNode *Heap; //堆的类型定义
typedef int Elementype;
struct HNode
{
Elementype *Data; //存储元素的数组 //堆是完全二叉树,用数组存储利用率高
int size; //堆中当前元素的个数
int capacity; //堆的最大容量
};
typedef Heap MaxHeap; //最大堆
typedef Heap MinHeap; //最小堆
#define MAXDATA 1000 //该值应根据情况定义为大于堆中所有可能元素的值
MaxHeap CreateHeap(int MaxSize)
{
//创建容量为MaxSize的空的最大堆
MaxHeap H = (MaxHeap)malloc(sizeof(struct HNode));
H->Data = (Elementype*)malloc((MaxSize+1)*sizeof(Elementype));
H->size = 0;
H->capacity = MaxSize;
H->Data[0] = MAXDATA; //定义“哨兵”为大于堆中所有可能元素的值
return H;
}
int IsFull(MaxHeap H)
{
return H->size == H->capacity;
}
//bool
int Insert(MaxHeap H, Elementype x)
{
//将元素x插入最大堆H,其中H->Data[0]已经定义为哨兵
int i;
if (IsFull(H))
{
printf("最大堆已满!");
return false;
}
i = ++H->size; //i指向插入后堆中的最后一个元素的位置
//先直接到插入到数组最后的元素,然后在调整堆
for (; H->Data[i / 2] < x;i/=2) //父节点比它小
{
H->Data[i] = H->Data[i/2]; // 和父节点交换
}
H->Data[i] = x; //找到插入位置,插入
return 1;
}
#define ERROR -1 //错误标识,定义为堆中不可能出现的元素值
bool IsEmpty(MaxHeap H)
{
return H->size == 0;
}
Elementype DeleteMax(MaxHeap H)
{
//从最大堆H中取出键值为最大的元素,并删除一个结点
int Parent, Child;
Elementype MaxItem, x;
if (IsEmpty(H))
{
printf("最大堆已为空");
return ERROR;
}
MaxItem = H->Data[1]; //取出根节点存放的最大值
//用最大堆中最后一个元素从根节点开始向上过滤下层结点
x = H->Data[H->size--]; //注意当前堆的规模要减小
for (Parent = 1; Parent * 2 <= H->size;Parent=Child)
{
Child = Parent * 2;
if ((Child!=H->size) && (H->Data[Child]<H->Data[Child+1]) ) //Child指向左右子节点中较大者 //注意没有右孩子的情况
{
Child++;
}
if (x>=H->Data[Child])
{
break; //找到合适的位置
}
else /* 下滤X */
{
H->Data[Parent] = H->Data[Child];
}
}
H->Data[Parent] = x;
return MaxItem;
}
/*------------建造最大堆----------------------*/
void PrecDown(MaxHeap H, int p)
{
//下滤:将H中以H->Data[p]为根的子堆调整为最大堆
int Parent, Child;
Elementype x;
x = H->Data[p]; //取出根节点存放的值
for (Parent = p; Parent * 2 <= H->size;Parent=Child)
{
Child = Parent * 2;
if ((Child!=H->size)&&(H->Data[Child]<H->Data[Child+1]))
{
Child++; //Child指向左右子节点的较大者
}
if (x>=H->Data[Child])
{
break;
}
else /* 下滤X */
{
H->Data[Parent] = H->Data[Child];
}
}
H->Data[Parent] = x;
}
void BuildHeap(MaxHeap H)
{
//调整H->Data[]中的元素,是满足最大堆的有序性
//这里假设所有H->size个元素已经存在H->Data[]中
int i;
//从最后一个结点的父节点开始,到根结点
for (i = H->size / 2; i > 0;i--)
{
PrecDown(H, i);
}
}
int main()
{
MaxHeap H;
H = CreateHeap(10);
for (int i = 0; i < 10;i++)
{
Insert(H, i + 10);
}
for (int i = 0; i < H->size;i++)
{
printf("%d ", H->Data[i + 1]);
}
printf("\n");
for (int i = 0; i < H->size; i++)
{
H->Data[i + 1] = i + 10;
}
BuildHeap(H);
for (int i = 0; i < H->size; i++)
{
printf("%d ", H->Data[i + 1]);
}
printf("\n");
return 0;
}
C/C++基本语法学习
STL
C++ primer