合并k个增序链表

来源:互联网 发布:windows如何快捷锁屏 编辑:程序博客网 时间:2024/04/29 22:27

合并k个增序链表

问题

归并排序是一个比较简单的算法,特别是二路归并排序,且用数组存储各个数列时。修改索引只需要简单的++操作即可。

但是如果换成链表,将二路换成多路,对链表操作接触不多的还是值得注意练习下的。

算法

多个链表的归并操作,其实容易混淆的就是指针的指向问题。A链表中某节点指向B中某节点,指完之后容易弄混,或者破坏了原有链表的关系而未保存导致遗漏。

只要把每次比较过后指针指向的修改操作统一起来,问题就很简单了。

此处用2个指针来保存头节点head,前一节点prev,用一个指针的指针min来修改索引完成++操作。当然,这种用法也相当于是限于c++类有指针的语言哈。没有指针的或者可以用引用来替代指针。

算法步骤:
1、遍历所有头节点找到最小的一个头节点。用min指向该头节点的地址。
2、如果是第一个节点,min指向的节点赋值给head与prev。修改min指向的头节点,令其指向其后一个节点。
3、如果不是第一个节点,令prev的后继指向min指向的节点。更新prev指向当前节点。++操作。

代码

代码如下:

/** * @brief MergeLists::mergSome * @param heads   要合并链表的头结点 * @return */MergeLists::Node *MergeLists::mergSome(std::vector<MergeLists::Node *> heads){    Node*  head=NULL;       ///<头节点,返回的指针    Node** min=NULL;        ///<指向最小节点的指针的指针,用于修改索引    Node* prev=NULL;        ///<新链表中前一节点。因为要将前一节点后继修改指向当前节点,所以保存    std::vector<MergeLists::Node *>::iterator iter;    while(!heads.empty()){        min=NULL;        for(iter=heads.begin();iter!=heads.end();iter++){            if((*iter)==NULL)                 continue;            if(min==NULL)                     min=&(*iter);            if((*min)->val>(*iter)->val)      min=&(*iter);        }        //说明所有链表都遍历到了最后节点        if(min==NULL)                         break;        //头节点指针,只赋值一次        if(head==NULL){            head=*min;                  //头节点赋值            prev=head;                  //更新前一节点指针            *min=(*min)->next;          //让当前节点的链表头指向当前节点的下一节点。++操作        }else{            prev->next=*min;            //前一节点的后继指向当前节点            prev=*min;                  //更新前一节点值            *min=(*min)->next;          //++操作。        }    }    for(Node* p=head;p;p=p->next)        std::cout<<p<<" "<<p->val<<std::endl;}

生成链表代码如下:

MergeLists::Node *MergeLists::makeList(std::vector<int> v){    Node* head=NULL;    Node* cur=NULL;    Node* prev=NULL;    std::vector<int>::iterator iter;    for(iter=v.begin();iter!=v.end();iter++){        cur=new Node(*iter);        if(head==NULL)            head=cur;        if(prev!=NULL)            prev->next=cur;        prev=cur;    }    return head;}

头文件:

class MergeLists{public:    MergeLists(){};    virtual ~MergeLists(){};    class Node{    public:        Node(){};        Node(int v):val(v),next(NULL){};        int val;        Node* next;    };    Node* mergTwo(Node* f,Node* s);    Node* mergSome(std::vector<Node*> heads);    Node* makeList(std::vector<int> v);};

测试

测试代码如下:

  MergeLists merge;  MergeLists::Node* first=merge.makeList(std::vector<int>({1,2,4,6}));  MergeLists::Node* sec=merge.makeList(std::vector<int>({3,5,7,9}));  MergeLists::Node* third=merge.makeList(std::vector<int>({3,8,9,12,13}));  merge.mergSome(std::vector<MergeLists::Node*>({first,sec,third}));

不支持vector列表初始化的拷贝赋值下吧。:)

测试结果:

0x14080160 10x14068428 20x1406ef70 30x14012a00 30x14057508 40x14074700 50x1406eed0 60x1405a370 70x1406dc20 80x14068560 90x14018180 90x1404f7f8 120x14077570 13
0 0