合并两个或多个有序链表

本文介绍了如何合并两个或多个有序链表。对于两个有序链表,通常采用双指针方法比较节点大小进行合并。而对于多个有序链表,可以使用堆(优先队列)策略,将链表头部节点放入堆中,或者所有节点一次性插入并解决自定义指针类型的排序问题。此外,还探讨了两两合并的方法,通过依次合并两个链表来逐步整合所有链表。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、合并两个有序链表

        常规思路:双指针,判断结点大小。

Node *MergeTwoList(Node *head1, Node *head2) {
    Node *i = head1->next;
    Node *j = head2->next;
    Node *nhead = new Node(-1);
    Node *k = nhead;
    while(i != nullptr && j != nullptr) {
        if(i->val <= j->val) {
            k->next = i;
            i = i->next;
            k = k->next;
        } else if(i->val > j->val) {
            k->next = j;
            j = j->next;
            k = k->next;
        }
    }
    if(i != nullptr) {
        k->next = i;
    } else {
        k->next = j;
    }
    return nhead;
}

二、合并多个有序链表

2.1 堆(优先队列)

        参考合并两个有序链表,可以设置一个堆,将每个链表的第一个结点插入其中;或者将全部结点一股脑插入进去。

        注意:这里在使用C++的优先队列(堆)时,遇到了一个问题,如果队列中的元素是自定义指针类型时,重载运算符失效了,无法完成排序工作。具体解决方法见

priority_queue元素为指针时,重载运算符失效_萧国浪子的博客-优快云博客使用priority_queue构造最大最小堆时,发现priority_queue中元素为指针时,stdgreater/stdless函数并不能调用到自定义数据的重载运算符,排序结果是根据指针地址大小计算的,从而导致最大最小堆失效。失效的最小堆,可以看到是按照指针地址排序的。.........icon-default.png?t=O83Ahttps://blog.youkuaiyun.com/auccy/article/details/126119520

struct Node {
    int val;
    Node *next;
    Node(int v) {
        val = v;
        next = nullptr;
    }
};

struct NodeCmp {
    bool operator ()(Node *a, Node *b){  
        return a->val > b->val;//最小值优先  
    }  
};

Node *MergeKLists1(vector<Node*> &lists) {
    priority_queue <Node*, vector<Node*>, NodeCmp> q;
    for (auto node: lists) {
        if(node != nullptr) {
            q.push(node);
        }
    }
    Node *head = new Node(-1);
    Node *cur = head;
    while (!q.empty()) {
        auto top = q.top(); q.pop();
        cur->next = top; 
        cur = cur->next;
        if(top->next) {
            q.push(top->next);
        }
    }
    return head;
}

2.2 两两合并

Node *MergeKLists2(vector<Node*> &lists) {
    queue<Node*> q;
    for(auto node : lists) {
        q.push(node);
    }
    while(q.size() >= 2) {
        Node *l1 = q.front(); q.pop();
        Node *l2 = q.front(); q.pop();
        Node *nlist = MergeTwoList(l1, l2);
        q.push(nlist);
    }
    return q.front();
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值