合并链表 C语言实现(非伪代码)

自我感觉不常见,了解即可

刚刚开始提到这个功能的时候,感觉有很多实现形式,也可以使用多种的返回值类型。

最后思来想去还是想着用结点直接作为返回值类型,但这样也会使得合成出来的链表没有len,也就是没有长度的变量,变成了一次性的链表,也不能对他做一些增删查改的操作,但是确实是最简单的一种实现方式

1.核心代码模块

// 合并两个有序链表
ListNode* Compose_List1_List2(ListNode* l1, ListNode* l2) 
{
    //创建合并链表list3
    ListNode head; // 创建虚拟头结点
    ListNode* tail = &head; // 尾指针初始化
    head.next = NULL; // 初始化虚拟头结点的 next 指针


    while (l1 != NULL && l2 != NULL) // 当两个链表都有结点时
    { 
        if (l1->data < l2->data) //表明此时需要把list1->data插入到list3中
        {
            tail->next = l1; // 连接 l1 的结点
            l1 = l1->next; // 移动 l1 指针
        }
        else 
        {
            tail->next = l2; // 连接 l2 的结点
            l2 = l2->next; // 移动 l2 指针
        }
        tail = tail->next; // 移动尾指针
    }

    //此时,表明一个结点已经为空直接 将剩余的结点连接到合并后的链表  

    if (l1 != NULL) //将 tail 指向的节点的 next 指向 l1 的第一个节点,表示把 l1 的剩余部分加到合并链表的末尾。
    {
        tail->next = l1;
    }
    else 
    {
        tail->next = l2;
    }

    return head.next; // 返回合并后的链表
    //由于head 是一个虚拟头节点,因此 head.next 是合并链表的实际头节点。
}

1.1:图解:

2、完整代码:

#include <stdio.h>
#include <stdlib.h>

typedef struct ListNode { // 创建链表单独结点
    int data; // 数值域
    struct ListNode* next; // 下一个结点的指针域
} ListNode;

typedef struct LinkedList { // 链表结构体
    ListNode* head; // 头结点
    int len; // 长度
} LinkedList;

// 创建和初始化链表
void Create_LinkedList(LinkedList* list) 
{
    list->head = NULL; // 将头节点置空
    list->len = 0; // 长度置为0
}

void Destroy_LinkList(LinkedList* list) // 销毁一个链表
{
    while (list->head) // 当头节点不为空时
    {
        ListNode* temp = list->head; // 用一个临时的结点指向此时的头节点
        list->head = list->head->next; // 将指针指向头指针的下一个结点
        free(temp); // 释放临时变量
    }
    list->len = 0; // 链表长度归0
    list->head = NULL; // 将头节点设置为NULL
}


// 合并两个有序链表
ListNode* Compose_List1_List2(ListNode* l1, ListNode* l2) 
{
    //创建合并链表list3
    ListNode head; // 创建虚拟头结点
    ListNode* tail = &head; // 尾指针初始化
    head.next = NULL; // 初始化虚拟头结点的 next 指针


    while (l1 != NULL && l2 != NULL) // 当两个链表都有结点时
    { 
        if (l1->data < l2->data) //表明此时需要把list1->data插入到list3中
        {
            tail->next = l1; // 连接 l1 的结点
            l1 = l1->next; // 移动 l1 指针
        }
        else 
        {
            tail->next = l2; // 连接 l2 的结点
            l2 = l2->next; // 移动 l2 指针
        }
        tail = tail->next; // 移动尾指针
    }

    //此时,表明一个结点已经为空直接 将剩余的结点连接到合并后的链表  

    if (l1 != NULL) //将 tail 指向的节点的 next 指向 l1 的第一个节点,表示把 l1 的剩余部分加到合并链表的末尾。
    {
        tail->next = l1;
    }
    else 
    {
        tail->next = l2;
    }

    return head.next; // 返回合并后的链表
    //由于head 是一个虚拟头节点,因此 head.next 是合并链表的实际头节点。
}

// 打印链表
void Print_Linked(ListNode* head) 
{
    ListNode* current = head; // 迭代器

    while (current) 
    {
        printf("%d -> ", current->data);
        current = current->next; // 往下走
    }

    printf("NULL\n");
}

// 示例代码
int main() {
    LinkedList list1, list2; // 定义两个链表
    Create_LinkedList(&list1); // 初始化链表1
    Create_LinkedList(&list2); // 初始化链表2

    // 手动创建有序链表 l1: 1 -> 3 -> 5
    list1.head = (ListNode*)malloc(sizeof(ListNode));
    list1.head->data = 1;
    list1.head->next = (ListNode*)malloc(sizeof(ListNode));
    list1.head->next->data = 3;
    list1.head->next->next = (ListNode*)malloc(sizeof(ListNode));
    list1.head->next->next->data = 5;
    list1.head->next->next->next = NULL;
    list1.len = 3; // 更新长度

    // 手动创建有序链表 l2: 2 -> 4 -> 6
    list2.head = (ListNode*)malloc(sizeof(ListNode));
    list2.head->data = 2;
    list2.head->next = (ListNode*)malloc(sizeof(ListNode));
    list2.head->next->data = 4;
    list2.head->next->next = (ListNode*)malloc(sizeof(ListNode));
    list2.head->next->next->data = 6;
    list2.head->next->next->next = NULL;
    list2.len = 3; // 更新长度

    // 合并两个链表
    ListNode* Compose_List = Compose_List1_List2(list1.head, list2.head);
    printf("Compose_List: ");
    Print_Linked(Compose_List);


    system("pause");
    
    return 0;
}

 如果后续遇到了需要对合并链表做操作的再补一份代码上来嘿嘿嘿嘿

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值