• 二叉堆与堆排序的简单实现


    一、二叉堆

    堆有序:
    一颗二叉树中每个节点都大于或者等于其两个孩子时,就称为堆有序。
    根节点是堆有序的二叉树的最大节点。

    堆有序的二叉树可以用指针来表示,
    堆有序的完全二叉树除了可以用指针表示外,还可以用数组表示。

    二叉堆:
    二叉堆是一组堆有序的完全二叉树,并且在数组中按层级存储(不使用数组中0号位置的元素)。
    二叉堆可以方便的实现优先队列的各种操作。

    对于给定堆中任意的位置k
    其父亲的位置:K/2
    其两个孩子的位置:2k或者2k+1
    这样就可以不使用指针来实现向上查找和向下查找。

    二、二叉堆实现

      1 package agheap;
      2 
      3 import java.util.ArrayList;
      4 
      5 class Node{
      6     public final int value;
      7     Node(int value){
      8         this.value = value;
      9     }
     10     public String toString(){
     11         return "value:"+value;
     12     }
     13 }
     14 public class BinHeap {
     15     private static void swap(ArrayList<Node> aryList,int indexA,int indexB){
     16         Node tmp;
     17         tmp = aryList.get(indexA);
     18         aryList.set(indexA, aryList.get(indexB));
     19         aryList.set(indexB, tmp);
     20     }
     21     
     22     //上浮堆有序化
     23     private static void swim(ArrayList<Node> aryList,int index) {
     24         while(index > 1 && aryList.get(index).value > aryList.get(index/2).value){//当前元素非堆顶且大于其父亲,需要上浮调整
     25             swap(aryList, index, index/2);
     26             index = index/2;
     27         }
     28     }
     29     
     30     //下沉堆有序化
     31     private static void sink(ArrayList<Node> aryList,int index,int high){
     32         int indexOfMaxChild;
     33         while(true){
     34             if (2*index > high) {break;}//ary[2*index]无孩子
     35             if (2*index == high) {//ary[2*index]有左孩子,此时indexOfMaxChild无选择
     36                 indexOfMaxChild = 2*index;
     37             }else {//ary[2*index]有左右两孩子,此时indexOfMaxChild有选择
     38                 indexOfMaxChild = aryList.get(2*index).value > aryList.get(2*index+1).value?2*index:2*index+1;
     39             }
     40             if (aryList.get(index).value <aryList.get(indexOfMaxChild).value) {//当前ary[index]不满足局部堆有序
     41                 swap(aryList, index, indexOfMaxChild);
     42             }
     43             index = indexOfMaxChild;//继续向下迭代
     44         }
     45     }
     46     
     47     //sink()构造大根堆
     48     public static void createHeap(ArrayList<Node> aryList){
     49         int high = aryList.size()-1;
     50         for (int i = high/2; i > 0; i--) {//从非叶节点开始构造,同时sink()保持堆有序
     51             sink(aryList, i, high);
     52         }
     53     }
     54     
     55 //    //swim()构造大根堆
     56 //    public static void createHeap(ArrayList<Node> aryList){
     57 //        int high = aryList.size()-1;
     58 //        for (int i = 1; i <= high; i++) {//从索引1位置开始逐个加入,同时swim()保持堆有序
     59 //            swim(aryList, i);
     60 //        }
     61 //    }
     62     public static void insert(ArrayList<Node> aryList,Node target){
     63         aryList.add(target);
     64         swim(aryList, aryList.size()-1);
     65     }
     66     //删除堆顶元素
     67     public static Node deleteMax(ArrayList<Node> aryList){
     68         int high = aryList.size()-1;
     69         Node node = null;
     70         if (high > 0) {
     71             swap(aryList, 1, high);//将末尾元素和堆顶元素交换
     72             node = aryList.remove(high);//删除末尾元素
     73             sink(aryList, 1, high-1);//对堆顶元素重新,使其重新堆有序
     74         }
     75         return node;
     76     }
     77     public static void main(String[] args) {
     78         // TODO Auto-generated method stub
     79         try {
     80             int[] ary = {0,12,9,78,10,30,8,20,12,15};
     81             ArrayList<Node> aryList = new ArrayList<Node>();
     82             for (int i = 0; i < ary.length; i++) {
     83                 aryList.add(new Node(ary[i]));
     84             }
     85             createHeap(aryList);
     86             insert(aryList, new Node(5));
     87 //            for(Node node:aryList){
     88 //                System.out.println(node);
     89 //            }
     90             int size = aryList.size()-1;
     91             for (int i = 0; i < size; i++) {
     92                 System.out.println(deleteMax(aryList));
     93             }
     94         } catch (Exception e) {
     95             // TODO: handle exception
     96             e.printStackTrace();
     97         }
     98     }
     99 
    100 }

    三、借助二叉堆实现堆排序

     1     private static void createHeap(int[] ary,int index,int high){
     2         int indexOfMaxChild;
     3         while(true){
     4             if (2*index > high) {break;}//ary[2*index]无孩子
     5             if (2*index == high) {//ary[2*index]有左孩子,此时indexOfMaxChild无选择
     6                 indexOfMaxChild = 2*index;
     7             }else {//ary[2*index]有左右两孩子,此时indexOfMaxChild有选择
     8                 indexOfMaxChild = ary[2*index] > ary[2*index+1]?2*index:2*index+1;
     9             }
    10             if (ary[index] < ary[indexOfMaxChild]) {//当前ary[index]不满足局部堆有序
    11                 swap(ary, index, indexOfMaxChild);
    12             }
    13             index = indexOfMaxChild;//继续向下迭代
    14         }
    15     }
    16     public static void heapSort(int[] ary){
    17         int high = ary.length-1;
    18         for (int i = high/2; i > 0; i--) {//从最大的非叶节点开始构造堆,堆顶位置为1,舍弃数组的0位
    19             createHeap(ary, i, high);
    20         }
    21         while(high > 0){
    22             swap(ary, 1, high);//将大根堆的堆顶元素(最大值)与数组尾部值交换。
    23             high--;//大根堆的范围缩小一个单位。
    24             createHeap(ary, 1, high);//重构大根堆。
    25             
    26         }
    27     }
  • 相关阅读:
    【分布式事务】的一篇良心之作!
    如何保证缓存与数据库的数据一致性
    30多岁的大龄程序员,应该如何保持职场竞争力
    Kafka acks参数对消息持久化的影响
    Kafka 如何优化内存缓冲机制造成的频繁 GC 问题?
    Shell中的特殊符号(special characters)和含义
    Bash中的一些常用的数组相关的特殊语法(array syntax)
    一站式搞定Bash脚本的参数处理问题
    Bash脚本set命令教程
    Bash中的eval命令
  • 原文地址:https://www.cnblogs.com/qcblog/p/7536520.html
Copyright © 2020-2023  润新知