回忆出2016一道考试题:
有两个单链表,已经按非减排序,要求完成两个链表的合并,也要非递减排序,并且不能使用除当前2个链表以外的存储空间。
其中,允许有重复元素存在。
例如:ha-> (1) -> (3) -> (8);hb->(1) -> (7) -> (9) 。
合并后应该得到:ha ->(1)-> (1) -> (3) -> (7) -> (8) -> (9)。
由于题目要求不允许使用额外的存储空间,因此,想直接把两个链表的元素依次写入到第三个链表的偷懒办法行不通了。
解决思路:依次把第2个链表的元素判断,是否插入到第1个链表的当前位置。s1,s2分别指向第一个链表,t1,t2分别指向第二个链表。
当t1的值大于s2的值,s1和s2依次后移,循环后再判断。
如果t1的值小于s2,说明t1要插入到s1和s2之间;t1变成t2,t2编程t1的后续。
循环的终止条件是:s2或t2任意一个变成NULL,就说明其中一条链表到了结尾。
代码如下,测试通过了:
typedef struct header
{
int V;
struct header * pnext;
} Node;
Node * link_merg(Node * p1, Node *p2)
{
Node *s1=p1, *s2, *t1=p2, *t2;
if(s1->V > t1->V)
{
Node * tmp = t1;
t1 = s1;
s1 = tmp;
}
s2 = s1->pnext;
t2 = t1->pnext;
while((s2!=NULL)&&(t2!=NULL))
{
if(s2->V > t1->V)
{
s1->pnext = t1;
t1->pnext = s2; //完成t1插入到第一个链表
s1= t1;
s2 = s1->pnext;
t1 = t2;
t2 = t1->pnext;
}
else
{
s1 = s2;
s2 = s1->pnext;
}
}
if(s2==NULL)
{ s1->pnext = t1;}
else
{s2->pnext = t1;}
return(s1);
}
回来了又在思考这个问题,发现还有一个好办法,直接合并两个链表,然后对整个大链表进行排序,冒泡也好,快速排序也好。
这样也符合题目要求,并没有用到其他额外的存储空间。
汗啊~当时太紧张了,没反应过来。。。