zoukankan      html  css  js  c++  java
  • 数据结构与算法08 之堆

            优先级队列可以用有序数组来实现,这种做法的问题是,尽管删除最大数据项的时间复杂度为O(1),但是插入还是需要较长的O(N)时间,这是因为必须移动数组中平均一半的数据项以插入新数据项,并在完成插入后,数组依然有序。

            这里介绍实现优先级队列的另一种结构:堆。堆是一种树,并非java和C++等编译语言里的“堆”。由它实现的优先级队列的插入和删除的时间复杂度都是O(logN)。尽管这样删除的时间变慢了一些,但是插入的时间快的多了。当速度非常重要,且有很多插入操作是,可以选择堆来实现优先级队列。堆有如下特点:

            ·它是完全二叉树。即除了树的最后一层节点不需要是满的外,其他的每一层从左到右都完全是满的。

            ·它常常用一个数组实现。用数组实现的完全二叉树中,节点的索引有如下特点(设该节点的索引为x):

                 它的父节点的索引为 (x-1) / 2;

                 它的左子节点索引为 2*x + 1;

                 它的右子节点索引为 2*x + 2。

            ·堆中每个节点的关键字都大于(或等于)这个节点的子节点的关键字。这也是堆中每个节点必须满足的条件。所以堆和二叉搜索树相比,是弱序的。

            向堆中插入数据,首先将数据项存放到叶节点中(即存到数组的最后一项),然后从该节点开始,逐级向上调整,直到满足堆中节点关键字的条件为止。

            从堆中删除数据与插入不同,删除时永远删除根节点的数据,因为根节点的数据最大,删除完后,将最后一个叶节点移到根的位置,然后从根开始,逐级向下调整,直到满足堆中节点关键字的条件为止。具体的看下面的代码:

    1. public class Heap {  
    2.       
    3.     private Node[] heapArray;  
    4.     private int maxSize;  
    5.     private int currentSize;  
    6.       
    7.     public Heap(int mx) {  
    8.         maxSize = mx;  
    9.         currentSize = 0;  
    10.         heapArray = new Node[maxSize];  
    11.     }  
    12.       
    13.     public boolean isEmpty() {  
    14.         return (currentSize == 0)? true : false;  
    15.     }  
    16.       
    17.     public boolean isFull() {  
    18.         return (currentSize == maxSize)? true : false;  
    19.     }  
    20.       
    21.     public boolean insert(int key) {  
    22.         if(isFull()) {  
    23.             return false;  
    24.         }  
    25.         Node newNode = new Node(key);  
    26.         heapArray[currentSize] = newNode;  
    27.         trickleUp(currentSize++);  
    28.         return true;  
    29.     }  
    30.     //向上调整  
    31.     public void trickleUp(int index) {  
    32.         int parent = (index - 1) / 2//父节点的索引  
    33.         Node bottom = heapArray[index]; //将新加的尾节点存在bottom中  
    34.         while(index > 0 && heapArray[parent].getKey() < bottom.getKey()) {  
    35.             heapArray[index] = heapArray[parent];  
    36.             index = parent;  
    37.             parent = (parent - 1) / 2;  
    38.         }  
    39.         heapArray[index] = bottom;  
    40.     }  
    41.       
    42.     public Node remove() {  
    43.         Node root = heapArray[0];  
    44.         heapArray[0] = heapArray[--currentSize];  
    45.         trickleDown(0);  
    46.         return root;  
    47.     }  
    48.     //向下调整  
    49.     public void trickleDown(int index) {  
    50.         Node top = heapArray[index];  
    51.         int largeChildIndex;  
    52.         while(index < currentSize/2) { //while node has at least one child  
    53.             int leftChildIndex = 2 * index + 1;  
    54.             int rightChildIndex = leftChildIndex + 1;  
    55.             //find larger child  
    56.             if(rightChildIndex < currentSize &&  //rightChild exists?  
    57.                     heapArray[leftChildIndex].getKey() < heapArray[rightChildIndex].getKey()) {  
    58.                 largeChildIndex = rightChildIndex;  
    59.             }  
    60.             else {  
    61.                 largeChildIndex = leftChildIndex;  
    62.             }  
    63.             if(top.getKey() >= heapArray[largeChildIndex].getKey()) {  
    64.                 break;  
    65.             }  
    66.             heapArray[index] = heapArray[largeChildIndex];  
    67.             index = largeChildIndex;  
    68.         }  
    69.         heapArray[index] = top;  
    70.     }  
    71.     //根据索引改变堆中某个数据  
    72.     public boolean change(int index, int newValue) {  
    73.         if(index < 0 || index >= currentSize) {  
    74.             return false;  
    75.         }  
    76.         int oldValue = heapArray[index].getKey();  
    77.         heapArray[index].setKey(newValue);  
    78.         if(oldValue < newValue) {  
    79.             trickleUp(index);  
    80.         }  
    81.         else {  
    82.             trickleDown(index);  
    83.         }  
    84.         return true;  
    85.     }  
    86.       
    87.     public void displayHeap() {  
    88.         System.out.println("heapArray(array format): ");  
    89.         for(int i = 0; i < currentSize; i++) {  
    90.             if(heapArray[i] != null) {  
    91.                 System.out.print(heapArray[i].getKey() + " ");  
    92.             }  
    93.             else {  
    94.                 System.out.print("--");  
    95.             }  
    96.         }  
    97.     }  
    98. }  
    99. class Node {  
    100.     private int iData;  
    101.     public Node(int key) {  
    102.         iData = key;  
    103.     }  
    104.       
    105.     public int getKey() {  
    106.         return iData;  
    107.     }  
    108.       
    109.     public void setKey(int key) {  
    110.         iData = key;  
    111.     }  
    112. }  

    http://blog.csdn.net/eson_15/article/details/51105955

  • 相关阅读:
    vue 小知识
    vue中alert toast confirm loading 公用
    vue 跳外链
    vue 中使用 Toast弹框
    vue 添加vux
    #034Python选修课第二届Turtle绘图大赛
    #033 信安培训基础题Python解决网络安全实验室|网络信息安全攻防学习平台
    #031 测试插入博客园插入视频
    # 030删除数组中的重复元素
    #029 博客换个主题从新开始
  • 原文地址:https://www.cnblogs.com/itommy/p/10610493.html
Copyright © 2011-2022 走看看