- 1.算法思路
- 2.定义结构体
- 3.定义函数
- 3.1 创建单链表
- 3.2 合并单链表
- 4.测试结果
- 5.完整代码
- 将两单链表合并,常用的方法是归并排序。每次比较两个链表的当前结点值,选择较大的结点值进行插入操作。
- 由于是将递减有序的链表变为递增有序的链表,那么可以考虑使用头插法,每次归并排序比较完成后将更大值的结点插入到已排序链表中,然后移动排序链表的头指针指向该结点。
typedef struct LNode {
int data;
struct LNode *next;
} LNode, *LinkList;
3.定义函数
3.1 创建单链表
编写函数创建单链表。输入参数为:
- LinkList A: 单链表的头结点
- int a[]: 该单链表的元素值
- length: 元素值的长度
当i < length时,循环创建结点,并使用尾插法将结点插入到当前链表的最后面,然后将链表尾指针移动至尾部,即当前结点。
void CreateList(LinkList A, int a[], int length) {
LNode *s = (LNode *)malloc(sizeof(LNode));
LNode *tail = A;
s->next = NULL;
for(int i=0; i < length; i++) {
s = (LNode *)malloc(sizeof(LNode));//创建新结点
s->data = a[i];
s->next = NULL;
tail->next = s;
tail = tail->next;
}
}
3.2 合并单链表
- 首先创建链表头结点C,它将指向已排好序的链表头结点,每次使用头插法插入新结点后都将指向此时的头结点,即新结点。
- 创建工作指针p,q分别指向A和B的首个数据结点。判断p,q是否为空。如果有链表为空,则返回NULL。这里假定两个链表都不为空时才进行排序,否则结束程序。
- 当p,q都不为空时,遍历A,B链表,比较结点值,进行如下判断:
- p->data == q->data: 说明两结点值重复,因此选择删除一个结点,头插另一个结点。这里选择插入p结点而删除q结点。首先使用指针s只想当前结点p,然后将p结点向后移动,之后修改相应指针实现p的头插。然后将s指向q,并让q向后移动,再释放s。
- p->data > q->data: 此时选择更大的结点即p将其插入到排序链表中,然后p后移,比较新的p和q。
- p->data < q->data: 此时选择更大的结点即q将其插入到排序链表中,然后q后移,比较新的p和q。
- 当A或B遍历完成时,上述循环退出。此时判断p,q哪个指针为空。使用头插法将未空指针后面的剩余结点插入到排序链表。
LinkList MergeList(LinkList A, LinkList B) {
//C用于指向以合并链表的头结点
LinkList C = (LinkList)malloc(sizeof(LNode));
C->next = NULL;
//p,q用于遍历两个链表,s用于指向当前结点更大的结点
LNode *p = A->next, *q = B->next, *s = NULL;
if(!p || !q) {
printf("链表为空!n");
return NULL;
}
while(p && q) {//p,q都不为空,开始比较
if(p->data == q->data) {//p,q相等,删除一个结点
//首先将一个结点头插到当前链表中
s = p;
p = p->next;
s->next = C->next;
C->next = s;
//删除另一个结点
s = q;
q = q->next;
free(s);
}
else {
if(p->data > q->data) {//p的结点值更大,将s移到p
s = p;
p = p->next;
} else{//q的结点值更大,将s移到q
s = q;
q = q->next;
}
s->next = C->next;
C->next = s;
}
}
while(p) {//当q为空时,将q剩下的进行头插法
s = p;
p = p->next;
s->next = C->next;
C->next = s;
}
while(q) {//当p为空时,将p剩下的进行头插法
s = q;
q = q->next;
s->next = C->next;
C->next = s;
}
return C->next;
}
4.测试结果
给出两组测试结果:
LinkList A = (LinkList)malloc(sizeof(LNode));
LinkList B = (LinkList)malloc(sizeof(LNode));
int a[] = {7,6,5,4,3,2,1};
int b[] = {9,5,3,1};
CreateList(A, a, sizeof(a) / sizeof(a[0]));
CreateList(B, b, sizeof(b) / sizeof(b[0]));
LinkList A = (LinkList)malloc(sizeof(LNode));
LinkList B = (LinkList)malloc(sizeof(LNode));
int a[] = {7,5,3,1};
int b[] = {7,5,3,1};
CreateList(A, a, sizeof(a) / sizeof(a[0]));
CreateList(B, b, sizeof(b) / sizeof(b[0]));
5.完整代码
#includeusing namespace std; //定义结构体 typedef struct LNode { int data; struct LNode *next; } LNode, *LinkList; //合并两个递减链表并实现递增有序 LinkList MergeList(LinkList A, LinkList B) { //C用于指向以合并链表的头结点 LinkList C = (LinkList)malloc(sizeof(LNode)); C->next = NULL; //p,q用于遍历两个链表,s用于指向当前结点更大的结点 LNode *p = A->next, *q = B->next, *s = NULL; if(!p || !q) { printf("链表为空!n"); return NULL; } while(p && q) {//p,q都不为空,开始比较 if(p->data == q->data) {//p,q相等,删除一个结点 //首先将一个结点头插到当前链表中 s = p; p = p->next; s->next = C->next; C->next = s; //删除另一个结点 s = q; q = q->next; free(s); } else { if(p->data > q->data) {//p的结点值更大,将s移到p s = p; p = p->next; } else{//q的结点值更大,将s移到q s = q; q = q->next; } s->next = C->next; C->next = s; } } while(p) {//当q为空时,将q剩下的进行头插法 s = p; p = p->next; s->next = C->next; C->next = s; } while(q) {//当p为空时,将p剩下的进行头插法 s = q; q = q->next; s->next = C->next; C->next = s; } return C->next; } //创建单链表 void CreateList(LinkList A, int a[], int length) { LNode *s = (LNode *)malloc(sizeof(LNode)); LNode *tail = A; s->next = NULL; for(int i=0; i < length; i++) { s = (LNode *)malloc(sizeof(LNode));//创建新结点 s->data = a[i]; s->next = NULL; tail->next = s; tail = tail->next; } } int main() { //创建单链表 LinkList A = (LinkList)malloc(sizeof(LNode)); LinkList B = (LinkList)malloc(sizeof(LNode)); int a[] = {7,6,5,4,3,2,1}; int b[] = {9,5,3,1}; CreateList(A, a, sizeof(a) / sizeof(a[0])); CreateList(B, b, sizeof(b) / sizeof(b[0])); LinkList p = A->next; //打印查看原始数据 printf("A链表的数据为:n"); while(p) { printf("%dt", p->data); p = p->next; } printf("n"); p = B->next; printf("B链表的数据为:n"); while(p) { printf("%dt", p->data); p = p->next; } printf("n"); //获取合并后的链表 LinkList q = MergeList(A, B); //打印输出 printf("修改后链表的数据为:n"); while(q) { printf("%dt", q->data); q = q->next; } return 0; }



