#include <stdio.h> #include <stdlib.h> /*由于不会动态获得当前堆的元素数量heap_size,所以暂时用传参的方法,但是当多次运行后发现 为了防止错误应该把heap_size设置为全局变量,主函数初始化后,让它被各个函数操作过程中动态 改变也是可以的。 */ int heap_maximum(char *a)//实现MAXIMUM(S),返回S中具有最大关键字的元素 { return a[1]; } int left(int i)//返回左孩子位置 { return 2*i; } int right(int i)//返回右孩子位置 { return 2*i+1; } int parent(int i)//返回父节点的位置 { return i/2; } void max_heapify(int *a,int heap_size,int i)//保持堆性质,使以i为根的子树成为最大堆 ,heap_size当前堆中元素数量 { //假设左右孩子已经分别为最大堆 int l,r,largest;//l,r分别为左右孩子的位置,largest用于临时存放当前节点与左右孩子中最大的节点的位置 int temp; l=left(i); r=right(i); if(l<=heap_size&&a[l]>a[i])//当做孩子大于父节点时,左孩子设为最大,否则父节点最大 largest=l; else largest=i; if(r<=heap_size&&a[r]>a[largest])//继续判断,当右孩子大于最大时,右孩子设为最大,否则刚才的最大不变 largest=r; if(largest!=i)//如果largest变化了,则通过交换使当前最大节点为父节点 { temp=a[i]; a[i]=a[largest]; a[largest]=temp; max_heapify(a,heap_size,largest);//继续递归保持交换后的某一孩子的堆的性质。 } } void build_max_heap(int *a,int heap_size)//建立最大堆 { int i; //从第一个叶子的前一个节点开始循环维护最大堆,由于这个节点后的都是叶子,单一元素可以当做最大堆。 //这个叶子往前循环,保证每个处理后的节点的子节点都已经是最大堆,一直到根节点。 for(i=heap_size/2;i>=1;i--) max_heapify(a,heap_size,i); } int heap_extract_max(int *a,int heap_size)//实现EXTRACT-MAX(S)操作,去掉并返回S中具有最大关键字的元素 { //heap_size为最大堆a中当前的元素数量 int max,i; if(heap_size<1) { printf("heap underflow!\n"); return -1; } max=a[1];//将当前堆顶元素赋给max,即最大值 a[1]=a[heap_size];//将当前堆最后一个元素赋给堆顶,然后进行维护最大堆的操作 heap_size--; max_heapify(a,heap_size,1);//从堆顶开始重新维护最大堆 return max; } void heap_increase_key(int *a,int i,int key)//实现INCREASE-KEY(S,x,k),将元素x的关键字值key { int temp; int fa; if (key<a[i])//新的key必须大于原来的,才能执行位置 上升的操作 { printf("new key is smaller than current key!\n"); // return -1; } a[i]=key; //当新key比父节点大时,与父节点交换,父节点变成子节点后也能保证最大堆。直到比父节点小为止。 while(i>1&&a[parent(i)]<a[i]) { temp=a[i]; a[i]=a[parent(i)]; a[parent(i)]=temp; i=parent(i); } } void max_heap_insert(int *a,int key,int heap_size) { //实现INSERT(S,X)操作,将元素x插入到集合S中。通过先加入一个关键字值为-00的叶节点扩展最大堆, //然后调用heap_increase_key设置新节点的正确的值 //heap_size为当前堆中的元素个数 heap_size=heap_size+1; a[heap_size]=0;//以0代表-00 heap_increase_key(a,heap_size,key); } int main(int argc, char *argv[]) { int a[1000]; a[0]=0; int num; int i,heap_size; printf("请输入元素的数量:"); scanf("%d",&heap_size); printf("\n请依次输入%d个元素,空格结束:\n",heap_size); for(i=1;i<=heap_size;i++) scanf("%d",&a[i]); printf("------------------------\n"); printf("建立最大堆以后\n"); build_max_heap(a,heap_size); for(i=1;i<=heap_size;i++) printf("%d ",a[i]); printf("\n------------------------\n"); printf("请插入一个新的元素:\n"); scanf("%d",&num); max_heap_insert(a,num,heap_size); for(i=1;i<=heap_size+1;i++) printf("%d ",a[i]); printf("逐个打印队列最大值\n"); for(i=heap_size+1;i>=1;i--)//逐步调用heap_extract_max算法,打印最大值 printf("%d ",heap_extract_max(a,i)); system("PAUSE"); return 0; }