• 第6章 堆排序 java实现 简单版 泛型版 最大优先级队列


    方案一、只考虑int类型的排序,最简单的实现如下。

     1 public class Heap {
     2     
     3     public int heap_size;//在build_max_heap中初始化,由heap_sort自动调用
     4     
     5     public int parent(int i){
     6         return (i - 1) / 2;
     7     }
     8     public int left(int i){
     9         return 2 * i + 1;
    10     }
    11     public int right(int i){
    12         return 2 * i + 2;
    13     }
    14     
    15     /** 保持堆的性质,
    16      * 假定left(i), right(i)为根的两根二叉树都是最大堆,
    17      * A[i]可能小于其子女,这样就违背了最大堆性质
    18      * 该函数让A[i]在最大堆中“下降”,使以i为根的子树成为最大堆
    19      * */
    20     public void max_heapify(int[] A, int i){
    21         int l = left(i);
    22         int r = right(i);
    23         int largest;
    24         // 从A[i] A[left(i)] A[right(i)] 中找出最大,下标存在largest中
    25         // 若A[i]为最大,则根据假设,i为根的子树已是最大堆,函数结束
    26         // 否则交换A[i]和A[largest],交换后下标为largest的节点值为A[i]
    27         // 该节点的子树可能违反最大堆,因此对largest下标递归调用
    28         if(l < heap_size && A[l] > A[i]){
    29             largest = l;
    30         } 
    31         else{
    32             largest = i;
    33         }    
    34         if(r < heap_size && A[r] > A[largest]){
    35             largest = r;
    36         }
    37         if(largest != i){
    38             int tmp = A[i];
    39             A[i] = A[largest];
    40             A[largest] = tmp;
    41             
    42             max_heapify(A, largest);
    43         }
    44     }
    45     
    46     /**
    47      * 建堆
    48      * 自底向上将数组A[1..n](此处n=length[A])变成最大堆
    49      * 子数组A[(floor(n / 2) + 1) .. n]中的元素都是树中的叶子
    50      * 所以对每一个非叶子节点都调用一次该过程
    51      * */
    52     public void build_max_heap(int[] A){
    53         heap_size = A.length; // 初始化heap_size
    54         for(int i = (heap_size/2 - 1); i > -1; --i){
    55             max_heapify(A, i);
    56         }
    57     }
    58     
    59     /**
    60      * 堆排序算法
    61      * 先建造最大堆,根A[1]即为最大,则置换到数组的正确位置A[n]
    62      * 从堆中去掉节点n,A[1..n-1]建成最大堆,但新根可能违背了最大堆性质,
    63      * 此时调用max_heapify(A,1)可以保持该性质,在A[1..n-1]构造出最大堆。
    64      * 不断重复,堆大小从n-1降到2
    65      * */
    66     public void heapsort(int[] A){
    67         build_max_heap(A);
    68         for(int i = A.length-1; i > 0; --i){
    69             int tmp = A[0];
    70             A[0] = A[i];
    71             A[i] = tmp;
    72             --heap_size;
    73             max_heapify(A, 0);
    74         }
    75     }
    76     
    77     public static void show_array(int[] A){
    78         for(int i = 0; i < A.length; ++i){
    79             System.out.print(A[i] + ". ");
    80         }
    81         System.out.println();
    82     }
    83     
    84     public static void main(String[] args){
    85         int[] A = {4, 1, 3, 2, 16, 9, 10, 14, 8, 7};
    86         
    87 88 System.out.println("before heapsort:"); 89 show_array(A); 90 91 Heap h = new Heap(); 92 h.heapsort(A); 93 94 System.out.println("after heapsort:"); 95 show_array(A); 96 97 } 98 99 }

     运行结果:

    方案二、考虑泛型,使用泛型数组的实现如下:

      1 public class HeapTwo<T extends Comparable<T>> {
      2     
      3     T[] A;
      4     int heap_size;//在build_max_heap中初始化,由heap_sort自动调用,或在类实例化时构造
      5     
      6     public HeapTwo(T[] A){
      7         this.A = A;
      8         this.heap_size = A.length;
      9     }
     10     
     11     public int parent(int i){
     12         return (i - 1) / 2;
     13     }
     14     public int left(int i){
     15         return 2 * i + 1;
     16     }
     17     public int right(int i){
     18         return 2 * i + 2;
     19     }
     20     
     21     /** 保持堆的性质,
     22      * 假定left(i), right(i)为根的两根二叉树都是最大堆,
     23      * A[i]可能小于其子女,这样就违背了最大堆性质
     24      * 该函数让A[i]在最大堆中“下降”,使以i为根的子树成为最大堆
     25      * */
     26     public void max_heapify(int i){
     27         int l = left(i);
     28         int r = right(i);
     29         int largest;
     30         // 从A[i] A[left(i)] A[right(i)] 中找出最大,下标存在largest中
     31         // 若A[i]为最大,则根据假设,i为根的子树已是最大堆,函数结束
     32         // 否则交换A[i]和A[largest],交换后下标为largest的节点值为A[i]
     33         // 该节点的子树可能违反最大堆,因此对largest下标递归调用
     34         if(l < heap_size && A[l].compareTo(A[i]) > 0 ){
     35             largest = l;
     36         } 
     37         else{
     38             largest = i;
     39         }    
     40         if(r < heap_size && A[r].compareTo(A[largest]) > 0){
     41             largest = r;
     42         }
     43         if(largest != i){
     44             T tmp = A[i];
     45             A[i] = A[largest];
     46             A[largest] = tmp;
     47             
     48             max_heapify(largest);
     49         }
     50     }
     51     
     52     /**
     53      * 建堆
     54      * 自底向上将数组A[1..n](此处n=length[A])变成最大堆
     55      * 子数组A[(floor(n / 2) + 1) .. n]中的元素都是树中的叶子
     56      * 所以对每一个非叶子节点都调用一次该过程
     57      * */
     58     public void build_max_heap(){
     59         heap_size = A.length; // 初始化heap_size
     60         for(int i = (heap_size/2 - 1); i > -1; --i){
     61             max_heapify(i);
     62         }
     63     }
     64     
     65     /**
     66      * 堆排序算法
     67      * 先建造最大堆,根A[1]即为最大,则置换到数组的正确位置A[n]
     68      * 从堆中去掉节点n,A[1..n-1]建成最大堆,但新根可能违背了最大堆性质,
     69      * 此时调用max_heapify(A,1)可以保持该性质,在A[1..n-1]构造出最大堆。
     70      * 不断重复,堆大小从n-1降到2
     71      * */
     72     public void heapsort(){
     73         build_max_heap();
     74         for(int i = A.length-1; i > 0; --i){
     75             T tmp = A[0];
     76             A[0] = A[i];
     77             A[i] = tmp;
     78             --heap_size;
     79             max_heapify(0);
     80         }
     81     }
     82     
     83     public void show_array(){
     84         for(int i = 0; i < A.length; ++i){
     85             System.out.print(A[i] + ". ");
     86         }
     87         System.out.println();
     88     }
     89     
     90     public static void main(String[] args){
     91         Double[] A = {4.3, 1.2, 3.2, 2.8, 16.5, 9.3, 10.6, 14.6, 8.4, 7.0};
     92         
     93         System.out.println("before heapsort:");
     94         
     95         
     96         HeapTwo h = new HeapTwo(A);
     97         h.show_array();
     98         h.heapsort();
     99         
    100         System.out.println("after heapsort:");
    101         h.show_array();
    102         
    103     }
    104 }

     最大优先级队列:

      1 package org.hhj;
      2 
      3 public class Heap {
      4     
      5     int[] A;
      6     int heap_size;//在build_max_heap中初始化,由heap_sort自动调用,或在类实例化时构造
      7     
      8     public Heap(int[] A){
      9         this.A = A;
     10         this.heap_size = A.length;
     11     }
     12     
     13     public int parent(int i){
     14         return (i - 1) / 2;
     15     }
     16     public int left(int i){
     17         return 2 * i + 1;
     18     }
     19     public int right(int i){
     20         return 2 * i + 2;
     21     }
     22     
     23     /** 保持堆的性质,
     24      * 假定left(i), right(i)为根的两根二叉树都是最大堆,
     25      * A[i]可能小于其子女,这样就违背了最大堆性质
     26      * 该函数让A[i]在最大堆中“下降”,使以i为根的子树成为最大堆
     27      * */
     28     public void max_heapify(int[] A, int i){
     29         int l = left(i);
     30         int r = right(i);
     31         int largest;
     32         // 从A[i] A[left(i)] A[right(i)] 中找出最大,下标存在largest中
     33         // 若A[i]为最大,则根据假设,i为根的子树已是最大堆,函数结束
     34         // 否则交换A[i]和A[largest],交换后下标为largest的节点值为A[i]
     35         // 该节点的子树可能违反最大堆,因此对largest下标递归调用
     36         if(l < heap_size && A[l] > A[i]){
     37             largest = l;
     38         } 
     39         else{
     40             largest = i;
     41         }    
     42         if(r < heap_size && A[r] > A[largest]){
     43             largest = r;
     44         }
     45         if(largest != i){
     46             int tmp = A[i];
     47             A[i] = A[largest];
     48             A[largest] = tmp;
     49             
     50             max_heapify(A, largest);
     51         }
     52     }
     53     
     54     /**
     55      * 建堆
     56      * 自底向上将数组A[1..n](此处n=length[A])变成最大堆
     57      * 子数组A[(floor(n / 2) + 1) .. n]中的元素都是树中的叶子
     58      * 所以对每一个非叶子节点都调用一次该过程
     59      * */
     60     public void build_max_heap(int[] A){
     61         heap_size = A.length; // 初始化heap_size
     62         for(int i = (heap_size/2 - 1); i > -1; --i){
     63             max_heapify(A, i);
     64         }
     65     }
     66     
     67     /**
     68      * 堆排序算法
     69      * 先建造最大堆,根A[1]即为最大,则置换到数组的正确位置A[n]
     70      * 从堆中去掉节点n,A[1..n-1]建成最大堆,但新根可能违背了最大堆性质,
     71      * 此时调用max_heapify(A,1)可以保持该性质,在A[1..n-1]构造出最大堆。
     72      * 不断重复,堆大小从n-1降到2
     73      * */
     74     public void heapsort(int[] A){
     75         build_max_heap(A);
     76         for(int i = A.length-1; i > 0; --i){
     77             int tmp = A[0];
     78             A[0] = A[i];
     79             A[i] = tmp;
     80             --heap_size;
     81             max_heapify(A, 0);
     82         }
     83     }
     84     
     85     public static void show_array(int[] A){
     86         for(int i = 0; i < A.length; ++i){
     87             System.out.print(A[i] + ". ");
     88         }
     89         System.out.println();
     90     }
     91     
     92     /**
     93      * 返回A[]中具有最大关键字的元素
     94      * @param A
     95      * @return
     96      */
     97     public int heap_maximum(int[] A){
     98         return A[0];
     99     }
    100     
    101     /**
    102      * 去掉并返回A中的具有最大关键字的元素
    103      * @param A
    104      * @return
    105      */
    106     public int heap_extract_max(int[] A){
    107         if(heap_size < 1){
    108             System.out.println("heap underflow");
    109             return -1;
    110         }
    111         int max = A[0];
    112         A[0] = A[heap_size - 1];
    113         --heap_size;
    114         max_heapify(A, 0);
    115         return max;
    116     }
    117     
    118     /**
    119      * 将元素i的关键字的值增加到key,这里key值不可小于i的原关键字的值
    120      * @param A
    121      * @param i
    122      * @param key
    123      */
    124     public void heap_increase_key(int[] A, int i, int key){
    125         if(key < A[i]){
    126             System.out.println("new key is smaller than current key");
    127         }
    128         A[i] = key;
    129         while(i > 1 && A[parent(i)] < A[i]){
    130             int tmp = A[i];
    131             A[i] = A[parent(i)];
    132             A[parent(i)] = tmp;
    133             i = parent(i);
    134         }
    135     }
    136     
    137     /**
    138      * 将key插入到最大堆A中,先用一个关键字值为负无穷的叶节点扩展对大队,
    139      * 然后调用heap_increase_key来设置新节点的关键字的正确值,并保持最大堆性质。
    140      * @param A
    141      * @param key
    142      */
    143     public void max_heap_insert(int[] A, int key){
    144         ++heap_size;
    145         A[heap_size] = Integer.MIN_VALUE;
    146         heap_increase_key(A, heap_size, key);
    147         
    148     }
    149     public static void main(String[] args){
    150         
    151         
    152     }
    153     
    154 }
  • 相关阅读:
    IDEA安装和JDK的配置
    IDEA里面创建maven项目,依赖
    JSON的简单书写(初学),使用Java语言反序列化
    Spring中的转换器:Converter
    关于Spring MVC中的表单标签库的使用
    解决Spring框架下中文乱码的问题
    SpringMVC中使用DispatcherServlet
    八大排序算法:冒泡排序
    总线与南桥和北桥
    设备驱动与控制器 I/O
  • 原文地址:https://www.cnblogs.com/tobebrave/p/4875521.html
Copyright © 2020-2023  润新知