堆(優先佇列,最大堆的基本操作,堆的例題)
阿新 • • 發佈:2019-02-10
1、堆(優先佇列):是一種特殊的“佇列”,取出元素的順序是
依照元素的優先權(關鍵字)大小,而不是元素進入佇列的先後順序。
2、堆的特性:
(1)結構性:用陣列表示的完全二叉樹(堆一定是完全二叉樹);
(2)有序性:任一結點的關鍵字是其子樹所有結點的最大值(或最小值)
“最大堆(MaxHeap)”,也稱“大頂堆”:任一結點的關鍵字是其子樹所有結點的最大值。
“最小堆(MinHeap)”,也稱“小頂堆” :任一結點的關鍵字是其子樹所有結點的最小值。
3、最大堆的基本操作:
!!!這裡主要講解最大堆,最小堆類似。這裡的所有操作都是建立在以下標為1開始儲存元素,下標為0的地方沒有儲存真實的元素
(1)、建立一個空的堆
#define MAXdata 10000
typedef struct Heap{
int *a;
int size;//當前元素個數
int maxsize;//最大儲存量
}heap;
heap* creat_maxheap(int maxdata,heap* h)//建立一個最大容量為maxdata的空堆
{
h->a = (int *)malloc((maxdata + 1)*sizeof(int));
//因為堆中元素是從下標為1的地方開始存放的,所以maxsize+1
h->maxsize = maxdata;
h->size = 0 ;
h->a[0] = MAXdata;//定義哨兵為大於堆中所有元素的值
return h;
}
(2)、判斷一個堆是否滿
int Isfull_maxheap(heap* h)//判斷最大堆是否滿
{
return h->maxsize == h->size;//若滿則返回1,未滿則返回0
}
(3)、插入元素
void insert_maxheap(int x,heap* h)//向堆中插入一個元素
{
int i;
if(Isfull_maxheap(h))
{
printf("最大堆已滿!\n");
return ;
}
i = ++h->size;//i指向插入後堆中的最後一個元素的位置
for ( ; h->a[i/2] < x; i/=2 )
h->a[i] = h->a[i/2]; //上濾X
h->a[i] = x; //將X插入
return ;
}
(4)、判斷堆是否為空
int Isempty_maxheap(heap* h)
{
return h->Size == 0;//若空則返回1,不空則返回0
}
(5)、刪除堆中最大的元素並返回
int deletemax_heap(heap* h)
// 從最大堆h中取出鍵值為最大的元素,並刪除一個結點
{
int parent,child;
int maxdata,temp;
if(Isempty_maxheap(h))
{
printf("最大堆以為空!\n");
return 0;
}
maxdata = h->a[1];//取出根結點最大值
//用最大堆中最後一個元素從根結點開始向上過濾下層結點
temp = h->a[h->size--];
//最開始用最後一個結點代替根結點,再交換順序使之成為堆
for(parent = 1;parent*2 <= h->size;parent = child)
{
child = parent*2;
if((child != h->size) && (h->a[child] < h->a[child+1]))
{
child++;//child指向左右子結點的較大者
}
if(temp >= h->a[child])
break;
else
h->a[parent] = h->a[child];//移動temp元素到下一層
}
h->a[parent] = temp;
return maxdata;
}
(6)、簡單例題:將陣列存放為最大堆,再遍歷輸出,刪除最大元素後再遍歷刪除後的結果
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define MAXdata 10000
typedef struct Heap{
int *a;
int size;//當前元素個數
int maxsize;//最大儲存量
}heap;
heap* creat_maxheap(int maxdata,heap* h)//建立一個最大容量為maxdata的空堆
{
h->a = (int *)malloc((maxdata + 1)*sizeof(int));
//因為堆中元素是從下標為1的地方開始存放的,所以maxsize+1
h->maxsize = maxdata;
h->size = 0 ;
h->a[0] = MAXdata;//定義哨兵為大於堆中所有元素的值
return h;
}
int Isfull_maxheap(heap* h)//判斷最大堆是否滿
{
return h->maxsize == h->size;//若滿則返回1,未滿則返回0
}
void insert_maxheap(int x,heap* h)//向堆中插入一個元素
{
int i;
if(Isfull_maxheap(h))
{
printf("最大堆已滿!\n");
return ;
}
i = ++h->size;//i指向插入後堆中的最後一個元素的位置
for ( ; h->a[i/2] < x; i/=2 )
h->a[i] = h->a[i/2]; //上濾X
h->a[i] = x; //將X插入
return ;
}
int Isempty_maxheap(heap* h)
{
return h->size == 0;//若空則返回1,不空則返回0
}
int deletemax_heap(heap* h)
// 從最大堆h中取出鍵值為最大的元素,並刪除一個結點
{
int parent,child;
int maxdata,temp;
if(Isempty_maxheap(h))
{
printf("最大堆以為空!\n");
return 0;
}
maxdata = h->a[1];//取出根結點最大值
//用最大堆中最後一個元素從根結點開始向上過濾下層結點
temp = h->a[h->size--];
//最開始用最後一個結點代替根結點,再交換順序使之成為堆
for(parent = 1;parent*2 <= h->size;parent = child)
{
child = parent*2;
if((child != h->size) && (h->a[child] < h->a[child+1]))
{
child++;//child指向左右子結點的較大者
}
if(temp >= h->a[child])
break;
else
h->a[parent] = h->a[child];//移動temp元素到下一層
}
h->a[parent] = temp;
return maxdata;
}
void print_maxheap(heap* h)
{
int i;
for (i=1; i<h->size+1; i++)
printf("%d ", h->a[i]);
}
int main()
{
int a[5] = {50,10,70,90,30};
int i,len = 5;
heap* h = (heap*)malloc(sizeof(heap));
h = creat_maxheap(len,h);
printf("依次新增:");
for(i = 0;i<len;i++)
{
printf("%d ",a[i]);
insert_maxheap(a[i],h);
}
printf("\n最大堆:");
print_maxheap(h);
printf("\n刪除的元素:%d",deletemax_heap(h));
printf("\n刪除元素後的最大推:");
print_maxheap(h);
}
執行結果: