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 

     

     

     

    一颗平常心,踏踏实实,平静对待一切
  • 相关阅读:
    google搜索的使用小窍门
    openssl的使用
    vi vim 的使用
    nfs
    setfacl命令的使用
    JAVA记录
    Yapi基本使用
    Yapi部署
    Mysql问题记录
    Spring boot+MYSQL多数据源
  • 原文地址:https://www.cnblogs.com/hanyuan/p/2693516.html
Copyright © 2011-2022 走看看