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


    题目:

    请给出一个时间为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个小时没有找到原因,暂时放一放。

  • 相关阅读:
    Linux系统下ZIP文件解压和压缩命令
    解析XML文件
    数组和集合之间的转换
    数据库密码到期修改密码
    Linux系统中启动jar程序
    JSONArray依赖包
    多态性
    接口----interface
    抽象类
    final关键字
  • 原文地址:https://www.cnblogs.com/youxin/p/3303587.html
Copyright © 2020-2023  润新知