堆(heap)
这个堆不是堆栈。
堆是用完全二叉树储存。
堆是解决不是按照(时间或是说输入顺序)来进行排队,而是以优先的级别来排序。这就是优先队列了。
堆的特性
结构性:堆使用完全二叉树来存储,所以具备了完全二叉树的性质。所有子树的根结点比左右结点大。
有序性:任一结点的关键字是其子树所有结点的最大值(或最小值)
- 最大堆(MaxHeap):最大值
- 最小堆(MinHeap):最小值
优先队列
优先队列(Priority Queue):特殊的“队列”,取出元素的顺序是依照元素的优先权大小,而不是元素进入队列的先后顺序。
数组实现
1,插入:元素总是插入尾部
2,删除:查找最大元素(或最小)关键字。(从数组删除元素需要移动元素)
链表实现
1,插入:元素总是插入链表的头部
2,删除:查找最大(或最小)关键字。(直接删除结点)
有序数组实现
1,插入:找到合适位置,移动元素并插入。
2,删除:删除最后一个元素
有序链表实现
1,插入:找到合适位置,插入元素。
2,删除:删除最后一个元素
用树来实现
为了保证它在删除结点之后,树不会歪,就要考虑采用什么样的树。这个就是完全二叉树了。
最大堆(MaxHeap)
完全二叉树,每个结点的元素值不小于其子结点的元素值。
堆的结构体和定义
#define MaxData 10000 //定义哨兵
typedef struct HeapStruct *MaxHeap;
typedef enum { false, true } Boolean;
struct HeapStruct{
ElementType *Elements;//储存堆元素的数组
int Size;//堆当前元素个数
int Capacity;//堆的最大容量
}
主要操作:
1,MaxHeap Create(int MaxSize):创建一个空的最大堆。
MaxHeap Create(int MaxSize){
MaxHeap H = malloc(sizeof(struct HeapStruct));
H->Elements=malloc((MaxSize+1)*sizeof(ElementType));//创建数组
H->Size = 0;
H->Capacity =MaxSize;
H->Elements[0]=MaxData;//哨兵
}
2,Boolean IsFull(MaxHeap H):判断最大堆H是否已满。
Boolean IsFull(MaxHeap H){
if(H->Size==Capacity)return 0;
else return 1;
}
3,void Insert(MaxHeap H,ElementType item):将元素item插入最大堆H.
void Insert(MaxHeap H,ElementType item){
int i;
if(IsFull(H)){
printf("最大堆已满");
return;
}
i = ++H->Size;//i指向插入后堆中的最后一个元素,并对size加1
/*比较父结点,如果放到最大,就会有哨兵,
这个哨兵就是最大的,让他不会在比较了。如果不用哨兵,就要加一个&&i>1*/
for(;H->Elements[i/2]<item;i/2)
H->Elements[i]=H-Elements[i/2];//向下过滤
H->Elements[i]=item;//插入item
}
4,Boolean IsEmpty(MaxHeap H):判断最大堆H是否为空。
Boolean IsEmpty(MaxHeap H){
if(H->Size==0) return 0;
else return 1;
}
4,ElementType DeleteMax(MaxHeap H):返回H中最大元素(高优先级)
ElementType DeleteMax(MaxHeap H){
int Parent,Child;
ElementType MaxItem,temp;
if(IsEmpty(H)){
printf("最大堆为空");
return;
}
MaxItem = H->Elements[1];//取出结点
//用最大堆中的一个元素从根结点向上过滤下层节点,调整
temp = H->Elements[H->Size--];
//判断有没有左右孩子
for(Parent = 1;Parent*2 <= H->Size;Parent=Child){
Child=Parent*2;
//判断有没有右孩子,并找左右孩子中大的
if((Child!=Size) && (H->Elements[Child] < H->Elements[Child+1]))
Child++;
if(temp >= H->Elements[Child]) break;
else H->Elements[Parent] = H->Elements[Child];//将大孩子拉上来,并进入下一层,
}
H->Elements[Parent] = temp;
return MaxItem;
}
最大堆的建立
- 通过插入操作:一个一个的插入。其时间复杂度为O(N log N)
- 在线性时间复杂度下建立最大堆。其时间复杂性为O(n)
2.1将N个元素按输入顺序储存,先满足完全二叉树的结构特性
2.2调整个结点位置,以满足最大堆的有序性
所以在排序中会有一种堆排序方法。