• 《算法导论》读书笔记(二)


    《算法导论》读书笔记之第6章 堆排序

      本章开始介绍了堆的基本概念,然后引入最大堆和最小堆的概念。全章采用最大堆来介绍堆的操作,两个重要的操作是调整最大堆和创建最大堆,接着着两个操作引进了堆排序,最后介绍了采用堆实现优先级队列。

    1、堆

      堆给人的感觉是一个二叉树,但是其本质是一种数组对象,因为对堆进行操作的时候将堆视为一颗完全二叉树,树种每个节点与数组中的存放该节点值的那个元素对应。所以堆又称为二叉堆,堆与完全二叉树的对应关系如下图所示:

      通常给定节点i,可以根据其在数组中的位置求出该节点的父亲节点、左右孩子节点,这三个过程一般采用宏或者内联函数实现。书上介绍的时候,数组的下标是从1开始的,所有可到:PARENT(i)=i/2  LEFT(i) = 2*i   RIGHT(i) = 2*i+1。

      根据节点数值满足的条件,可以将分为最大堆和最小堆。最大堆的特性是:除了根节点以外的每个节点i,有A[PARENT(i)] >= A[i],最小堆的特性是:除了根节点以外的每个节点i,有A[PARENT(i)] >=A[i]。

      把堆看成一个棵树,有如下的特性:

    (1)含有n个元素的堆的高度是lgn。

    (2)当用数组表示存储了n个元素的堆时,叶子节点的下标是n/2+1,n/2+2,……,n。

    (3)在最大堆中,最大元素该子树的根上;在最小堆中,最小元素在该子树的根上。

    2、保持堆的性质

      堆个关键操作过程是如何保持堆的特有性质,给定一个节点i,要保证以i为根的子树满足堆性质。书中以最大堆作为例子进行讲解,并给出了递归形式的保持最大堆性的操作过程MAX-HEAPIFY。先从看一个例子,操作过程如下图所示:

    从图中可以看出,在节点i=2时,不满足最大堆的要求,需要进行调整,选择节点2的左右孩子中最大一个进行交换,然后检查交换后的节点i=4是否满足最大堆的要求,从图看出不满足,接着进行调整,直到没有交换为止。书中给出了递归形式的为代码,我用C语言实现如下所示:

    复制代码
     1 void adjust_max_heap_recursive(int *datas,int length,int i)
     2 {
     3     int left,right,largest;
     4     int temp;
     5     left = LEFT(i);   //left child
     6     right = RIGHT(i); //right child
     7     //find the largest value among left and rihgt and i.
     8     if(left<=length && datas[left] > datas[i])
     9         largest = left;
    10     else
    11         largest = i;
    12     if(right <= length && datas[right] > datas[largest])
    13         largest = right;
    14     //exchange i and largest
    15     if(largest != i)
    16     {
    17         temp = datas[i];
    18         datas[i] = datas[largest];
    19         datas[largest] = temp;
    20         //recursive call the function,adjust from largest
    21         adjust_max_heap(datas,length,largest);
    22     }
    23 }
    复制代码

      课后习题要求给出其非递归的形式,我想了半天,才搞出来,领悟能力有限啊。非递归就要考虑要循环进行实现,需要考虑的是循环结束条件是什么。对一个给定的节点i,要对其进行调整使其满足最大堆的性质。总的思想是先找出节点i的左右孩子节点,然后从三者中找到最大的节点,如果找到的最大节点就是i,说明i节点满足堆的性质,此时循环就结束了。如果找到的最大节点不是节点i,那么这个时候就要将最大的节点(设为largest)与节点i进行交换,然后从largest节点开始循环进行调整,直到满足条件为止。给出非递归的调整堆程序如下:

    复制代码
     1 void adjust_max_heap(int *datas,int length,int i)
     2 {
     3     int left,right,largest;
     4     int temp;
     5     while(1)
     6     {
     7         left = LEFT(i);   //left child
     8         right = RIGHT(i); //right child
     9         //find the largest value among left and rihgt and i.
    10         if(left <= length && datas[left] > datas[i])
    11             largest = left;
    12         else
    13             largest = i;
    14         if(right <= length && datas[right] > datas[largest])
    15             largest = right;
    16         //exchange i and largest
    17         if(largest != i)
    18         {
    19             temp = datas[i];
    20             datas[i] = datas[largest];
    21             datas[largest] = temp;
    22             i = largest;
    23             continue;
    24         }
    25         else
    26             break;
    27     }
    28 }
    复制代码

     3、建堆

      建立最大堆的过程是自底向上地调用最大堆调整程序将一个数组A[1.....N]变成一个最大堆。将数组视为一颗完全二叉树,从其最后一个非叶子节点(n/2)开始调整。调整过程如下图所示:

     书中给出了创建堆的为代码,我用C语言实现如下:

    复制代码
    1 void build_max_heap(int *datas,int length)
    2 {
    3     int i;
    4     //build max heap from the last parent node
    5     for(i=length/2;i>0;i--)
    6         adjust_max_heap(datas,length,i);
    7 }
    复制代码

    4、堆排序算法
      堆排序算法过程为:先调用创建堆函数将输入数组A[1...n]造成一个最大堆,使得最大的值存放在数组第一个位置A[1],然后用数组最后一个位置元素与第一个位置进行交换,并将堆的大小减少1,并调用最大堆调整函数从第一个位置调整最大堆。给出堆数组A={4,1,3,16,9,10,14,8,7}进行堆排序简单的过程如下:

    (1)创建最大堆,数组第一个元素最大,执行后结果下图:

    (2)进行循环,从length(a)到2,并不断的调整最大堆,给出一个简单过程如下:

    书中给出了对排序为代码,我用C语言实现如下所示:

    复制代码
     1 void heap_sort(int *datas,int length)
     2 {
     3     int i,temp;
     4     //bulid max heap
     5     build_max_heap(datas,length);
     6     i=length;
     7     //exchange the first value to the last unitl i=1
     8     while(i>1)
     9     {
    10         temp = datas[i];
    11         datas[i] = datas[1];
    12         datas[1] =temp;
    13         i--;
    14         //adjust max heap,make sure the fisrt value is the largest
    15         adjust_max_heap(datas,i,1);
    16     }
    17 }
    复制代码

       结合上面的调整堆和创建堆 的过程,写个简单测试程序连续堆排序,程序如下所示:

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 
      4 //array's index begins 1,not 0
      5 
      6 #define PARENT(i)  (i/2)
      7 #define LEFT(i)    (i*2)
      8 #define RIGHT(i)   (i*2+1)
      9 #define NOTNUSEDATA   -65536
     10 
     11 void adjust_max_heap(int *datas,int length,int i);
     12 void adjust_max_heap_recursive(int *datas,int length,int i);
     13 void build_max_heap(int *datas,int length);
     14 void heap_sort(int *datas,int length);
     15 
     16 int main()
     17 {
     18     int i;
     19     //array's index begin 1
     20     int datas[11] = {NOTNUSEDATA,5,3,17,10,84,19,6,22,9,35};
     21     heap_sort(datas,10);
     22     for(i=1;i<11;++i)
     23         printf("%d ",datas[i]);
     24     printf("
    ");
     25     exit(0);
     26 }
     27 
     28 void adjust_max_heap_recursive(int *datas,int length,int i)
     29 {
     30     int left,right,largest;
     31     int temp;
     32     left = LEFT(i);   //left child
     33     right = RIGHT(i); //right child
     34     //find the largest value among left and rihgt and i.
     35     if(left<=length && datas[left] > datas[i])
     36         largest = left;
     37     else
     38         largest = i;
     39     if(right <= length && datas[right] > datas[largest])
     40         largest = right;
     41     //exchange i and largest
     42     if(largest != i)
     43     {
     44         temp = datas[i];
     45         datas[i] = datas[largest];
     46         datas[largest] = temp;
     47         //recursive call the function,adjust from largest
     48         adjust_max_heap(datas,length,largest);
     49     }
     50 }
     51 void adjust_max_heap(int *datas,int length,int i)
     52 {
     53     int left,right,largest;
     54     int temp;
     55     while(1)
     56     {
     57         left = LEFT(i);   //left child
     58         right = RIGHT(i); //right child
     59         //find the largest value among left and rihgt and i.
     60         if(left <= length && datas[left] > datas[i])
     61             largest = left;
     62         else
     63             largest = i;
     64         if(right <= length && datas[right] > datas[largest])
     65             largest = right;
     66         //exchange i and largest
     67         if(largest != i)
     68         {
     69             temp = datas[i];
     70             datas[i] = datas[largest];
     71             datas[largest] = temp;
     72             i = largest;
     73             continue;
     74         }
     75         else
     76             break;
     77     }
     78 }
     79 void build_max_heap(int *datas,int length)
     80 {
     81     int i;
     82     //build max heap from the last parent node
     83     for(i=length/2;i>0;i--)
     84         adjust_max_heap(datas,length,i);
     85 }
     86 void heap_sort(int *datas,int length)
     87 {
     88     int i,temp;
     89     //bulid max heap
     90     build_max_heap(datas,length);
     91     i=length;
     92     //exchange the first value to the last unitl i=1
     93     while(i>1)
     94     {
     95         temp = datas[i];
     96         datas[i] = datas[1];
     97         datas[1] =temp;
     98         i--;
     99         //adjust max heap,make sure the fisrt value is the largest
    100         adjust_max_heap(datas,i,1);
    101     }
    102 }

    程序测试结果如下所示:


    从结果可以看出按照最大堆进行堆排序最终使得结果是从小到大排序(非递减的)。

    堆排序算法时间复杂度:调整堆过程满足递归式T(n)<=T(2n/3)+θ(1),有master定义可以知道T(n) = O(lgn),堆排序过程中执行一个循环,调用最大堆调整函数,总的时间复杂度为O(nlgn)。

    5、问题

    (1)在创建最大堆的过程中,为什么从最后一个非叶子节点(n/2)开始到第一个非叶子(1)结束,而不是从第一个非叶子节点(1)到最后一个非叶子节点(n/2)结束呢?

    我的想法是:如果是从第一个非叶子节点开始创建堆,有可能导致创建的堆不满足堆的性质,使得第一个元素不是最大的。这样做只是使得该节点的和其左右孩子节点满足堆性质,不能确保整个树满足堆的性质。如果最大的节点在叶子节点,那么将可能不会出现在根节点中。例如下面的例子:

    从图中可以看出,从第一个非叶子节点开始创建最大堆,最后得到的结果并不是最大堆。而从最后一个非叶子节点开始创建堆时候,能够保证该节点的子树都满足堆的性质,从而自底向上进行调整堆,最终使得满足最大堆的性质。

    《算法导论》读书笔记之第6章 优先级队列

    1、概述

      队列是一种满足先进先出(FIFO)的数据结构,数据从队列头部取出,新的数据从队列尾部插入,数据之间是平等的,不存在优先级的。这个就类似于普通老百姓到火车站排队买票,先来的先买票,每个人之间是平等的,不存在优先的权利,整个过程是固定不变的。而优先级队列可以理解为在队列的基础上给每个数据赋一个权值,代表数据的优先级。与队列类似,优先级队列也是从头部取出数据,从尾部插入数据,但是这个过程根据数据的优先级而变化的,总是优先级高的先出来,所以不一定是先进先出的。这个过就类似于买火车票时候军人比普通人优先买,虽然军人来的晚,但是军人的优先级比普通人高,总是能够先买到票。通常优先级队列用在操作系统中的多任务调度,任务优先级越高,任务优先执行(类似于出队列),后来的任务如果优先级比以前的高,则需要调整该任务到合适的位置,以便于优先执行,整个过程总是使得队列中的任务的第一任务的优先级最高。

      优先级队列有两种:最大优先级队列和最小优先级队列,这两种类别分别可以用最大堆和最小堆实现。书中介绍了基于最大堆实现的最大优先级队列。一个最大优先级队列支持的操作如下操作:

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

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

    EXTRACT_MAX(S):去掉并返回S中的具有最大关键字的元素

    INCREASE_KEY(S,x,k):将元素x的关键字的值增加到k,这里k值不能小于x的原关键字的值。

    2、最大优先级队列操作实现

      采用最大堆实现最大优先级队列,关于最大堆可以参见上一篇日志http://www.cnblogs.com/Anker/archive/2013/01/23/2873422.html

    (1)HEAP_MAXIMUM用O(1)时间实现MAXIMUM(S)操作,即返回最大堆第一个元素的值即可(return A[1])。

    (2)HEAP_EXTRACT_MAX实现EXTRACT_MAX操作,删除最大堆中第一个元素,然后调整堆。操作过程如下:将最堆中最后一个元素复制到第一个位置,删除最后一个节点(将堆的大小减少1),然后从第一个节点位置开始调整堆,使得称为新的最大堆。操作过程如下图所示:

    伪代码描述如下:

    复制代码
    1 HEAD_EXTRACT_MAX(A)
    2  if heap_size[A]<1
    3    ther error
    4  max = A[1]
    5  A[1] = A[heap_size[A]];
    6  heap_size[A] = heap_size[A]-1
    7  adjust_max_heap(A,1)
    8  return MAX
    复制代码

    (3)HEAP_INCREASE_KEY实现INCREASE_KEY,通过下标来标识要增加的元素的优先级key,增加元素后需要调整堆,从该节点的父节点开始自顶向上调整。操作过程如下图所示:

    伪代码描述如下:

    复制代码
    1 HEAP_INCREASE_KEY(A,i,key)
    2    if key < A[i]
    3      then error
    4    A[i] = key
    5   while i>1 && A[PARENT(i)] <A[i]
    6        do exchange A[i] <-> A[PARENT(i)]
    7        i = PARENT(i)
    复制代码

    (4)MAX_HEAP_INSERT实现INSERT操作,向最大堆中插入新的关键字。新的关键字插入在优先级的队尾部,然后从尾部的父节点开始自顶向上调整堆伪代码描述如下:

    1 MAX_HEAP_INSERT(A,key)
    2   heap_size[A] = heap_size[A]+1
    3   A[heap_size[A]] = -0;
    4   HEAP_INCREASE_KEY(A,heap_size[A],key)

     3、实例

     问题描述如下:优先级队列中有多个事件发生,每个事件有自己独立的优先级,优先级是非负数,数值越大优先级越高。采用最大优先级队列模拟事件执行的优先顺序。具体操作包括:

    (1)向优先级队列中添加一个新事件

    (2)获取优先级队列中优先级最高的事件

    (3)删除优先级队列中指定位置的事件

    (4)增加优先级队列中指定位置事件的优先级

    (5)降低优先级队列中指定位置事件的优先级

    采用C++语言实现,完整程序如下所示:

      1 #include <iostream>
      2 #include <string>
      3 #include <cstdlib>
      4 using namespace std;
      5 
      6 const static int QUEUELEN = 100;
      7 
      8 class Event
      9 {
     10 public:
     11     Event():eventname(""),priority(-1){};
     12     Event(const string &en,const int p):eventname(en),priority(p){};
     13     Event(const Event& en)
     14     {
     15         eventname = en.eventname;
     16         priority = en.priority;
     17     }
     18     ~Event(){};
     19     int get_event_priority()const
     20     {
     21         return priority;
     22     }
     23     string get_event_name()const
     24     {
     25         return eventname;
     26     }
     27     void increase_event_priority(const int k)
     28     {
     29         priority = priority + k;
     30     }
     31     void decrease_event_priority(const int k)
     32     {
     33          priority = priority - k;
     34     }
     35     void show_event() const
     36     {
     37         cout<<"Eventname is: ("<<eventname<<") and the priority is: "<<priority<<endl;
     38     }
     39 private:
     40     string eventname;
     41     int priority;
     42 };
     43 class PriorityQueue
     44 {
     45 public:
     46     PriorityQueue();
     47     void adjust_event(int index);
     48     Event get_event()const;
     49     void insert_event(const Event& en);
     50     void increase_event_priority(int pos,int k);
     51     Event delete_event(int pos);
     52     void show_events() const;
     53     ~PriorityQueue();
     54 private:
     55     Event *events;
     56     int length;
     57 };
     58 
     59 PriorityQueue::PriorityQueue()
     60 {
     61     events = new Event[QUEUELEN];
     62     length = 0;
     63 }
     64 
     65 PriorityQueue::~PriorityQueue()
     66 {
     67     if(!events)
     68         delete [] events;
     69     length = 0;
     70 }
     71 //adjust max heap 
     72 void PriorityQueue::adjust_event(int index)
     73 {
     74     int left,right,largest;
     75     Event temp;
     76     while(1)
     77     {
     78         left = index*2;
     79         right = index*2+1;
     80         if(left <= length &&
     81            events[left].get_event_priority() > events[index].get_event_priority())
     82             largest = left;
     83         else
     84             largest = index;
     85         if(right <= length &&
     86            events[right].get_event_priority() > events[largest].get_event_priority())
     87             largest = right;
     88         if(largest != index)
     89         {
     90             temp = events[index];
     91             events[index] = events[largest];
     92             events[largest] = temp;
     93             index = largest;
     94         }
     95         else
     96             break;
     97     }
     98 }
     99 Event PriorityQueue::get_event()const
    100 {
    101     if(length != 0)
    102         return events[1];
    103     else
    104         return Event();
    105 }
    106 
    107 void PriorityQueue::insert_event(const Event& en)
    108 {
    109     length = length + 1;
    110     events[length] = en;
    111     increase_event_priority(length,0);
    112 }
    113 
    114 void PriorityQueue::increase_event_priority(int pos,int k)
    115 {
    116     int i,parent;
    117     Event temp;
    118     if(pos > length)
    119     {
    120         cout<<"error: the pos index is larger than queue length"<<endl;
    121         return;
    122     }
    123     events[pos].increase_event_priority(k);
    124     i = pos;
    125     parent = i/2;
    126     while(i>1
    127           && events[parent].get_event_priority() < events[i].get_event_priority())
    128     {
    129         temp = events[i];
    130         events[i] = events[parent];
    131         events[parent] = temp;
    132         i = parent;
    133         parent = i/2;
    134     }
    135 }
    136 
    137 Event PriorityQueue::delete_event(int pos)
    138 {
    139     Event reten;
    140     if(pos > length)
    141     {
    142         cout<<"Error:pos index is larger than queue length"<<endl;
    143         return reten;
    144     }
    145     reten = events[pos];
    146     events[pos] = events[length];
    147     length--;
    148     adjust_event(pos);
    149     return reten;
    150 }
    151 void PriorityQueue::show_events() const
    152 {
    153     if(length == 0)
    154     {
    155         cout<<"There is no any event in the priority queue"<<endl;
    156     }
    157     else
    158     {
    159         cout<<"There are "<<length<<" events in the priority queue."<<endl;
    160         for(int i=1;i<=length;i++)
    161         {
    162             events[i].show_event();
    163         }
    164     }
    165 
    166 }
    167 int main()
    168 {
    169     PriorityQueue pqueue;
    170     Event en;
    171     Event en1("fork",2);
    172     Event en2("exec",3);
    173     Event en3("wait",1);
    174     Event en4("signal",6);
    175     Event en5("pthread_create",5);
    176     pqueue.insert_event(en1);
    177     pqueue.insert_event(en2);
    178     pqueue.insert_event(en3);
    179     pqueue.insert_event(en4);
    180     pqueue.insert_event(en5);
    181     pqueue.show_events();
    182     cout<<"
    The max priority event is: "<<endl;
    183     en = pqueue.get_event();
    184     en.show_event();
    185     cout<<"
    Increse event3 by 7"<<endl;
    186     pqueue.increase_event_priority(3,7);
    187     en = pqueue.get_event();
    188     en.show_event();
    189     pqueue.show_events();
    190     cout<<"
    Delete the first event:"<<endl;
    191     pqueue.delete_event(1);
    192     pqueue.show_events();
    193     exit(0);
    194 }

    程序测试结果如下所示:


    4、问题

    (1)如何使用优先级队列实现一个先进先出的队列和先进后出的栈?

      我的想法是:队列中的元素是先进先出(FIFO)的,因此可以借助最小优先级队列实现队列。具体思想是,给队列中的每个元素赋予一个权值,权值从第一个元素到最后一个依次递增(如果采用数组实现的话,可以用元素所在的下标作为优先级,优先级小的先出队列),元素出队列操作每次取优先级队列第一个元素,取完之后需要堆最小优先级队列进行调整,使得第一个元素的优先级最小。栈中的元素与队列刚好相反,元素是先进后出(FILO),因此可以采用最大优先级队列进行实现,与用最小优先级队列实现队列思想类似,按照元素出现的顺序进行标记元素的优先级,数据越是靠后,优先级越高。

      举例说明采用最小优先级队列实现先进先出队列,现在有一组数A={24,15,27,5,43,87,34}共六个数,假设数组下标从1开始,以元素所在数组中的下标为优先级创建优先级队列,队列中元素出入时候调整最小优先级队列。操作过程如下图所示:

    《算法导论》练习6.5-8—最小堆k路合并

      《算法导论》第六章主要内容是关于堆和优先级队列,书中给出了一个练习题,非常有有意思,今天好好研究练习一下。题目如下:请给出一个时间为O(nlgk)、用来将k个已排序链表合并为一个排序链表的算法。此处n为所有输入链表中元素的总数。(提示:用一个最小堆来做k路合并)。

      看到题目第个想到的是归并排序过程中的归并操作子过程,从头开始两两比较,找出最小的,然后接着往后比较,常用的是2路归并。而题目给的是k个已排好序的链表(k>=2)。如果没有提示,我半天不知道如何去实现,幸好提示说用最小堆来做k路合并,于是我想到可以这样做:创建一个大小为k的数组,将k个链表中的第一个元素依次存放到数组中,然后将数组调整为最小堆,这样保证数组的第一个元素是最小的,假设为min,将min从最小堆取出并存放到最终结果的链表中,此时将min所在链表的下一个元素到插入的最小堆中,继续上面的操作,直到堆中没有元素为止。举个例子如下图所示(只给出不部分操作):

    最终结果如下图所示:

    现在采用C++语言,借助STL实现此过程,链表采用list,最小堆中存放的是list的迭代器,表示list中元素的位置。完整程序如下:

    复制代码
      1 #include <iostream>
      2 #include <vector>
      3 #include <list>
      4 #include <iterator>
      5 #include <cstdlib>
      6 using namespace std;
      7 
      8 template<class T> class MinHeap
      9 {
     10 public:
     11     MinHeap();
     12     MinHeap(const size_t size);
     13     ~MinHeap();
     14     T get_min() const;
     15     void delete_min();
     16     void insert_element(const T& e);
     17     void adjust_min_heap(const size_t i);
     18     size_t get_heap_size() const;
     19     int compare(const T& t1,const T& t2);
     20 private:
     21     T *heap;
     22     size_t heap_size;
     23 };
     24 
     25 template<class T>
     26 MinHeap<T>::MinHeap():heap(NULL),heap_size(0){}
     27 
     28 template<class T>
     29 MinHeap<T>::MinHeap(const size_t size)
     30 {
     31     if(!heap)
     32         delete [] heap;
     33     heap = new T[size+1];
     34     heap_size = 0;
     35 }
     36 
     37 template<class T>
     38 MinHeap<T>::~MinHeap()
     39 {
     40     if(!heap)
     41         delete [] heap;
     42     heap_size = 0;
     43 }
     44 
     45 template<class T>
     46 T MinHeap<T>::get_min() const
     47 {
     48     if(heap_size > 0)
     49         return heap[1];
     50     else
     51         return T();
     52 }
     53 
     54 template<class T>
     55 void MinHeap<T>::delete_min()
     56 {
     57     if(heap_size > 0)
     58     {
     59         heap[1] = heap[heap_size];
     60         heap_size = heap_size - 1;
     61         adjust_min_heap(1);
     62     }
     63     else
     64     {
     65         cout<<"Error: the min heap is empty"<<endl;
     66     }
     67 }
     68 
     69 template<class T>
     70 void MinHeap<T>::insert_element(const T& e)
     71 {
     72     size_t i,parent;
     73     T temp;
     74     heap_size = heap_size + 1;
     75     heap[heap_size] = e;
     76     i = heap_size;
     77     parent = i/2;
     78     while(i>1 && compare(heap[parent],heap[i]) > 0)
     79     {
     80         temp = heap[parent];
     81         heap[parent] = heap[i];
     82         heap[i] = temp;
     83         i = parent;
     84         parent = i/2;
     85     }
     86 }
     87 
     88 template<class T>
     89 void MinHeap<T>::adjust_min_heap(const size_t i)
     90 {
     91     size_t left,right,least;
     92     T temp;
     93     left = i*2;
     94     right = i*2+1;
     95     if(left <= heap_size && compare(heap[left],heap[i]) < 0)
     96         least = left;
     97     else
     98         least = i;
     99     if(right <= heap_size && compare(heap[right],heap[least]) < 0)
    100         least = right;
    101     if(least != i)
    102     {
    103         temp = heap[least];
    104         heap[least] = heap[i];
    105         heap[i] = temp;
    106         adjust_min_heap(least);
    107     }
    108 }
    109 template<class T>
    110 size_t MinHeap<T>::get_heap_size() const
    111 {
    112     return heap_size;
    113 }
    114 
    115 template<class T>
    116 int MinHeap<T>::compare(const T& t1,const T& t2)
    117 {
    118     return (*t1-*t2);
    119 }
    120 
    121 const static int k = 3;
    122 
    123 int main()
    124 {
    125 
    126     list<int> lists[k];
    127     list<int>::iterator iters[k];
    128     list<int> retlist;
    129     list<int>::iterator retiter;
    130     list<int>::iterator iter;
    131     MinHeap<list<int>::iterator> minheap(k);
    132 
    133     //first list <12,24,52>
    134     lists[0].push_back(12);
    135     lists[0].push_back(24);
    136     lists[0].push_back(52);
    137     cout<<"First list: ";
    138     for(iter=lists[0].begin();iter != lists[0].end();++iter)
    139           cout<<*iter<<"->";
    140     cout<<"NULL"<<endl;
    141     //second list <9,32>
    142     lists[1].push_back(9);
    143     lists[1].push_back(32);
    144     cout<<"Second list: ";
    145     for(iter=lists[1].begin();iter != lists[1].end();++iter)
    146           cout<<*iter<<"->";
    147     cout<<"NULL"<<endl;
    148     //third list <34,42,78>
    149     lists[2].push_back(34);
    150     lists[2].push_back(42);
    151     lists[2].push_back(78);
    152     cout<<"Third list: ";
    153     for(iter=lists[2].begin();iter != lists[2].end();++iter)
    154           cout<<*iter<<"->";
    155     cout<<"NULL"<<endl;
    156     iters[0] = lists[0].begin();
    157     iters[1] = lists[1].begin();
    158     iters[2] = lists[2].begin();
    159 
    160     minheap.insert_element(iters[0]);
    161     minheap.insert_element(iters[1]);
    162     minheap.insert_element(iters[2]);
    163 
    164     while(minheap.get_heap_size())
    165     {
    166         iter = minheap.get_min() ;
    167         retlist.push_back(*iter);
    168         minheap.delete_min();
    169         ++iter;
    170         if(iter != lists[0].end() && iter != lists[1].end()
    171            &&iter != lists[2].end())
    172             minheap.insert_element(iter);
    173     }
    174     cout<<"Merge the there list is: "<<endl;
    175     for(retiter = retlist.begin();retiter!= retlist.end();retiter++)
    176         cout<<*retiter<<"->";
    177     cout<<"NULL"<<endl;
    178     exit(0);
    179 }
    复制代码

    程序测试结果如下所示:

  • 相关阅读:
    iOS tableHeaderView有默认高度?
    flutter 自定义tabbar 给tabbar添加背景功能
    jar各个版本号的意义
    【转载】springboot + swagger
    分表需要解决的问题 & 基于MyBatis 的轻量分表落地方案
    解决Spring Boot中,通过filter打印post请求的 request body 问题
    SpringBoot自动配置xxxAutoConfiguration 的使用
    Shell
    Spring踩坑记录
    Spring中可复用工具类&&特性记录&&技巧
  • 原文地址:https://www.cnblogs.com/alantu2018/p/8469067.html
Copyright © 2020-2023  润新知