zoukankan      html  css  js  c++  java
  • 算法练习——堆排序应用(优先队列)

    优先队列作为堆排序的高级应用具有十分广泛的应用场景,其中一个就是在共享计算机系统的作业调度。最大优先队列记录将要执行的各个作业以及它们之间的相对优先级.

    当一个作业完成或者被中断后,调度器调用  EXTRACT-MAX  从所有的等待作业中,选出具有最高优先级的作业来执行。

    在任何时候,调度器可以调用 INSERT() 把一个新作业加入到队列中来。

    下面就讨论一下关于优先队列的基本操作:

    优先队列(priority queue)是一种用来维护由一组元素构成的集合S的数据结构,其中的每一个元素都有一个相关的值,称为关键字( key).一个最大优先队列支持以下操作:

      INSERT(S , x): 把元素x插入集合S中。

      MAXIMUM(S):返回S中具有最大键字的元素.

      EXTRACT-MAX(S):去掉并返回S中的具有最大键字的元素。

      INCREASE-KEY(S , x,k):将元素x的关键字值增加到k,这里假设k的值不小于x的原关键字值。
      HeapDelete(A,i)    :删除第 i 个位置的元素

      

    下面分别给出各自的伪代码描述:

    1     INSERT(S,x) 

        把元素x插入到集合S中

    1 MaxHeapInsert(A,key)
    2     A.heapsize = A.heapsize+1
    3     A[A.heapsize] =-无穷大
    4     HeapIncreaseKey(A,A[A.heapsize],key)

         此时时间复杂度主要消耗在    HeapIncreaseKey()   上,而后者的时间复杂度为   O(logn)

    2   INCREASE_KEY(S,x,k)

        将元素x的关键字值增加为k(前提:k>=x)     整体的算法:从开始增大的那个值开始往根节点循环调用。(自低向顶) 

          该方法的时间复杂度为    O(logn)     因为第三行做关键字更新的结点到根节点的路径长度为  O(logn)

    1 HeapIncreaseKey(A,x,key)
    2     if key <= A[i]
    3         error "请输入更大的key值"
    4     A[i] = key
    5     while i >=0 && A[Parent(i)] <= A[i]
    6         Exchange A[i] with A[Parent(i)]
    7         i = Parent(i)

        HEAP-INCREASE-KEY的操作过程.(a)图6-4(a)中的最大堆,其中下标为i的结点以深色阴影显示.
        (b)该结点的关键字增加到15.
        (c)经过第 4--6 行的 while 循环的一次迭代,该结点与其父结点交换关键字,
        同时下标i的指示上移到其父结点.(d)经过再一次迭代后得到的最大堆.此时,
        A[PARENT(i)]≥A[f].现在,最大堆的性质成立,程序终止

    3    EXTRACT_MAX(S)

        去掉并且返回S中的最大关键字元素

    HeapMaxImum(A)
        max = A[0]
        A[0] = A[A.heapsize] 
        A.heapsize = A.heapsize-1
        MaxHeap(A,0)
        return max

           EXTRACT_MAX(S)   的时间复杂度为   O( log(n) ),因此除了MaxHeap(A,i)的时间复杂度为O(logn)之外,其余的时间复杂度均为常数。

    4   MaxIMUM(S)

        取得S集合中的最大值

    HeapMaxImum(A)
        return A[0]

    5   HeapDelete(A,i)    

        删除第 i 个位置的元素

    1 HeapDelete(A,i)
    2     temp = A[i]
    3     A[i] = A[A.heapsize]
    4     A.heapsize = A.heapsize-1
    5     MaxHeap(A,i)
    6     return temp

    具体的代码实现:

     1 /*
     2  * 优先队列主要通过四个函数来实现
     3  */
     4 public class Priorityqueue {
     5     
     6     static int[] a={15,13,9,5,21,8,7,4,0,6,2,1};
     7     public static int [] heap =a ;
     8     public static int heapsize = heap.length;
     9     
    10     //给优先队列插入某一个值   数组大小不容易控制     可以考虑使用链表
    11     public void MaxHeapInsert(int[] A,int key){
    12         heapsize = heapsize+1;
    13         a[heapsize-1] = -1000;
    14         HeapIncreaseKey(a,heapsize,key);
    15     }
    16     
    17     //增加第i个元素的数值
    18     public void HeapIncreaseKey(int[] a2, int i, int key) {
    19         if (key <= a[i]) 
    20             System.out.println("请输入更大的值------");
    21         a[i] = key;
    22         //这里也可以用递归
    23         while(i > 0 && a[HeapSort.findParent(i)]<a[i] ){
    24             swap(a,HeapSort.findParent(i) , i);
    25             i = HeapSort.findParent(i);
    26         }
    27         
    28     }
    29 
    30     //交换数组中的两个元素
    31     private void swap(int[] a2, int parent, int i) {
    32         int temp = a[i];
    33         a[i] = a[parent];
    34         a[parent] = temp;
    35     }
    36     
    37     //取得优先队列的最大值
    38     public int HeapMaximum(){
    39         return a[0];
    40     }
    41     
    42     //去掉并且返回最大值最大值
    43     public int HeapExtractMax(int[] b){
    44         int max = b[0];
    45         b[0] = b[heapsize-1];
    46         heapsize--;
    47         HeapSort.maxHeap(b , 0);
    48         return 0;
    49     }
    50 
    51     //删除优先队列中第i个位置的元素     这里面调用的HeapSort.maxHeap(a,i)  主要来自于上一篇文章中的maxHeap() 在于维持最大堆的性质
    52     public void MaxHeapDelete(int[] b,int i){
    53         int temp = b[i];
    54         b[i] = b[heapsize-1];
    55         heapsize--;
    56         HeapSort.maxHeap(b, i);
    57     }
    58     
    59     public void printMy(int[] a){
    60         for (int i = 0; i < heapsize; i++) 
    61             System.out.print(a[i]+" ");
    62         System.out.println();
    63     }
    64 
    65     
    66     public static void main(String[] args){
    67         Priorityqueue pqueue = new Priorityqueue();
    68         System.out.print("原数组:  ");
    69         pqueue.printMy(a);
    70         
    71         HeapSort.createHeap(a);
    72         System.out.print("最大堆:  ");
    73         pqueue.printMy(a);
    74         
    75         pqueue.HeapIncreaseKey(a, 7, 11);
    76         System.out.print("增加数值  ");
    77         pqueue.printMy(a);
    78         
    79         int max = pqueue.HeapMaximum();
    80         System.out.print("返回最大值  ");
    81         System.out.println(max);
    82         
    83         int extracte = pqueue.HeapExtractMax(a);
    84         System.out.print("去掉最大值:  ");
    85         pqueue.printMy(a);
    86     }
    87     
    88 }

    总之,对于优先队列中所有的操作都可以在   O(logn)  的时间复杂度内完成。

  • 相关阅读:
    最近看到C#里面的抽象类和接口,还有索引器。
    Memcached服务端自动启动
    python操作MySQL数据库
    Linux开放端口
    关于数组的几道面试题
    这群超酷的开发者,是如何轻松搞定软件开发?
    五分钟开发好你的第一个人工智能应用
    Case Study: 技术和商业的结合点在哪里?
    【江湖趣事】话说开源界和微软的那些往日恩怨
    评微软收购GitHub
  • 原文地址:https://www.cnblogs.com/xiaxj/p/7410046.html
Copyright © 2011-2022 走看看