• 索引优先队列


    一、简介

    在很多应用中,允许用例对已经进入优先队列中的元素非常有必要。

    一个简单的实现方法是对每个元素关联一个索引

    索引优先队列API:

    二、实现

     通过对普通优先队列的实现进行拓展来实现索引优先队列。

    思路:

    (1)增加数组keys用来保存优先队列元素(item or key)

    (2)pq数组则改用于保存索引(pq[i] = k,k为索引)

        这里的pq数组仍然保持堆有序,即pq[1]所对应的元素(keys[pq[1]])大于或等于pq[2]、pq[3]所对应的元素(keys[pq[2]]、keys[pq[3]])。

    (3)增加数组qp,用于保存pq的逆序。

        如果pq[i] = k,则qp[k] = i,也就是pq[qp[k]] = k。

        如果k不在队列之中,则qp[k] = -1。

    代码实现:

    package com.qiusongde;
    
    import java.util.NoSuchElementException;
    
    public class IndexMinPQ<Key extends Comparable<Key>> {
        
        /*
         * k is index(0,maxN-1)
         * pq[i] = k means the ith node in the heap is keys[k]
         * qp[k] = i means keys[k] is the ith node in the heap
         * qp[k] = -1 if k(index) is not in the Priority Queue
         * 
         */
        private Key[] keys;//items with priorities
        private int[] pq;//binary heap using 1-based indexing
        private int[] qp;//inverse: qp[pq[i]] = pq[qp[i]] = i
        private int n;//number of elements on PQ
        private int maxN;
        
        public IndexMinPQ(int maxN) {
            
            if(maxN < 0)
                throw new IllegalArgumentException("The size of IndexMinPQ should larger than 0");
            
            this.maxN = maxN;
            keys = (Key[]) new Comparable[maxN + 1];
            pq = new int[maxN + 1];
            qp = new int[maxN + 1];
            for(int i = 0; i <= maxN; i++)
                qp[i] = -1;
            n = 0;
        }
        
        public boolean isEmpty() {
            return n == 0;
        }
        
        public int size() {
            return n;
        }
        
        public boolean contains(int k) {
            if(k < 0 || k >= maxN)
                throw new IndexOutOfBoundsException();
            return qp[k] != -1;
        }
        
        public void insert(int k, Key key) {
            
             if (k < 0 || k >= maxN)
                 throw new IndexOutOfBoundsException();
             if (contains(k))
                 throw new IllegalArgumentException("index is already in the priority queue");
             
            n++;
            qp[k] = n;
            pq[n] = k;
            keys[k] = key;
            swim(n);
            
        }
        
        public Key min() {
            
            if(n == 0)
                throw new NoSuchElementException("IndexMinPQ underflow");
            
            return keys[pq[1]];
            
        }
        
        public int minIndex() {
            
            if(n == 0)
                throw new NoSuchElementException("IndexMinPQ underflow");
            
            return pq[1];
        }
        
        public int delMin() {
            
            if(n == 0)
                throw new NoSuchElementException("IndexMinPQ underflow");
            
            int indexOfMin = pq[1];
            
            exch(1, n--);
            sink(1);
            keys[pq[n+1]] = null;
            qp[pq[n+1]] = -1;
            
            return indexOfMin;
        }
        
        public void delete(int i) {
            
            if (i < 0 || i >= maxN) 
                throw new IndexOutOfBoundsException();
            if (!contains(i))
                throw new NoSuchElementException("index is not in the priority queue");
            
            int index = qp[i];
            exch(index, n--);
            swim(index);
            sink(index);
            keys[i] = null;
            qp[i] = -1;
            
        }
        
        public void changeKey(int i, Key key) {
            
            if (i < 0 || i >= maxN)
                throw new IndexOutOfBoundsException();
            if (!contains(i))
                throw new NoSuchElementException("index is not in the priority queue");
            
            keys[i] = key;
            swim(qp[i]);
            sink(qp[i]);
            
        }
        
         /***************************************************************************
        * General helper functions.
        ***************************************************************************/
        private boolean greater(int i, int j) {
            return keys[pq[i]].compareTo(keys[pq[j]]) > 0;
        }
    
        private void exch(int i, int j) {
            int swap = pq[i];
            pq[i] = pq[j];
            pq[j] = swap;
            qp[pq[i]] = i;
            qp[pq[j]] = j;
        }
    
    
       /***************************************************************************
        * Heap helper functions.
        ***************************************************************************/
        private void swim(int k) {
            while (k > 1 && greater(k/2, k)) {
                exch(k, k/2);
                k = k/2;
            }
        }
    
        private void sink(int k) {
            while (2*k <= n) {
                int j = 2*k;
                if (j < n && greater(j, j+1)) j++;
                if (!greater(k, j)) break;
                exch(k, j);
                k = j;
            }
        }
        
        
    }
      public static void main(String[] args) {
            // insert a bunch of strings
            String[] strings = { "it", "was", "the", "best", "of", "times", "it", "was", "the", "worst" };
    
            IndexMinPQ<String> pq = new IndexMinPQ<String>(strings.length);
            for (int i = 0; i < strings.length; i++) {
                pq.insert(i, strings[i]);
            }
    
            // delete and print each key
            while (!pq.isEmpty()) {
                int i = pq.delMin();
                StdOut.println(i + " " + strings[i]);
            }
            StdOut.println();
    
    
        }
    3 best
    0 it
    6 it
    4 of
    8 the
    2 the
    5 times
    7 was
    1 was
    9 worst

    三、应用

     多向归并问题:

    将多个有序的输入流归并成一个有序的输入流。使用优先队列,无论输入有多长都可以将这些数据读入并归并。

    public class Multiway { 
    
        // This class should not be instantiated.
        private Multiway() { }
    
        // merge together the sorted input streams and write the sorted result to standard output
        private static void merge(In[] streams) {
            int n = streams.length;
            IndexMinPQ<String> pq = new IndexMinPQ<String>(n);
            for (int i = 0; i < n; i++)
                if (!streams[i].isEmpty())
                    pq.insert(i, streams[i].readString());
    
            // Extract and print min and read next from its stream. 
            while (!pq.isEmpty()) {
                StdOut.print(pq.minKey() + " ");
                int i = pq.delMin();
                if (!streams[i].isEmpty())
                    pq.insert(i, streams[i].readString());
            }
            StdOut.println();
        }
    
    
        /**
         *  Reads sorted text files specified as command-line arguments;
         *  merges them together into a sorted output; and writes
         *  the results to standard output.
         *  Note: this client does not check that the input files are sorted.
         *
         * @param args the command-line arguments
         */
        public static void main(String[] args) {
            int n = args.length;
            In[] streams = new In[n];
            for (int i = 0; i < n; i++)
                streams[i] = new In(args[i]);
            merge(streams);
        }
    }
  • 相关阅读:
    遍历数据类型数组方式
    for 循环 和for..in循环遍历数组 的区别
    多个区域内有相同属性名称子元素,同一区域内 操作DOM子集 使用$("选择器",context)方法
    CSS 使用技巧
    JavaScript 动态加载页面 js文件
    angular2环境配置
    在路上●我的年青●逐步前进
    ARM v8-A 系列CPU的MMU隐射分析
    ARM Cortex-A53 Cache与内存的映射关系以及Cache的一致性分析
    二维图像的投影和图像重建分析之傅里叶变换法
  • 原文地址:https://www.cnblogs.com/songdechiu/p/6736114.html
Copyright © 2020-2023  润新知