zoukankan      html  css  js  c++  java
  • 【算法导论】第6章堆排序及利用堆建立最小优先级队列

    1、堆排序

    1.1 堆排序简介

      堆数据结构是一种数组对象,它可以被视为一棵完全二叉树,树中每个节点与数组A中存放该结点值的那个元素对应。树根为A[1],给定了某个结点的下标i,其父节点PARENT(i),左儿子节点LEFT(i)和右儿子结点RIGHT(i)的下标可以简单的计算出来:PARENT(i):不大于i/2的最大整数,LEFT(i):2i;RIGHT(i):2i+1;

      堆排序主要分成三个重要步骤:

      (1)利用MAX-HEAPIFY来保持堆的性质:输入为数组A和下标i。当其被调用时,我们假定以LEFT(i)和RIGHT(i)为根的两棵二叉树都是最大堆,但这时A[i]可能小于其子女,这就违反了最大堆性质。MAX-HEAPIFY让A[i]在最大堆中“下降”,使以i为根的子树成为最大堆。

      (2)BUILD-MAX-HEAP(A)建堆:自底向上的用MAX-HEAPIFY来将一个数组A[1...n]变成一个最大堆。子数组A[n/2+1...n]中的元素都是树中的叶子,因此每个都可以看做只含一个元素的堆。建堆过程对树中的每一个其他结点都调用一次MAX-HEAPIFY。

      (3)HEAPSORT(A):利用(2)已经将数组A造成一个最大堆。因为数组中最大元素在根A[1],则可以通过把它与A[n]互换来达到最终正确的位置。现在,如果从堆中去掉结点n(通过减小A的大小),可以很容易的将A[1...n-1]建成最大堆。原来的根的子女仍是最大堆,而新的根元素可能违背了最大堆性质,这时调用MAX-HEAPIFY(A,1)就可以保持这一性质,在A[1...(n-1)]中构造出最大堆。

    1.2、堆排序具体实现代码:

    View Code
     1 #include<stdio.h>
     2 void max_heapify(int *p,int i,int n)//保持堆的性质
     3 {
     4     int l,r,largest,temp;
     5     l=2*i;
     6     r=2*i+1;
     7     if((l<=n) && (*(p+l) > *(p+i)))
     8         largest=l;
     9     else largest=i;
    10     if((r<=n) && (*(p+r) > *(p+largest)))
    11         largest =r;
    12     if(largest!=i)
    13     {
    14         temp=*(p+i);
    15         *(p+i)=*(p+largest);
    16         *(p+largest)=temp;
    17         max_heapify(p,largest,n);
    18     }
    19 }
    20 void build_max_heap(int *p,int n)//建立大顶堆
    21 {
    22     int i;
    23     for(i=n/2;i>0;i--)
    24         max_heapify(p,i,n);
    25 }
    26 
    27 void heapsort(int *p,int n)//堆排序
    28 {
    29     int i,temp;
    30     build_max_heap(p,n);
    31     for(i=n;i>=1;i--)
    32     {
    33         temp=*(p+1);
    34         *(p+1)=*(p+i);
    35         *(p+i)=temp;
    36         printf("%d  ",temp);
    37         n--;
    38         max_heapify(p,1,n);
    39     }
    40 }
    41 int main()
    42 {
    43     int n=10;
    44     int a[11]={0,16,14,10,8,7,9,3,2,4,1};
    45     printf("排序结果为:\n");
    46     heapsort(a,n);
    47     return 0;
    48 }

      堆排序算法的时间复杂度为O(nlgn);;

    2 利用堆建立最小优先级队列

      优先级队列是一种用来维护由一组元素构成的集合S的数据结构,这一组元素中的每一个都有一个关键字key,一个最小优先级队列支持一下操作

    (1)heap_insert(S,x):把元素x插入到集合S。

    (2)heap_minimun(S):返回S中具有最大关键字的元素。

    (3)heap_extract_min(S):去掉并返回S中的具有最小关键字的元素。

    (4)heap_decrease_key(S,x,k)将元素x的关键字减小到k,这里k不能大于x的原来的关键字值。

      具体实现代码如下:

    View Code
      1 /*----------------------------------------------
      2  *name:用最小堆实现最小优先级队列
      3  *data:2012-7-3
      4  *author:lp
      5  *---------------------------------------------*/
      6 #include<stdio.h>
      7 #include<limits.h>
      8 #define maxsize 20//最大节点数
      9 int realsize=10;//实际初始时节点数
     10 int parent(int i)//父节点
     11 {
     12     return(i/2);
     13 }
     14 int left(int i)//左子节点
     15 {
     16     return(2*i);
     17 }
     18 int right(int i)//右子节点
     19 {
     20     return(2*i+1);
     21 }
     22 void min_heapify(int p[],int i)//保持堆的性质
     23  {
     24      int l,r,little,temp;
     25      l=2*i;
     26      r=2*i+1;
     27      if(l<=realsize && p[l]<p[i])
     28          little=l;
     29      else little=i;
     30      if(r<=realsize && p[r]<p[little])
     31          little =r;
     32      if(little!=i)
     33      {
     34          temp=p[i];
     35          p[i]=p[little];
     36          p[little]=temp;
     37          min_heapify(p,little);
     38      }
     39  }
     40 void build_min_heap(int p[])//建立大顶堆
     41 {
     42      int i;
     43      for(i=realsize/2;i>0;i--)
     44          min_heapify(p,i);
     45 }
     46 int heap_minimum(int p[])//返回堆中最大值
     47 {
     48      return(p[1]);
     49 }
     50 int heap_extract_min(int p[])//去掉并返回堆中的具有最大关键字的元素
     51 {
     52      int min;
     53      if(realsize<1)
     54      {
     55          printf("堆下溢出\n");
     56          return(-1);
     57      }
     58      min=p[1];
     59      p[1]=p[realsize-1];
     60      realsize--;
     61      min_heapify(p,1);
     62      return(min);
     63 }
     64 int heap_decrease_key(int p[],int i,int key)//将元素i的关键字的值增加到key,这里key不能小于原来的值
     65 {
     66     int temp;
     67      if(key>p[i])
     68      {
     69          printf("key的值太大\n");
     70          return(-1);
     71      }
     72      p[i]=key;
     73 
     74      while(i>1 && p[parent(i)]>p[i])
     75      {
     76          temp=p[i];
     77          p[i]=p[parent(i)];
     78          p[parent(i)]=temp;
     79          i=parent(i);
     80      }
     81      return(0);         
     82  }
     83 void heap_insert(int p[],int key)//将关键字值为key的值插入到堆中
     84 {
     85      realsize++;
     86      p[realsize]=INT_MAX;
     87      heap_decrease_key(p,realsize,key);
     88 }
     89 void heap_print(int p[])//打印堆
     90 {
     91     int i;
     92     for(i=1;i<realsize+1;i++)
     93         printf("%d  ",p[i]);
     94     printf("\n");
     95 }
     96 
     97  void main()
     98  {
     99      int i,key;
    100      int a[maxsize+1]={0,4,1,3,2,16,9,10,14,8,7};
    101      printf("建堆的数据为:\n");
    102          for(i=1;i<realsize+1;i++)
    103              printf("%d  ",a[i]);
    104      printf("\n");
    105      printf("新建成的堆为:\n");
    106      build_min_heap(a);
    107      heap_print(a);
    108 
    109      printf("堆中的最大元素为:\n%d\n",heap_minimum(a));
    110      //printf("堆中取出最大元素后为:\n");
    111      //heap_extract_max(a);
    112      //heap_print(a);
    113      printf("输入要插入堆的元素:\n");
    114      scanf("%d",&key);
    115      heap_insert(a,key);
    116      printf("堆中插入元素%d后为:\n",key);
    117      heap_print(a);
    118      printf("请输入要减小的元素及其要减小的值:\n");
    119      scanf("%d,%d",&i,&key);
    120      printf("元素减小之后为:\n");
    121      heap_decrease_key(a,i,key);
    122      heap_print(a);
    123  }

    3 参考资料:

    (1)算法导论

    (2)数据结构

  • 相关阅读:
    syslog+rsyslog+logstash+elasticsearch+kibana搭建日志收集
    行为型模式(一)
    spring cloud Sleuth
    Java面试题(基础)
    Java笔试题
    Idea创建SpringBoot项目整合Hibernate
    Java中遍历Map的四种方式
    SQL面试题
    Linux入门
    Spring Boot AOP Demo
  • 原文地址:https://www.cnblogs.com/lpshou/p/2550720.html
Copyright © 2011-2022 走看看