解题时,主要解决以下几个问题。
①对两个有序链表里的数字进行综合排序,合二为一。
先分别遍历两表,求知长度:
PNode p=l1; int len1=0;
PNode q=l2; int len2=0;
while (p!=NULL) //分别求两个链表的长度
{
len1++;
p=p->next;
}
p=l1;
while (q!=NULL)
{
len2++;
q=q->next;
}
q=l2;
创建一个judge数组,存放排序的所有数字。
int sum=len1+len2;
int judge[sum];
然后就进行整合排序。
当前遍历的结点val值,哪张表的大,就存入哪个值;如果相等,就都存入。
注意临界情况:有一张表遍历到了尾部,就不需要在比较大小了,另一张表直接全部录入就可以了。
int i=0;
while(p!=NULL && q!=NULL)
{
if(p->val==q->val)
{
judge[i++]=p->val;
judge[i++]=q->val;
p=p->next;
q=q->next;
}
else if(p->val < q->val)
{
judge[i++]=p->val;
p=p->next;
}
else if(p->val > q->val)
{
judge[i++]=q->val;
q=q->next;
}
if (p==NULL && q!=NULL)
{
while(q!=NULL)
{
judge[i++]=q->val;
q=q->next;
}
}
else if (q==NULL && p!=NULL)
{
while(p!=NULL)
{
judge[i++]=p->val;
p=p->next;
}
}
else continue;
}
可以看到,这个过程是部分嵌套了双重循环的,但是不用担心,大多数时候内循环是不会执行的。内循环是处理最后的事情,内循环执行完毕后,外循环也就退出了。(p,q都指向NULL了)
②把排序好的数字置入链表中return。
一开始,我想要用malloc另外开辟一串链表,然后将这些数字一个一个存入,然后return。
但是,其实没有必要再申请空间了,现成的l1和l2不就是吗?我只要将l1和l2连起来,不就有一个长串了吗。
p=l1;
while(p->next!=NULL)
{
p=p->next;
}
p->next=l2;
接下来就是赋值了,很简单。
p=l1;
i=0;
while(p!=NULL)
{
p->val=judge[i++];
p=p->next;
}
③特殊情况的讨论。
如果止步于上述程序,是会出现错误的。因为有一些特殊情况并没有考虑完整。问题出在这里:
int sum=len1+len2;
int judge[sum];
如果sum==0,judge数组的创建就是错误的,也就是说,两表皆为空时,直接返回NULL就可以了。
同样的,如果其中一表为空,那么直接返回另一表就可以了。
if (len1==0 && len2==0) return NULL;
else if (len1==0 && len2!=0) return l2;
else if (len1!=0 && len2==0) return l1;
else ;
将这段代码添加在创建judge数组之前,程序就完整无误了。
④完整代码和延伸
完整代码:
typedef struct ListNode* PNode;
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
PNode p=l1; int len1=0;
PNode q=l2; int len2=0;
while (p!=NULL) //分别求两个链表的长度
{
len1++;
p=p->next;
}
p=l1;
while (q!=NULL)
{
len2++;
q=q->next;
}
q=l2;
if (len1==0 && len2==0) return NULL;
else if (len1==0 && len2!=0) return l2;
else if (len1!=0 && len2==0) return l1;
else ;
int sum=len1+len2;
int judge[sum];
int i=0;
while(p!=NULL && q!=NULL)
{
if(p->val==q->val)
{
judge[i++]=p->val;
judge[i++]=q->val;
p=p->next;
q=q->next;
}
else if(p->val < q->val)
{
judge[i++]=p->val;
p=p->next;
}
else if(p->val > q->val)
{
judge[i++]=q->val;
q=q->next;
}
if (p==NULL && q!=NULL)
{
while(q!=NULL)
{
judge[i++]=q->val;
q=q->next;
}
}
else if (q==NULL && p!=NULL)
{
while(p!=NULL)
{
judge[i++]=p->val;
p=p->next;
}
}
else continue;
}
/*
for (i=0; i<=sum-1; i++)
{
printf("%d ",judge[i]);
}
*/
/*把两个链表连接,再重新复制一遍,就不用再额外申请空间了*/
p=l1;
while(p->next!=NULL)
{
p=p->next;
}
p->next=l2;
p=l1;
i=0;
while(p!=NULL)
{
p->val=judge[i++];
p=p->next;
}
return l1;
}
随便再讨论一下:
如果给定的这两个表是乱序的,也要完成上述的任务,其实也好办。我们录入judge数组的时候,先全部录入,不排序。录入完毕后,在进行排序工作即可,后续同上。难度上并没有增加。