7-51 两个有序链表序列的合并

7-51 两个有序链表序列的合并

题目

已知两个非降序链表序列S1与S2,设计函数构造出S1与S2合并后的新的非降序链表S3。
输入格式:
输入分两行,分别在每行给出由若干个正整数构成的非降序序列,用−1表示序列的结尾(−1不属于这个序列)。数字用空格间隔。
输出格式:
在一行中输出合并后新的非降序链表,数字间用空格分开,结尾不能有多余空格;若新链表为空,输出NULL。
输入样例:

1 3 5 -1 2 4 6 8 10 -1
结尾无空行

输出样例:

1 2 3 4 5 6 8 10
结尾无空行

查了很多资料,一些地方参考了博主们的思路。

具体思路

1.建立两个链表L1,L2,里面放着值,到-1停止。
2.初始化第三个链表L3,顺次比较L1,L2里面的值,使用L1,L2里面的结点构造出第三个链表。(因为没有说新建立一个链表把比较大小之后的值放进去,这样比较好)
3.打印L3。

代码实现

#include
#include //这个不能丢
using namespace std;

typedef struct LNode {
    int data;
    struct LNode* next;
}LNode, *LinkList;

//创建多个链表的方法
LinkList CreateList()    //初始化和创建合在一起!
{
   LinkList L = (LNode*)malloc(sizeof(LNode));  //给第一个链表创建头结点
   L->next = NULL;                             //初始为空
    LinkList p;
    p = L;
    int e;
    while (cin >> e)
    {
        if (e == -1)
            break;           *//这里不能写成return 用return必须得返回相应值 
            				 //采用break*跳出当前循环!
         //尾接法
        LinkList temp = (LNode*)malloc(sizeof(LNode));
        temp->data = e;
        temp->next = p->next;
        p->next = temp;  
        p = p->next;
    }
    return L;                    //循环结束再return true 不然会跳出循环 也不要忘记加
}

//合并函数
LinkList Merge(LinkList L1, LinkList L2)          //整个传入
{
	 //初始化p3
     LinkList p3;
     LinkList L;
     L = (LNode*)malloc(sizeof(LNode));
     p3 = L;
     p3->next = NULL;
     
    LNode* p1 = L1->next; //设立指针来遍历L1,L2
    LNode* p2 = L2->next;
    while (p1 && p2)
    {
        //LinkList temp = (LNode*)malloc(sizeof(LNode)); 
        //不太对,要求是合并,没有要求创建新的链表。
        
        if (p1->data >= p2->data)       //等于的也放进来就行!
        {
            p3->next = p2;            //降序排列 放小的!
            p2 = p2->next;            //类比冒泡排序!!!
        }
        else {
            p3->next = p1;
                p1 = p1->next;
        }
        p3 = p3->next;
    }
	//其中一个遍历完之后把没有遍历完的链表的其他结点连到后面
      p3->next = p1 ? p1 : p2;   //三目运算符很简便,下面那段代码也可以实现,更好理解
      
   //  while (p1)
	//{
	//	p3->next = p1;
	//	p1 = p1->next;
	//	p3 = p3->next;
	//}
	//while (p2)
	//{
	//	p3->next = p2;
	//	p2 = p2->next;
	//	p3 = p3->next;
	//}
	
    L1->next = NULL;   //这一步很重要!让哨头结点指向空,和两个链表断开连接
    L2->next = NULL;
    return L;
}

//打印L3
bool Print(LinkList &L3)
{
    LNode* p = L3;
    p = p->next;
    if(p==NULL)
    {
        cout << "NULL" << endl;
        return true;     //这里写false还是true  无所谓!
       // break;   不行 只能阻断循环!
    }
    while (p != NULL)
    { 
        cout << p->data << " " ;
        p = p->next;
        if(p->next == NULL)         //这里用指针来去掉结尾的多余空格!
        {
            cout << p->data;
            //return true;		   //这个也行!
            break;                 //这里可以用break!!!
        }
     //   cout << endl;
    }
    return true;       //循环结束后再return true!
}

int main()
{
      LinkList L1,L2,L3; //可以三行变一行
	  L1 =  CreateList();
	  L2 =  CreateList();
   /* CreateList(L1);
    CreateList(L2);*/    //这样类似的代码不可以 有歧义!

      L3 = Merge(L1, L2);
      Print(L3);

    return 0;
}

我的一些问题

1.如何创建多个链表

LinkList CreateList(),最后return L;
主函数中 L1 = CreateList(); L2 = CreateList();即可

2.如何顺次输入这些数直到-1停止

while(1) or while(cin >> e) 到-1之后使用break

3.如何比较两个单链表中data域的值并存放在链表L3中?

再设两个可以移动的指针来遍历

4.相等的数据怎么办?

直接放进来就可以!放一个就行!

5.其中一个遍历完了怎么办

p1,p2本身即是降序排列,不用操心,直接把剩下的那个链表剩余的结点连到后面即可

6.怎么连?

用三目运算符!!或者循环

7.总结
(1)break的用法:终止当前循环。
(2)注意题目是否要求创建新的链表。
(3)使用指针p->next = NULL来去掉最后的空格。
(4)结合形成第三个链表之后让前两个链表指向空!
(5)创建一个指向链表的指针的思路很重要,遍历链表,删除结点,寻找某个节点都用得到!

完结撒花~!
2021.10.2
22:25

你可能感兴趣的:(PTA,数据结构与算法题目集,链表,数据结构)