zoukankan      html  css  js  c++  java
  • (二叉)堆操作

    堆操作

    实验目的

    (一)建堆:将数组A[1..n]变成一个最大堆。

    (二)堆排序:将一个堆中的元素按递减排序输出。

    (三)用插入方法建堆:堆大小从1到n每次插入一个元素到堆中,直到n个元素入堆。

    实验原理

    (二叉)堆是一个数组,它可以被看成一个近似的完全二叉树。树上的每一个结点对应数组中的一个元素。除了最底层外,该树是完全充满的,而且是从左向右填充。表示堆的数组A包括两个属性:A.length(通常)给出数组元素的个数,A.heap-size表示有多少个堆元素存储在该数组中。也就是说,虽然A[1..A.length]可能都存有数据,但是只有A[1..A.heap-size]中存放的是堆的有效元素,这个,0 <=A.heap-size <= A.length 。树的根节点是A[1]。

    二叉堆可以分为两种形式:最大堆和最小堆。在这两种堆中,结点的值都要满足堆的性质,但一些细节定义则有所差异。在最大堆中,最大堆性质是指除了根以外的所有结点i都要满足:A[PARENT(i)] >= A[i] ,也就是说,某个结点的值至多与其父结点一样大。因此,堆中的最大元素存放在根结点中;并且,在任一子树中,该子树所包含的所有结点的值都不大于该子树根节点的值。最小堆的组织方式正好相反:最小堆性质是指除了根以外的所有结点i都有A[PARENT(i)] <= A[i] ,最小堆中的最小元素存放在根结点中。

    实验过程

    (一)维护堆的性质

    MAX-HEAPIFY是用于维护最大堆性质的重要过程。它的输入为一个数组A和一个下标i。在调用MAX-HEAPIFY的时候,对于违背了最大堆的性质的A[i]使其在最大堆中“逐级下降”,从而使得以下标i为根结点的子树重新遵循最大堆的性质。

    MAX-HEAPIFY(A, i)

    1 l = LEFT(i)

    2 r = RIGHT(i)

    3 if l <= A.heap-size andA[l] > A[i]

    4     largest = l

    5 else largest = i

    6 if r <= A.heap-size andA[r] > A[largest]

    7     largest = r

    8 if largest != i

    9     exchange A[i] with A[largest]

    10    MAX-HEAPIFY(A, largest)

    (二)建堆

    我们可以用自底向上的方法利用过程MAX-HEAPIFY把一个大小为n = A.length的数组A[1..n]转换为最大堆。子数组A(|n/2|+1..n)中的元素都是树的叶节点。对每一个叶节点都调用MAX-HEAPIFY进行调整,从而满足最大堆的性质。

    BUILD-MAX-HEAP

    1 A.heap-size = A.length

    2 for i = |A.length/2| downto1

    3     MAX-HEAPIFY(A, i)

     

    (三)堆排序

    由于数组中的最大元素总是在根结点A[1]中,通过把它与A[n]进行互换,我们可以让该元素放到正确的位置。这个时候,我们从堆中去掉结点n(即通过减少A.heap-size的值来实现),剩余的节点中,原来根的孩子仍然是最大堆,而新的节点可能违背最大堆的性质,为了维护最大堆的性质,调用一次MAX-HEAPIFY(A, 1),从而在A[1..n-1]上构造一个新的最大堆。

    HEAPSORT(A)

    1 BUILD-MAX-HEAP(A)

    2 for i = A.length downto 2

    3     exchange A[1] with A[i]

    4     A.heap-size = A.heap-size - 1

    5     MAX-HEAPIFY(A, 1)

     

    (四)插入方法建堆

    MAX-HEAP-INSERT能够实现INSERT操作。它的输入是要被插入到最大堆A中的新元素的关键字。MAX-HEAP-INSERT首先通过增加一个关键字为-∞的叶节点来扩展最大堆,然后调用HEAP-INCREASE-KEY为新节点设置对应的关键字,同时保持最大堆的性质。

    MAX-HEAP-INSERT(A, key)

    1 A.heap-size = A.heap-size +1

    2 A[A.heap-size] = -∞

    3 HEAP-INCREASE-KEY(A,A.heap-size, key)

    HEAP-INCREASE-KEY(A, i, key)

    1 if key < A[i]

    2     error“new key is smaller than current key”

    3 A[i] = key

    4 while i > 1 and A[PARENT(i)]< A[i]

    5     exchange A[i] with A[PARENT(i)]

    6     i = PARENT(i)

     

    实验总结

    (一)将整个实验过程完成后,深入理解了二叉堆的性质。堆的优点:在大多数计算机上,在实现PARENT(i),LEFT(i),RIGHT(i)过程中,可以通过较少的指令(左移,右移)进行计算。

    (二)在建堆的过程中,有一个巧妙的地方:就是对于A[|A.length/2|..1]的叶节点进行最大堆的性质维护,而不是遍历整个堆。

    (三)堆排序的实际应用场景:基于最大堆实现最大优先队列(记录将要执行的各个作业以及它们之间的相对优先级),从而应用到计算机系统的作业调度中。

    附录(代码)

    (一)建堆

     1 #include <stdio.h>
     2 
     3 #include <stdlib.h>
     4 
     5  
     6 
     7 #define a_length 10
     8 
     9  
    10 
    11 int a_heap_size;
    12 
    13  
    14 
    15 void max_heapify(int a[], int i){
    16 
    17     intl,r,largest;
    18 
    19     int change;
    20 
    21     l = 2 * i +1;
    22 
    23     r = 2 * i +2;
    24 
    25     if(l <=a_heap_size-1 && a[l] > a[i])
    26 
    27        largest =l;
    28 
    29     else largest= i;
    30 
    31     if(r <=a_heap_size-1 && a[r] > a[largest])
    32 
    33        largest =r;
    34 
    35     if(largest !=i){
    36 
    37        change     = a[i];
    38 
    39        a[i]       = a[largest];
    40 
    41        a[largest]= change;
    42 
    43        max_heapify(a,largest);
    44 
    45     }     
    46 
    47 }
    48 
    49  
    50 
    51 void build_max_heap(int a[]){
    52 
    53     int i;
    54 
    55     a_heap_size =a_length;
    56 
    57     for(i =a_length/2 - 1; i >= 0; i--)
    58 
    59        max_heapify(a,i);
    60 
    61 }
    62 
    63  
    64 
    65 int main(){
    66 
    67     inta[a_length] = {4,1,3,2,16,9,10,14,8,7};
    68 
    69     int i;
    70 
    71  
    72 
    73     printf("origin_heapa[]=");
    74 
    75     for(i = 0; i< 10; i++)
    76 
    77        printf("%d  ",a[i]);
    78 
    79     printf("
    ");
    80 
    81    
    82 
    83     build_max_heap(a);
    84 
    85  
    86 
    87     printf("  max_heap a[]=");
    88 
    89     for(i = 0; i< 10; i++)
    90 
    91        printf("%d  ",a[i]);
    92 
    93     printf("
    ");
    94 
    95 }

    (二)堆排序

      1 #include <stdio.h>
      2 
      3 #include <stdlib.h>
      4 
      5  
      6 
      7 #define a_length 10
      8 
      9  
     10 
     11 int a_heap_size;
     12 
     13  
     14 
     15 void max_heapify(int a[], int i){
     16 
     17     intl,r,largest;
     18 
     19     int change;
     20 
     21     l = 2 * i +1;
     22 
     23     r = 2 * i +2;
     24 
     25     if(l <=a_heap_size-1 && a[l] > a[i])
     26 
     27        largest =l;
     28 
     29     else largest= i;
     30 
     31     if(r <=a_heap_size-1 && a[r] > a[largest])
     32 
     33        largest =r;
     34 
     35     if(largest !=i){
     36 
     37        change     = a[i];
     38 
     39        a[i]       = a[largest];
     40 
     41        a[largest]= change;
     42 
     43        max_heapify(a,largest);
     44 
     45     }     
     46 
     47 }
     48 
     49  
     50 
     51 void build_max_heap(int a[]){
     52 
     53     int i,j;
     54 
     55     a_heap_size =a_length;
     56 
     57     for(i =a_length/2 - 1; i >= 0; i--)
     58 
     59        max_heapify(a,i);
     60 
     61 }
     62 
     63  
     64 
     65 void heapsort(int a[]){
     66 
     67     inti,exchange;
     68 
     69     int j;
     70 
     71     for(i =a_length-1; i >= 1; i--){
     72 
     73        exchange    = a[0];
     74 
     75        a[0]        = a[i];
     76 
     77        a[i]        = exchange;
     78 
     79        a_heap_size= a_heap_size - 1;
     80 
     81       
     82 
     83        max_heapify(a,0);
     84 
     85  
     86 
     87        printf("
    a_heap_size= %d   i = %d  
    ",a_heap_size,i);
     88 
     89        for(j = 0;j < 10; j++)
     90 
     91            printf("%d  ",a[j]);
     92 
     93        printf("
    ");
     94 
     95  
     96 
     97     }
     98 
     99 }
    100 
    101  
    102 
    103  
    104 
    105 int main(){
    106 
    107     int a[a_length] = {4,1,3,2,16,9,10,14,8,7};
    108 
    109     int i;
    110 
    111  
    112 
    113     printf("origin_heapa[]=");
    114 
    115     for(i = 0; i< 10; i++)
    116 
    117        printf("%d  ",a[i]);
    118 
    119     printf("
    ");
    120 
    121    
    122 
    123     build_max_heap(a);
    124 
    125     printf("  max_heap a[]=");
    126 
    127     for(i = 0; i< 10; i++)
    128 
    129        printf("%d  ",a[i]);
    130 
    131     printf("
    ");
    132 
    133  
    134 
    135     heapsort(a);
    136 
    137     printf("heap_sort a[]=");
    138 
    139     for(i = 0; i< 10; i++)
    140 
    141        printf("%d  ",a[i]);
    142 
    143     printf("
    ");
    144 
    145 }

    (三)用插入法建堆

      1 #include <stdio.h>
      2 
      3 #include <stdlib.h>
      4 
      5  
      6 
      7 #define a_length 10
      8 
      9 int a_heap_size;
     10 
     11 int insert_length;
     12 
     13  
     14 
     15 int parent(int i){
     16 
     17     int a;
     18 
     19     a = (i-1)/2;
     20 
     21     return a;
     22 
     23 }
     24 
     25  
     26 
     27 void heap_increase_key(int a[], int i, int key){
     28 
     29     int exchange;
     30 
     31     int a_end;
     32 
     33     //if(key <a[i-1])
     34 
     35     //  printf("new key is smaller than currentkey!
    ");
     36 
     37     a_end      = i - 1;
     38 
     39     a[a_end]   = key;
     40 
     41    
     42 
     43     while(a_end> 0 && a[parent(a_end)] < a[a_end]){
     44 
     45        exchange         = a[a_end];
     46 
     47        a[a_end]         = a[parent(a_end)];
     48 
     49        a[parent(a_end)]= exchange;
     50 
     51        a_end            = parent(a_end);
     52 
     53 //     printf("
    1111111111111
    ");
     54 
     55     }
     56 
     57 }
     58 
     59  
     60 
     61 void max_heap_insert(int a[], int key){
     62 
     63     a_heap_size =a_heap_size + 1;
     64 
     65     a[a_heap_size-1]= -1;
     66 
     67     heap_increase_key(a,a_heap_size, key);
     68 
     69 }
     70 
     71  
     72 
     73 void build_max_heap(int a[]){
     74 
     75     int i;
     76 
     77     a_heap_size =1;
     78 
     79     for(i = 1; i< insert_length; i++){
     80 
     81        max_heap_insert(a,a[i]);
     82 
     83 //     printf("
    66666666666
    ");
     84 
     85     }
     86 
     87 }
     88 
     89  
     90 
     91 int main(){
     92 
     93     inta[a_length];
     94 
     95     int number,i;
     96 
     97     printf("inputthe numbers:");
     98 
     99     scanf("%d",&number);
    100 
    101     //printf("
    ");
    102 
    103     //printf("number=%d
    ",number);
    104 
    105     insert_length= number;
    106 
    107    
    108 
    109     printf("inputthe array:");
    110 
    111     for(i = 0; i< number; i++)
    112 
    113        scanf("%d",&a[i]);
    114 
    115    
    116 
    117     printf("
    ");
    118 
    119     for(i = 0; i <number; i++)
    120 
    121        printf("a[%d]=%d  ",i,a[i]);
    122 
    123     printf("
    ");
    124 
    125  
    126 
    127     build_max_heap(a);
    128 
    129     printf("max_heapa[]= ");
    130 
    131     for(i = 0; i< number; i++)
    132 
    133        printf("%d  ",a[i]);
    134 
    135     printf("
    ");
    136 
    137 }
    说明:所有内容仅做学习记录
  • 相关阅读:
    springboot p6spy 打印完整sql
    mybatis报Invalid bound statement (not found) 分析
    springboot Actuator健康检查
    springboot idea 配置热加载
    面试加笔试大全
    面试题(二)
    面试题(一)
    AJAX技术简介及入门实例
    Google的AJAX翻译程序,使你快速全球化
    ASP.NET调用javascript脚本的方法总结
  • 原文地址:https://www.cnblogs.com/jayinnn/p/9559329.html
Copyright © 2011-2022 走看看