//多种情况的时候,把每一种情况处理好了,再把它们合并起来。
#include <stdio.h>
#include <stdlib.h>
typedef struct _node {
int key;
struct _node * next;
}node;
node * build_linked_list(void);
void print(node * );
node * merge(node *,node * );
int main(void)
{
//建立链表,并返回头指针
node * head_of_linked_list1=build_linked_list();
//打印链表
print(head_of_linked_list1);
node * head_of_linked_list2=build_linked_list();
print(head_of_linked_list2);
//合并两个已经排列好顺序的链表,并返回这个新链表的头指针
node * new_head= merge(head_of_linked_list1,head_of_linked_list2);
print(new_head);
}
//建立链表
/*建立链表的时候要维护两个节点
1. 当前节点和
2.当前节点的前一个节点
*/
node * build_linked_list(void)
{ puts("Enter the key in ascending order (q to quit) ");
node * head=NULL;
node * prev;
node * current;
int key;
char ch;
while(scanf("%d",&key)==1)
{ current=(node * )malloc(sizeof(node));
current->next=NULL;
current->key=key;
if (head==NULL)
head=current;
else
prev->next=current;
prev=current;
}
//读取缓存里面的字符,并抛掉
while(getchar()!='\n')
continue;
return head;
}
void print(node * head)
{ puts("The linked list:\n");
while (head!=NULL)
{ printf("%d ",head->key);
head=head->next;
}
puts("\n");
}
/* 合并两个已经排好序(由大到小)的链表
#####################算法思想####################
表一、表二的头指针分别问head1、和head2,如下所示
head1->n1->n2->n3
head2->N1->N2->n3
1.假设把表2插入表1。循环表2,依次把表2的节点插入
到表1的合适位置上。
2. 在进行插入操作的时候有如下几种情况需要考虑:
为了方便书写,只写出节点的key值。
1. 表一:1 3 5 8
表二 : 2 4 6
Max(表1)>Max(表2) 并且 Min(表1)<Min(表2)
这种情况表1的头指针不会该边表
2. 表1: 1 3 5 8
表2: 0 2 4
Max(表1)>Max(表2) 并且 Min(表1)>Min(表2)
这种情况头指针需要改标
3. 表1: 1 3 5 8
表2: 2 9 10 11
Max(表1)<Max(表2) 并且 Min(表1)>Min(表2) \
直接把key值为9(包括该节点)之后的所有节点都插入到表1的结尾
#######################代码实现################
函数的输入值是两个待合并链表的头指针
输出值是合并后的链表的头指针
head--随时保持指向合并链表的头
prev、head1-指向被插入链表的相邻两个节点
head1指向正好大于待插入节点的被插入链表中的节点
prev指向正好小于待插入节点的被插入链表中的节点
temp-用来临时存储插入链表的头位置
*/
node * merge(node * head1,node * head2)//把head2所指向的表插入到head1所指向的表里面
{ // puts("There");
node * head=head1;//保存head1原始所指向的位置
node * prev=head1;
node * temp;
//循环链表2的节点
while(head2!=NULL)
{ while(head1!=NULL && head1->key<head2->key)//如果head1所指向的位置不为空并且执行的元素小于待插入
{ prev=head1; // 保存下来此时head1的位置
head1=head1->next;//head1指向链表的下一个节点
}
//这段代码专门用来处理情况二,相当于重新生产了两个新的链表,然后,再跳出循环,情况二现在转换成了情况1或者情况3。
temp=head2->next; //首先保存下head2所指向链表的下一个元素的位置
// 处理情况3并返回
if (head1==NULL)
{ prev->next=head2;
return head;
}
if(head1==head)//如果出现情况2
{
head2->next=head1;//head2的第一个节点的next链表1的头
head1=head2;//把header1指向增加了一个节点的❤新链表
head=head2;//修改head指针的值
head2=temp;//head2指向下一个节点
continue;//继续下次循环
}
//prev的next指向这个节点
// 并修改prev的值
else
{ prev->next=head2;
prev=head2;
}
// 修改这个header指针,指向head1
head2->next=head1;
//head2指向链表2的下一个元素
head2=temp;
}
//正常返回。
return head;
}
##############################################测试####################################################
$ ./a.out
Enter the key in ascending order (q to quit)
1 3 5 8 q
The linked list:
1 3 5 8
表1
Enter the key in ascending order (q to quit)
-1 0 4 6 7 10 11 q
The linked list:
表2
-1 0 4 6 7 10 11
表1、表2合并后的结果
The linked list:
-1 0 1 3 4 5 6 7 8 10 11