您的位置:首页 > 其它

算法导论练习6.5-8 k路合并

2013-09-05 16:30 316 查看
题目:

请给出一个时间为O(nlgk)、用来将k个已排序链表合并为一个排序链表的算法。此处n为所有输入链表中元素的总数。(提示:用一个最小堆来做k路合并。

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



最终结果如下图所示:



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

#include <iostream>
#include <vector>
#include <list>
#include <iterator>
#include <cstdlib>
using namespace std;

template<class T> class MinHeap
{
public:
MinHeap();
MinHeap(const size_t size);
~MinHeap();
T get_min() const;
void delete_min();
void insert_element(const T& e);
void adjust_min_heap(const size_t i);
size_t get_heap_size() const;
int compare(const T& t1,const T& t2);
private:
T *heap;
size_t heap_size;
};

template<class T>
MinHeap<T>::MinHeap():heap(NULL),heap_size(0){}

template<class T>
MinHeap<T>::MinHeap(const size_t size)
{
if(!heap)
delete [] heap;
heap = new T[size+1];
heap_size = 0;
}

template<class T>
MinHeap<T>::~MinHeap()
{
if(!heap)
delete [] heap;
heap_size = 0;
}

template<class T>
T MinHeap<T>::get_min() const
{
if(heap_size > 0)
return heap[1];
else
return T();
}

template<class T>
void MinHeap<T>::delete_min()
{
if(heap_size > 0)
{
heap[1] = heap[heap_size];
heap_size = heap_size - 1;
adjust_min_heap(1);
}
else
{
cout<<"Error: the min heap is empty"<<endl;
}
}

template<class T>
void MinHeap<T>::insert_element(const T& e)
{
size_t i,parent;
T temp;
heap_size = heap_size + 1;
heap[heap_size] = e;
i = heap_size;
parent = i/2;
while(i>1 && compare(heap[parent],heap[i]) > 0)
{
temp = heap[parent];
heap[parent] = heap[i];
heap[i] = temp;
i = parent;
parent = i/2;
}
}

template<class T>
void MinHeap<T>::adjust_min_heap(const size_t i)
{
size_t left,right,least;
T temp;
left = i*2;
right = i*2+1;
if(left <= heap_size && compare(heap[left],heap[i]) < 0)
least = left;
else
least = i;
if(right <= heap_size && compare(heap[right],heap[least]) < 0)
least = right;
if(least != i)
{
temp = heap[least];
heap[least] = heap[i];
heap[i] = temp;
adjust_min_heap(least);
}
}
template<class T>
size_t MinHeap<T>::get_heap_size() const
{
return heap_size;
}

template<class T>
int MinHeap<T>::compare(const T& t1,const T& t2)
{
return (*t1-*t2);
}

const static int k = 3;

int main()
{

list<int> lists[k];
list<int>::iterator iters[k];
list<int> retlist;
list<int>::iterator retiter;
list<int>::iterator iter;
MinHeap<list<int>::iterator> minheap(k);

//first list <12,24,52>
lists[0].push_back(12);
lists[0].push_back(24);
lists[0].push_back(52);
cout<<"First list: ";
for(iter=lists[0].begin();iter != lists[0].end();++iter)
cout<<*iter<<"->";
cout<<"NULL"<<endl;
//second list <9,32>
lists[1].push_back(9);
lists[1].push_back(32);
cout<<"Second list: ";
for(iter=lists[1].begin();iter != lists[1].end();++iter)
cout<<*iter<<"->";
cout<<"NULL"<<endl;
//third list <34,42,78>
lists[2].push_back(34);
lists[2].push_back(42);
lists[2].push_back(78);
cout<<"Third list: ";
for(iter=lists[2].begin();iter != lists[2].end();++iter)
cout<<*iter<<"->";
cout<<"NULL"<<endl;
iters[0] = lists[0].begin();
iters[1] = lists[1].begin();
iters[2] = lists[2].begin();

minheap.insert_element(iters[0]);
minheap.insert_element(iters[1]);
minheap.insert_element(iters[2]);

while(minheap.get_heap_size())
{
iter = minheap.get_min() ;
retlist.push_back(*iter);
minheap.delete_min();
++iter;
if(iter != lists[0].end() && iter != lists[1].end()
&&iter != lists[2].end())
minheap.insert_element(iter);
}
cout<<"Merge the there list is: "<<endl;
for(retiter = retlist.begin();retiter!= retlist.end();retiter++)
cout<<*retiter<<"->";
cout<<"NULL"<<endl;
exit(0);
}


测试结果:



转自:http://www.cnblogs.com/Anker/archive/2013/01/24/2874569.html

我按照上面的写了代码,总是遇到错误说:在画红线的地方

if(it!=lists[0].end() && it!=lists[1].end() && it!=lists[2].end()):

总是报错:list iterator incompatible:

#include<iostream>
#include<string>
#include<list>
#include<algorithm>
using namespace std;

int left(int i) { return 2*i;}
int right(int i){ return 2*i+1;}
int parent(int i) { return i/2;}

template<class T>
class MinHeap
{
private:
T *heap;
int heapSize;
public:

MinHeap(const int size);
~MinHeap();

void adjustMinHeap(int i);

void insert(const T& e);
T extractMin();
T getMin();
void deleteMin();

void print();
int getHeapSize(){ return heapSize;}
int comp(const T& a,const T& b) { return (*a)-(*b);}
};

template<class T>
MinHeap<T>::MinHeap(const int size)
{
heap=new T[size+1];
heapSize=0;
}
template<class T>
MinHeap<T>::~MinHeap()
{
delete[] heap;
heapSize=0;
}

template<class T>
void MinHeap<T>::insert(const T& e)
{
heapSize++;
heap[heapSize]=e;//从这可以看出第0个不存
int i=heapSize;
int parentNode=parent(i);
while(i>1 && comp(heap[parentNode],heap[i])>0) //注意,T里面的类型为Iter迭代器类型,不能是这么来比较heap[parentNode]>heap[i].
{
swap(heap[parentNode],heap[i]);
i=parentNode;
parentNode=parent(i);
}
}

template<class T>
void MinHeap<T>::adjustMinHeap(int i)
{
int l=left(i);
int r=right(i);
int smallest;
if(l<=heapSize && comp(heap[l],heap[i])<0 )//l<=heapSize必须在前面,为什么,因为如果在后面,heap[l]将访问冲突
smallest=l;
else
smallest=i;
if(r<=heapSize && comp(heap[r],heap[smallest])<0)
smallest=r;

if(smallest!=i)
{
swap(heap[i],heap[smallest]);
adjustMinHeap(smallest);
}
}
template<class T>
T MinHeap<T>::extractMin()
{
T min=heap[1];
heap[1]=heap[heapSize];
heapSize--;
adjustMinHeap(1);
return min;
}

template<class T>
T MinHeap<T>::getMin()
{
if(heapSize>0)
return heap[1];
else
return T();
}

template<class T>
void MinHeap<T>::deleteMin()
{
heap[1]=heap[heapSize];
heapSize--;
adjustMinHeap(1);
}

template<class T>
void MinHeap<T>::print()
{
for(int i=1;i<=heapSize;i++)
cout<<*heap[i]<<ends;
cout<<endl;
}

//#define k 3
const  int k=3;
int main()
{
//验证MinHeap正确性
/*
MinHeap<int> heap(4);
heap.insert(4);
heap.insert(3);
heap.insert(1);
heap.insert(2);
heap.print(); //1 2 3  4
cout<<"min:"<<heap.extractMin()<<endl; //1
heap.print(); //2 4 3
*/

list<int> lists[k];
typedef list<int>::iterator Iter;
Iter iters[k];

MinHeap<Iter> minHeap(k);

//first list<12,24,52>
lists[0].push_back(12);
lists[0].push_back(24);
lists[0].push_back(52);
cout<<"First list: ";
Iter it;
for(it=lists[0].begin();it!=lists[0].end();it++)
cout<<*it<<"->";
cout<<"NULL"<<endl;

//second list <9,32>
lists[1].push_back(9);
lists[1].push_back(32);
cout<<"Second list: ";
for(it=lists[1].begin();it != lists[1].end();++it)
cout<<*it<<"->";
cout<<"NULL"<<endl;

//third list <34,42,78>
lists[2].push_back(34);
lists[2].push_back(42);
lists[2].push_back(78);
cout<<"Third list: ";
for(it=lists[2].begin();it != lists[2].end();++it)
cout<<*it<<"->";
cout<<"NULL"<<endl;

iters[0]=lists[0].begin();
iters[1]=lists[1].begin();
iters[2]=lists[2].begin();

minHeap.insert(iters[0]);
minHeap.insert(iters[1]);
minHeap.insert(iters[2]);
minHeap.print();
list<int> retlist;
while(minHeap.getHeapSize()!=0)//这个条件最开始没想到
{
it=minHeap.getMin();
retlist.push_back(*it);
minHeap.deleteMin();
++it;

if(it!=lists[0].end() && it!=lists[1].end() && it!=lists[2].end())
{
minHeap.insert(it);
}
}
cout<<"Merge list:"<<endl;
for(it=retlist.begin();it!=retlist.end();it++)
cout<<*it<<"->";
cout<<"NULL"<<endl;

}


搞了2-3个小时没有找到原因,暂时放一放。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: