一、实验名称:Array Implementation of min-Heaps
二、实验目的:
4. 熟练掌握最小堆的数据结构,结构的特点;
5. 能够实现最小堆的基本操作:如构造,插入,删除,初始化,回收内存等
三、实验内容:
A complete min-heap is a min-heap with the structure of a complete binary tree which can be stored using an array.
- Determine the array structures for a complete min-heap(以数组形式表示的树结构)
- Input a linear list of 20 random numbers, building a complete min-heap to store the numbers
- Implement POP and PUSH operations for the min-heaps.
四. 算法实现:
通过在堆的末尾添加或删除,插入和删除操作都首先修改堆以使其符合shape属性。然后,通过向上或向下遍历堆来恢复堆属性。两种操作都需要O(log n)时间。
1.插入
要将元素添加到堆,我们可以执行以下算法:
将元素添加到堆的最底层开放空间的最底层。
将添加的元素与其父元素进行比较;如果顺序正确,请停止。
如果不是,则将元素与其父元素交换并返回上一步。
步骤2和3通过比较节点并可能与其父节点交换节点来恢复堆属性,这些步骤称为up-heap操作。
所需的操作数仅取决于新元素必须满足堆属性的级别数。因此,插入操作的最坏情况时间复杂度为O(log n)。对于随机堆和重复插入,插入操作的平均情况复杂度为O(1)。
2.弹出
从堆中删除根的过程(有效地提取max-heap中的最大元素或min-heap中的最小元素),同时保留heap属性:
用最后一级的最后一个元素替换堆的根。
将新的根与其子代进行比较;如果顺序正确,请停止。
如果不是,则将元素与其子元素之一交换并返回上一步。(将其较小的子项换成最小堆,将其较大的子项换成最大堆。)
步骤2和3通过将节点与子节点之一进行比较并可能与其交换来恢复堆属性,这些步骤称为下降堆操作
3.建立堆
从最低级别开始向上移动,像删除算法一样向下筛选每个子树的根,直到恢复堆属性。
四. 程序清单(较为详细的注释):
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MaxSize 100
typedef struct Hnode* MinHeap;
struct Hnode{
int* data;
int size;
int Capacity;
};
int getRandomNum(){
int RandomNum;
RandomNum=rand();
return RandomNum;
}
/*Filter down and find the proper position of the node on the premise that all subtrees are the smallest heap.
The tree with this node as the root node is a smallest heap*/
void FixDown(MinHeap h,int index){
int parent;
int child;
int temp=h->data[index];
for(parent=index;parent*2<=h->size;parent=child){
child=parent*2;
if(child+1<=h->size&&h->data[child+1]<h->data[child])
child++;
if(h->data[child]<temp){
h->data[parent]=h->data[child];
}
else break;
}
h->data[parent]=temp;
}
/*The idea of recursion is adopted to establish the minimum heap from bottom to top, which ensures
that the subtrees currently established are all the smallest heaps.*/
void BuildMinHeap(MinHeap h){
int i;
for(i=h->size/2;i>=1;i--){
FixDown(h,i);
}
}
//Determine whether the MinHeap is empty
int Empty(MinHeap h){
return h->size==0;
}
//Return and delete the minimum value of the minimum heap (that is, the head node), and keep the tree as the minimum heap
/*Move the last node to the head node, and size--,
Because the subtrees are all the smallest heap at this time, filtering directly
down can ensure that the tree is still the smallest heap*/
int PopMinHeap(MinHeap h){
if(Empty(h)){
printf("The minimum heap is empty, and the popped -11111 is an invalid value\n");
return -11111;
}
int result=h->data[1];
h->data[1]=h->data[(h->size)--];
//向下过滤
FixDown(h,1);
return result;
}
/*Insert node, keep minimum heap*/
void PushMinHeap(MinHeap h,int val){
if(h->size==h->Capacity){
printf("The minimum heap is full and element insertion is invalid\n");
return;
}
h->data[++(h->size)]=val;
//向上过滤
int child=h->size;
int parent;
for(;child>1;child=parent){
parent=child/2;
if(h->data[parent]>val){
h->data[child]=h->data[parent];
}
else
{
break;
}
}
h->data[child]=val;
}
/*Request space for the MinHeap*/
MinHeap CreateMinHeap(int MinHeapSize){
MinHeap h=(MinHeap)malloc(sizeof(MinHeap));
h->data=(int*)malloc((MinHeapSize+1)*sizeof(int));
h->size=0;
h->Capacity=MinHeapSize;
return h;
}
/*Free up space for MinHeap*/
void CleanMinHeap(MinHeap h){
free(h->data);
free(h);
}
int main()
{
MinHeap h=CreateMinHeap(MaxSize);
//Construct the MinHeap with a random array of 20 numbers, and pop the MinHeap number in turn
printf("Construct the MinHeap with a random array of 20 numbers\n");
srand((unsigned)time(NULL));
int i=1;
printf("20 random numbers:\n");
for(;i<=20;i++){
h->data[i]=getRandomNum();
printf("%d ",h->data[i]);
h->size++;
}
printf("\n");
BuildMinHeap(h);
//After the minimum heap is established, pop the element
printf("After the minimum heap is established, pop the element:\n");
while(!Empty(h)){
printf("%d ",PopMinHeap(h));
}
printf("\n");
//Randomly insert 10 elements
int randNum;
printf("10 random numbers inserted in sequence:\n");
for(i=1;i<=10;i++){
randNum=getRandomNum();
printf("%d ",randNum);
PushMinHeap(h,randNum);
}
printf("\n");
//while the minimum heap is not empty, pop the element
printf("After the insertion, pop the element:\n");
while(!Empty(h)){
printf("%d ",PopMinHeap(h));
}
printf("\n");
CleanMinHeap(h);
return 0;
}
五、测试结果:
输入输出格式说明:
-
输入格式:
无 -
输出格式:
先输出20个随机数组的内容;
再输出数组构造的最小堆,依次弹出的内容;
再输出10个依次插入的随机;
再依次插入后的最小堆,依次弹出的内容; -
测试样例1:
输入:
输出:
Construct the MinHeap with a random array of 20 numbers 20 random numbers: 25934 30979 23498 31152 11647 2301 29550 22606 11334 6914 30615 28013 5979 11444 21228 3691 28332 32284 17894 14376 After the minimum heap is established, pop the element: 2301 3691 5979 6914 11334 11444 11647 14376 17894 21228 22606 23498 25934 28013 28332 29550 30615 30979 31152 32284 10 random numbers inserted in sequence: 16559 5286 28109 18979 2294 28525 14307 31967 23812 20665 After the insertion, pop the element: 2294 5286 14307 16559 18979 20665 23812 28109 28525 31967
-
测试样例2:
输入:
输出:
Construct the MinHeap with a random array of 20 numbers 20 random numbers: 26012 26797 26254 18847 29821 31007 5944 17888 14396 23200 27065 29070 13024 15340 29552 26589 16604 15737 29064 21912 After the minimum heap is established, pop the element: 5944 13024 14396 15340 15737 16604 17888 18847 21912 23200 26012 26254 26589 26797 27065 29064 29070 29552 29821 31007 10 random numbers inserted in sequence: 28387 16381 28017 23489 25085 31792 1424 1400 1499 18387 After the insertion, pop the element: 1400 1424 1499 16381 18387 23489 25085 28017 28387 31792
-
测试样例3:
输入:
输出:
Construct the MinHeap with a random array of 20 numbers 20 random numbers: 26058 13435 14208 28054 10385 20445 16751 9674 16182 2663 24995 29686 28056 17613 12562 7179 31608 11546 21926 23578 After the minimum heap is established, pop the element: 2663 7179 9674 10385 11546 12562 13435 14208 16182 16751 17613 20445 21926 23578 24995 26058 28054 28056 29686 31608 10 random numbers inserted in sequence: 24364 3738 8848 23389 151 22775 4832 2683 10328 8866 After the insertion, pop the element: 151 2683 3738 4832 8848 8866 10328 22775 23389 24364
-
测试样例4:
输入:
输出:
Construct the MinHeap with a random array of 20 numbers 20 random numbers: 26133 31272 31868 24454 18244 12456 22801 7883 2733 25098 21593 30699 12962 4962 31462 12739 25829 9342 31264 7589 After the minimum heap is established, pop the element: 2733 4962 7589 7883 9342 12456 12739 12962 18244 21593 22801 24454 25098 25829 26133 30699 31264 31272 31462 31868 10 random numbers inserted in sequence: 24777 32119 26509 20885 8339 14983 3408 21176 10790 18970 After the insertion, pop the element: 3408 8339 10790 14983 18970 20885 21176 24777 26509 32119
六、算法分析:
最小堆的插入和删除操作都是在树的结构基础上建立的,每次的时间复杂度为O(log n)时间,
若算法需要n次插入,每次删除,则插入和删除总共的时间复杂度为O((n+m)log n);
构造有n个节点的最小堆,同理其时间复杂度为O(nlog n);
算法的空间复杂度为最小堆数据结构(以数组形式表示的树结构)的内存空间