boj_67_堆操作

题目描述:

   求中位数。

 

解题思路:

   用两个堆来记录中间的两位数。一个大根堆,一个小根堆。变动堆的最后一个数采用倒调整操作(这里代码可以改进成倒调序,另写一个函数效率会更高些)。变动根值采用正调整操作。本题对时间要求较严,时间复杂度不能超过nlogn。

 

代码:

#include <stdio.h>
#include <stdlib.h>
#define N 100001
#define MAX 1
#define MIN 0

double array[N];
double left_heap[N], right_heap[N];
int lcnt, rcnt;

void heap_adjust(double a[N], int cnt, int f)
{
   int l = 2*cnt, r=2*cnt+1, largest = cnt;
   double tmp;

   if( f==MAX )
   {
      if(l<=lcnt && a[l] > a[cnt])
         largest = l;
      if(r<=lcnt && a[r] > a[largest])
         largest = r;
   }
   else
   {
      if(l<=rcnt && a[l] < a[cnt])
         largest = l;
      if(r<=rcnt && a[r] < a[largest])
         largest = r;     
   }
  // printf("f=%d, largest=%d.\n",f,largest);
   if(largest != cnt)
   {
      tmp = a[largest];
      a[largest] = a[cnt];
      a[cnt] = tmp;
      heap_adjust(a, largest, f);
   }
}

main()
{
   int n, count, op, i;
   double num;
  
   while(scanf("%d",&n)!=EOF)
   {
       count = 0;
       lcnt = 0;
       rcnt = 0;
       while(n>0)
       {
          n--;
          scanf("%d",&op);
          if(1 == op)
          {
             count ++;
             scanf("%lf",&num);
            
             if(1 == count)
                left_heap[++lcnt] = num;
             else if(2 == count)
             {
                if(num >= left_heap[lcnt])
                   right_heap[++rcnt] = num;
                else
                {
                   right_heap[++rcnt] = left_heap[lcnt];
                   left_heap[lcnt] = num;
                }
             }
             else
             {
                 if(num>left_heap[1] && rcnt-lcnt < 1) //加入小根堆-右
                 {
                    rcnt ++;
                    right_heap[rcnt] = num;
                    for(i=rcnt/2;i>=1;i=i/2)
                       heap_adjust(right_heap, i, MIN);
                 }
                 else if(num<right_heap[1] && lcnt-rcnt < 1)//加入大根堆-左
                 {
                    lcnt ++;
                    left_heap[lcnt] = num;
                    for(i=lcnt/2;i>=1;i=i/2)
                       heap_adjust(left_heap, i, MAX);
                 }
                 else if(num>=right_heap[1] && rcnt-lcnt == 1) //把小根堆头挪到大根堆,把num放入小根堆
                 {
                    lcnt++;
                    left_heap[lcnt] = right_heap[1];
                    for(i=lcnt/2;i>=1;i=i/2)
                       heap_adjust(left_heap,i, MAX);
                    right_heap[1] = num;
                    heap_adjust(right_heap,1, MIN);
                 }
                 else
                 {
                    rcnt++;
                    right_heap[rcnt] = left_heap[1];
                    for(i=rcnt/2;i>=1;i=i/2)
                       heap_adjust(right_heap, i, MIN);
                    left_heap[1] = num;
                    heap_adjust(left_heap, 1, MAX);
                 }
             }
//             //print heap
//             printf("left heap:\n");
//             for(i=1;i<=lcnt;i++)
//                printf("%.1f\t",left_heap[i]);
//             printf("\n");
//             printf("right_heap:\n");
//             for(i=1;i<=rcnt;i++)
//                printf("%.1f\t",right_heap[i]);
//             printf("\n");

          }
          else
          {
             if( count%2 ==0 )
                printf("%.1f\n",(left_heap[1]+right_heap[1])/2);
             else
             {
                if(lcnt > rcnt)
                   printf("%.1f\n",left_heap[1]);
                else
                   printf("%.1f\n",right_heap[1]);
             }
          }
       }
   }
   system("pause");
   return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值