C语言|用指针将两个有序单链表拼接成一个新的有序单链表详解

算法描述

略去部分诸如链表为空的细节。带数字的图示容易理解,一般情况的抽象图示就偷懒没画了。(画这个还挺累的,为了表达清楚,尝试了好几种不同的图示方案,希望下面的能容易理解。)

  1. 不改变各个节点的数据域,只通过改变两个链表的指针域,来拼接成新的链表。所以新链表的头指针指向的是两个链表中头节点数据较小的一个。因而,第一步,应先将头指针确定。

  2. 引入两个指针:pnew=指向已成型的新链表的尾部;px指向另一个链表的头部。比如,如图,初始的pnew应当指向数据域为1的结点,而px指向另一个链表的头节点。因为,px节点的后继节点的值必定大于px节点的值。(单个链表本身是升序的)
    在这里插入图片描述

  3. 如果pnew->next节点值小于或等于px,则pnew=pnew->next,直到后继节点值大于px :
    在这里插入图片描述

  4. 将pnew的后继指针指向px,即将px插在新链表的尾部,该节点就变成新链表的尾部了,pnew指向该节点,而原来的pnew的后继节点,因为与前部分链表断开,成为头部,px指向该节点。
    在这里插入图片描述

  5. 如此交替插在新链表的尾部,直到pnew指针遍历完某个链表,就可以将pnew后继指针指向px节点,然后返回头指针了。(px是不会动的,判断pnew指针所指的链表是否遍历完即可)
    在这里插入图片描述

示例代码

struct ListNode *mergelists(struct ListNode *list1, struct ListNode *list2){
    struct ListNode *head,*pnew,*px,*temp;
    if(list1==NULL)return list2;	//---------
    if(list2==NULL)return list1;	//检查链表是否为空
    if(list1->data>=list2->data){	//初始化操作:确定头节点与两个指针的位置
        head=list2;
        pnew=list2;
        px=list1;
    }							
    else{
        head=list1;
        pnew=list1;
        px=list2;
    }							
    while(1){		//交替拼接
        while(pnew->next!=NULL && pnew->next->data <= px->data){	//确定px与pnew的交接位置
                pnew=pnew->next;
        }
        if(pnew->next==NULL){//判断pnew是否遍历完所在链表,如是便可返回头节点,否则交换指针
            pnew->next=px;
            return head;
        }
        else{		//交换指针
            temp=pnew->next;
            pnew->next=px;
            pnew=px;
            px=temp;
        }
    }
}

有常规算法,各方面更方便一些。当时把问题复杂化了。
三个指针:两个分别用来遍历两个链表(p1p2),另一个操作生成新链表(pnew);
每次循环用对比p1p2所指结点,取两者中符合顺序的一个,接在新链表上,被取值的指针向前移,直到有链表遍历完成,接上剩余的另一个链表即可。20.3.27注

发布了188 篇原创文章 · 获赞 31 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44421292/article/details/104851130