算法入门--最大堆实现优先队列

#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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值