《算法导论》练习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 }

程序测试结果如下所示:

posted @ 2013-01-24 11:23  Rabbit_Dale  阅读(3750)  评论(1编辑  收藏  举报