• 《算法导论》练习6.58—最小堆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 }

    程序测试结果如下所示:

  • 相关阅读:
    js数组与字符串的相互转换方法
    js页面跳转常用的几种方式
    js刷新页面方法大全
    IIS上开启反向代理实现Vue项目接口跨域处理
    【问题解决记录】vue解决低版本安卓与ios10以下系统兼容性问题
    【解决问题记录】https网站中请求http资源接口报错与netERRSSLPROTOCOLERROR错误的解决
    indexedDb数据库基本操作
    Object常用方法
    htmlToTex
    禁止鼠标右键保存/拖动/选中/复制 图片/文字
  • 原文地址:https://www.cnblogs.com/Anker/p/2874569.html
Copyright © 2020-2023  润新知