数据结构的链表章节后有一道实现两个有序递增链表的合并操作,对于这题,要进行节点之间的比较和插入顺序,我就来解释一下这个题的解法。
(1)合并链表
首先我们知道要将两个链表的节点按照顺序插入新建链表就必须要先对两个节点进行比较再进行插入,这样我们可以知道要先对两个节点进行比较后对较小的节点进行插入操作,然后将新链表的节点后移,来接纳后面要插入的节点。所以我们解这道题的关键就是比较节点大小和插入元素。
void mergeLnode(Lnodelink* a,Lnodelink* b,Lnodelink* c)
{
c->head = NULL;
c->size = 0;//新建链表要对新链表进行初始化
Lnode** pc = &(c->head);//用指向节点的指针来作为c的头结点
Lnode* pa=a->head;//将pa指向a的头结点
Lnode* pb=b->head;//将pb指向b的头结点
while (pa && pb)
{
if (pa->data <= pb->data)//比较节点大小
{
*pc = pa;
pa = pa->next;//插入节点(下同)
}
else
{
*pc = pb;
pb = pb->next;
}
pc = &((*pc)->next);//将节点后移
}
*pc = (pa ? pa : pb);//判断哪个节点是非空就直接接到pc上
c->size = a->size + b->size;//将新链表的size值重新赋值
}
一开始我是直接用Lnode* pc = c->head来想初始化将pc定义为c(新建链表)链表的头结点 ,没有任何意外啊,直接错了。初始设置时c->head=NULL,这时就是单纯地将pc节点置为空值,并没有接到c的头结点上面,所以我们要用指向型指针的地址调用就是将Lnode* pc取值地址为(c->head),这样才能正确的将pc接到c的头结点上。
后面的操作就十分简单了就利用循环将pa或pb的节点接到pc上在将接上节点的链表头结点向后移动一位和将pc取地址为原来pc节点地址的下一位即可,如果两个节点pa和pb还存在再进行下一次比较来进行遍历。最后还要考虑哪个链表还有剩余的节点就直接将节点接到pc上就可以了。也就是三元比较式*pc=(pa?pa:pb)含义是如果pa节点不为空就将pa接到pc上,如果不存在就将pb接到pc上。
(2)实现代码
1.声明函数
Lnodecreat(Lnodelink* L);//初始化
Lnodedistory(Lnodelink* L);//销毁
Lnodeinsert(Lnodelink* L, int index, int data);//插入元素
printLnode(Lnodelink* L);//显示链表
mergeLnode(Lnodelink* a,Lnodelink* b,Lnodelink* c);//合并链表
2. 实现主函数
链表构建部分就不再赘述,详情可以看【C语言】单链表的实现
int main()
{
Lnodelink L,X,C;
Lnodecreat(&L);
Lnodecreat(&X);
Lnodecreat(&C);
for (int i = 0; i < 10; ++i)
{
Lnodeinsert(&L, i, i * 10);
}
for (int i = 0; i < 10; ++i)
{
Lnodeinsert(&X, i, i * 9);
}
printf("L链表:");
printLnode(&L);
printf("X链表: ");
printLnode(&X);
mergeLnode(&L,&X,&C);
printf("合并后的链表C:");
printLnode(&C);
Lnodedistory(&C);
return 0;
}
还要注意一点,到最后我只销毁了C表而没有销毁前两个表,是因为合并过程中前两个表包括结构已经到了表C上了,实际上表C用的结构都是原来的表的结构,所以我们只需要删除合并后的新表而不需要将前两个表也删除,这样会重复删除结构,导致运行结果最后产生错误,没有办法通过,特别是在链表显示部分会一直报错(好像是调用的data一直产生错误,VS2022上的,不过我忘了截图下来了)。
3.实现效果
最后实现了两个有序递增链表的合并,如果觉得有帮助的记得给个免费的点赞哦(^_−)☆