合并两个递增有序单链表为递减有序单链表

有两个不带头结点的单链表,且数据元素为整数型,且递增有序。 (此时假设它输入的时候就已经是递增有序的单链表了)

算法实现目标:将这两个单链表合并为一个递减有序的单链表

思路:可以利用这两个链表本来就是递增有序的特性进行合并,然后再进行逆序,即可得到递减有序链表。

链表类:


//链表类
class List { 
public:
    int val;
    List* next;
public:
    List() : val(0), next(nullptr) { }
    List(int x) : val(x), next(nullptr) { }
    List(int x, List* next) : val(x), next(next) { }
};

合并链表函数
使用了3个指针:now,p1,p2
1.先比较两个链表头结点的数值的大小,选择更小者作为新链表的头结点。

2.此后设置now指向新链表的当前结点,而p1指向链表1未加入新链表的结点,p2指向链表2未加入新链表的结点。

3.p1和p2进行数值比较,选择结点值更小的加入新链表,而p1/p2要指向p1->next/p2->next(即往前移)

4.以此类推,最后有3种情况,即链表1和链表2都全并入新链表或 链表1加入新链表 或 链表2加入新链表。只需要判断p1和p2哪个为空,在now后面接上剩余链表即可(因为已经有序了)

个人觉得该思路的好处是一次遍历即可合并,并且不用额外空间

//该函数作用:合并递增链表为一个新的递增链表
int MergeList1(List* l1, List* l2) { 
    //先判断l1、l2是否为空节点
    if (l1 == nullptr && l2 == nullptr)
        return 0;
    if (l1 == nullptr) return 2;
    if (l2 == nullptr) return 1;

    List *head,*now;
    int flag;

    //选取首结点更小的链表作为头结点,最后返回的也是该链表
    if (l1->val < l2->val) { 
        flag = 1;//选择链表1
        head = now = l1;
        l1 = l1->next;
    }
    else { 
        flag = 2;//选择链表2
        head= now = l2;
        l2 = l2->next;
    }

    //两个都不为nullptr才能继续
    while (l1!=nullptr && l2!=nullptr) { 
        if (l1->val < l2->val) {  //如果l1的结点更小 那么下一个结点应该是l1
            now->next = l1;
            l1 = l1->next;
            now = now->next;
        }
        else { 
            now->next = l2;
            l2 = l2->next;
            now = now->next;
        }
    }

    //此时有3种情况: l1是空 或 l2是空 或 l1和l2都是空
    //如果选择链表1作为头结点 最后要返回的是链表1 因此在now的后面接上链表2 
    if (flag == 1) { 
        now->next = l2;
        l1 = head;
    }
        
    //如果选择链表2作为头结点 最后要返回的是链表2 因此在now的后面接上链表1
    else { 
        now->next = l1;
        l2 = head;
    }
    return flag;
}

逆序函数
三指针法

//该函数作用:将链表逆序(并且返回新的头结点)
List* Reverse(List* l) { 
    List* p1, *p2, *p3;//逆序方法:三指针法
    List* head;
    head = l;
    p1 = l;
    p2 = p1->next;
    p3 = p2->next;
    while (p3!=nullptr) { 
        p2->next = p1;
        p1 = p2;
        p2 = p3;
        p3 = p2->next;
    }
    p2->next = p1;
    head->next = nullptr;
    return p2; //此时p2是新的头结点(即原链表的尾结点) 因此返回p2
}

Show(展示函数)

//该函数作用:展示链表
void Show(List* l) { 
    //cout << "head->";
    while (l != nullptr) { 
        cout << l->val << "->";
        l = l->next;
    }
    cout << "nullptr" << endl;
}

测试程序

//主测试程序
int main() { 
    cout << "本程序为【将两个不带头结点的递增有序单链表(数据元素为整数)合并为递减有序单链表】的算法测试程序" << endl;
    cout << endl;
    int n1, n2;
    List* p1=nullptr, * p2=nullptr;
    List* head1=nullptr, *head2=nullptr;

    //输入链表
    cout << "请输入 链表1 的结点个数:" ;
    cin >> n1;
    for (int i = 1; i <= n1; i++) { 
        cout << "请输入 链表1 的第 " << i << " 个结点的值:";
        int temp1;//值
        cin >> temp1;
        if (i == 1) { 
            p1 = new List(temp1);
            head1 = p1;
            continue;
        }
        p1->next = new List(temp1);
        p1 = p1->next;
    }

    cout << "请输入 链表2 的结点个数:";
    cin >> n2;
    for (int i = 1; i <= n2; i++) { 
        cout << "请输入 链表2 的第 " << i << " 个结点的值:";
        int temp2;//值
        cin >> temp2;
        if (i == 1) { 
            p2 = new List(temp2);
            head2 = p2;
            continue;
        }
        p2->next = new List(temp2);
        p2 = p2->next;
    }

    cout << endl;
    int Lflag;
    cout << "链表1:";
    Show(head1);
    cout << "链表2:";
    Show(head2);
    Lflag = MergeList1(head1, head2);
    //到这里应该已经成功升序合并了
    if (Lflag == 1) { 
        cout << endl;
        cout << "合并链表1和链表2:";
        Show(head1);
        List* temphead = Reverse(head1);
        cout << "合并链表1和链表2并将其逆序:";
        Show(temphead);
    }
    else if (Lflag == 2) { 
        cout << endl;
        cout << "合并链表1和链表2:";
        Show(head2);
        List* temphead = Reverse(head2);
        cout << "合并链表1和链表2并将其逆序:";
        Show(temphead);
    }   
    else if (Lflag == 0)
        cout << "链表为空";
    cout << endl;
    
    return 0;
}

测试结果
《合并两个递增有序单链表为递减有序单链表》

    原文作者:姚同学阿
    原文地址: https://blog.csdn.net/Kother/article/details/121980714
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞