zoukankan      html  css  js  c++  java
  • 堆和优先队列的应用

    什么是堆:

    堆的定义:n个元素的序列k={k0,k1,……,kn-1},当且仅满足条件
    (1)k>= k2i+1 和 k>= k2i+2      (2)k<= k2i+1 和 ki <= k2i+2

    (1)称为大根堆 (2)称为小根堆

    可以把堆看成完全二叉树。

     

    什么是优先队列:

    优先队列是一种常见的抽象数据类型,它与"队列"不同,不遵循"先进先出"原则,而遵循"最小元素先出"原则。

    优先队列的基本操作有三个:
    (1) 向优先队列里插入一个元素
    (2) 在优先队列找出最小元素
    (3) 删除优先队列中最小元素

    可以用堆来实现有限队列 

     

    优先队列的实现:

      1 #include "stdio.h"
      2 #include "stdlib.h"
      3 
      4 typedef int DATATYPE;
      5 
      6 /********************优先队列存储结构********************************/
      7 struct priorityQueue 
      8 {
      9     int MAXNUM; //存储结构长度
     10     int n; //实际元素个数
     11     DATATYPE * element;
     12 };
     13 typedef struct priorityQueue *PQ;
     14 
     15 /********************创建优先队列***********************************/
     16 PQ createPQ(int maxnum)
     17 {
     18     PQ pq = NULL;
     19     pq = (PQ) malloc(sizeof(struct priorityQueue));
     20     if(NULL != pq)
     21     {
     22         pq->element = malloc(sizeof(DATATYPE) * maxnum);
     23         if(pq->element != NULL)
     24         {
     25             pq->MAXNUM = maxnum;
     26             pq->n = 0;
     27         }
     28     }
     29     return pq;
     30 }
     31 
     32 /****************************判断优先队列是否为空****************************/
     33 int isEmpty_heap(PQ pq)
     34 {
     35     return pq->n == 0;
     36 }
     37 
     38 /**************************往优先队列中插入元素*******************************/
     39 void add_heap(PQ pq, DATATYPE x)
     40 {
     41     int i = -1; //标志元素最后要插入位置的下标
     42     if(pq->n >= pq->MAXNUM) //如果队列已满,无法插入
     43     {
     44         printf("PriorityQueue is full");
     45         return;
     46     }
     47     //寻找插入的位置,pq->n是未有元素的空位
     48     for(i = pq->n; i > 0 && x < pq->element[(i-1)/2]; i = (i - 1)/2)
     49     {
     50         pq->element[i] = pq->element[(i-1)/2];
     51     }
     52     //插入元素
     53     pq->element[i] = x;
     54     pq->n++;
     55 }
     56 
     57 /*************************在三个元素中,找出最小元素的下标********************/
     58 int findMinIndex(PQ pq,int index1, int index2, int index3)
     59 {
     60     int min = 0;
     61     min = (pq->element[index1] < pq->element[index2])?index1:index2;
     62     min = (pq->element[min] < pq->element[index3])?min:index3;
     63     return min;
     64 }
     65 
     66 /*************************删除优先队列最小元素************************************/
     67 void removeMin_heap(PQ pq)
     68 {
     69     int endIndex,leftchild,rightchild,index,minIndex;
     70     if(isEmpty_heap(pq)) //如果为空队列,返回
     71         return;
     72     endIndex = --pq->n; //找到队列尾元素下标,并将首元素删除
     73 
     74     index = 0; //空位的下标,开始时在根节点处
     75     for(;index < endIndex;)
     76     {
     77         leftchild = index*2 + 1;
     78         rightchild = index*2 + 2;
     79         if(leftchild > endIndex || rightchild > endIndex)
     80         {
     81             pq->element[index] = pq->element[endIndex];
     82             break;
     83         }            
     84                 
     85         minIndex = findMinIndex(pq,endIndex,leftchild,rightchild);
     86         pq->element[index] = pq->element[minIndex];
     87         if(minIndex == endIndex)
     88             break;
     89         else if(minIndex == leftchild)
     90             index = leftchild;
     91         else if(minIndex == rightchild)
     92             index = rightchild;
     93     }
     94 }
     95 
     96 
     97 
     98 /***********************显示优先队列中元素的排列****************************/
     99 void show(PQ pq)
    100 {
    101     int i = 0;
    102     
    103     for(i = 0; i < pq->n; i++)
    104     {
    105         printf("%d, ",pq->element[i]);
    106     }
    107 
    108 }
    109 
    110 int main()
    111 {
    112     PQ pq = createPQ(6);
    113     add_heap(pq, 3);
    114     add_heap(pq, 2);
    115     add_heap(pq, 8);
    116     add_heap(pq, 4);
    117     add_heap(pq, 6);
    118     add_heap(pq, 10);
    119     
    120     show(pq);
    121     printf("\n");
    122     
    123     removeMin_heap(pq);
    124     show(pq);
    125     return 0;
    126 }

    删除优先队列的原理为:在最小节点被删除后,根节点形成一个空位,这时考虑能否把处在队中最后位置的节点填入这里。由于这样做可能破坏堆序性,所以选择这个元素与根的两个子节点中最小的节点填入,选择的结果可能使得原来的空位向叶节点方向传递。如此反复交换,最终到堆中最后节点小于等于空位的两个子节点时,将最后节点填入这个空位。

     

    利用堆,可以进行排序:

     1 /********************对元素进行排序*********************************/
     2 void sort(DATATYPE * data,int size)
     3 {
     4     int i; 
     5     PQ pq = createPQ(size);
     6 
     7     for(i = 0; i < size; i++)
     8     {
     9         add_heap(pq,data[i]);
    10     }
    11 
    12     for(i = 0; i < size; i++)
    13         printf("%d, ",removeMin_heap(pq));
    14 }

    测试:

     1 int main()
     2 {    
     3     int i = 0;
     4     int a[100];
     5     for(i = 99; i >= 0; i--)
     6         a[i] = i * 2 + 1;
     7 
     8 
     9     sort(a,100);
    10     return 0;
    11 }

     输出结果:

     

    数组长度的限制:

    栈里能声明的最大是1M 
    也就是char a[n]的大小不能大于1M 
    堆里的可以很大 
    也就是char * a; a=new   char   [n]的话a的大小可以达2G 

     

     

     

    一颗平常心,踏踏实实,平静对待一切
  • 相关阅读:
    【转】CUDA5/CentOS6.4
    【转】centos 6.4 samba 安装配置
    【转】Install MATLAB 2013a on CentOS 6.4 x64 with mode silent
    【转】Getting xrdp to work on CentOS 6.4
    【VLFeat】使用matlab版本计算HOG
    Unofficial Windows Binaries for Python Extension Packages
    March 06th, 2018 Week 10th Tuesday
    March 05th, 2018 Week 10th Monday
    March 04th, 2018 Week 10th Sunday
    March 03rd, 2018 Week 9th Saturday
  • 原文地址:https://www.cnblogs.com/hanyuan/p/2693516.html
Copyright © 2011-2022 走看看