将两个单链表原来的空间交叉合并,比如
单链表LA=(a1, a2,…,am)
单链表LB=(b1, b2, …, bn)
m与n不一定相等
合并后的单链表LC=(a1, b1, a2, b2, …,am, bm, bm+1, bm+2,…,bn) (m
- 首先需要两个指针p,q分别做遍历LA, LB使用
- 然后遍历依次将q结点链接在p结点之后
q->next = p->next; p->next = q;
注意:
如果我们只是做上图这样的链接,那么就会产生一个问题,LB中q结点的后继结点无法再找到,因为q的后继我们已经修改为LA的p结点的后继,所以在操作前我们需要设置一个结点n先取到q的后继节点n = q->next;
- 然后将p和q分别在其所在的原链表中后移,达到遍历目的
p = q->next; q = n;
- 当LA比LB长度更长,由于LB遍历完成之后p结点依然是LA的结点,所以不需要做任何处理。当LA比LB短时,我们需要将LB剩余的结点链接至LA最后。通过分析,如下图:
按照我们之前的逻辑,最后p会指向NULL,显然不能把LB的后继结点链接上,所以我们还需要一个指针f来保留q移动到n前的位置(绿色的q结点),如果出现LB比LA长,只需要让p结点指向这个f结点
f = q;
if(q) // 若LA遍历完后LB还有后继结点,将后继的第一个结点链接在f后,因为此时f保存的就是已经完成合并后的最后一个结点
{
f->next = q;
}
整体实现代码
#include#include // ** 兔子骑士叫旺仔原创 ** // 单链表的结点结构体,并重命名为Node,对应指针命名为LinkList typedef struct Node{ int data; struct Node *next; }Node, *LinkList; // 尾插法建立单链表 LinkList RearInsertCreat() { LinkList L; Node *p, *rear; int x; L = (LinkList)malloc(sizeof(LinkList)); L -> next = NULL; rear = L; scanf("%d", &x); while(x != -1) { p = (Node *)malloc(sizeof(Node)); p->data = x; p->next = rear->next; rear->next = p; //rear指针后移,保证始终指向最后一个结点 rear = p; scanf("%d", &x); } rear->next=NULL; return L; } // 在原空间交叉合并两个单链表 LinkList merge_up(LinkList LA, LinkList LB) { Node *p, *q, *n, *f; // p指针遍历链表LA,q指针遍历链表LB,n指针指向链表LB中q的下一个结点, f指针指向q指针指向的结点 p = LA->next; q = LB->next; n = NULL; f = NULL; while(p && q) //当p和q指针都不为空时 ,将LB中q指针指向的结点连接在LA中p指针指向的结点后,然后将此时的p结点更新至q的后继(LA中p的下一个结点) { //if(p->data <= q->data) //{ n = q->next; q->next = p->next; p->next = q; p = q->next; f = q; q = n; //} } if(q) // 若LA遍历完后LB还有后继结点,将后继的第一个结点链接在f后,因为此时f保存的就是已经完成合并后的最后一个结点 { f->next = q; } return LA; } void ViewList(LinkList L, Node *p) { p = L->next; while(p) { printf("--%d",p->data); p = p->next; } } main() { LinkList LA, LB, LC; Node *p; LA = (LinkList)malloc(sizeof(LinkList)); LB = (LinkList)malloc(sizeof(LinkList)); LA = RearInsertCreat(); LB = RearInsertCreat(); LC = merge_up(LA,LB); p = LC->next; ViewList(LC, p); }
综上,问题解答完毕。
不过我们可以进一步实现有序单链表在原空间合并后仍为有序单链表,大家可以多多交流学习,一起进步。加油!



