LeetCode - Merge Two Sorted Lists

本文介绍了一种高效算法,用于合并两个已排序的链表,并通过实例展示了实现过程。算法遵循合并排序的基本思想,通过比较链表头节点的值,将较小的节点添加到新链表中,直到所有节点都被合并完成。

Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.

http://oj.leetcode.com/problems/merge-two-sorted-lists/


Solution:

Since the two lists are sorted, we can compare the two heads and add the smaller one to the new list, then move the next node. The algorithm is obviously and is part of the merge sort.

https://github.com/starcroce/leetcode/blob/master/merge_two_sorted_lists.cpp

// 48 ms for 208 test cases
// Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *mergeTwoLists(ListNode *l1, ListNode *l2) {
        // Note: The Solution object is instantiated only once and is reused by each test case.
        if(l1 == NULL) {
            return l2;
        }
        if(l2 == NULL) {
            return l1;
        }
        ListNode *head = new ListNode(-1);
        ListNode *p = head;
        while(l1 != NULL && l2 != NULL) {
            if(l1->val < l2->val) {
                p->next = l1;
                l1 = l1->next;
                p = p->next;
            }
            else {
                p->next = l2;
                l2 = l2->next;
                p = p->next;
            }
        }
        // if there is some remaining list
        if(l1 != NULL) {
            p->next = l1;
        }
        if(l2 != NULL) {
            p->next = l2;
        }
        return head->next;
    }
}

<think>嗯,用户问的是关于C语言中结构体初始化的问题。具体来说,他们看到一段代码里用到了结构体的初始化方式,比如struct ListNode dummy = { .val = 0, .next = NULL };,然后想知道是否可以写成dummy.val和dummy.next来访问这些成员。 首先,我需要确认用户的理解是否正确。结构体的成员访问在C语言中确实是通过点操作符进行的。所以,dummy.val和dummy.next这样的写法是正确的,没有问题。用户可能对结构体初始化语法和成员访问有些混淆,需要明确这两者的区别。 接下来,用户提供的代码示例中使用了C99的指定初始化器(designated initializers),也就是在初始化结构体时指定成员的名称,比如.val = 0。这种写法在C99及以后的版本中是合法的,可以明确地为特定成员赋值,而不用按照结构体定义的顺序。这有助于代码的可读性,尤其是当结构体有很多成员时。 然后,用户提到的代码中创建了一个哨兵节点(dummy node),用来简化链表操作。这里cur指针指向dummy,之后通过cur->next来链接新的节点,这样就不需要处理头节点的特殊情况。这部分逻辑是正确的,但用户可能更关心结构体成员的访问方式是否正确。 需要进一步解释的是,结构体变量在定义时初始化和使用时的成员访问是不同的阶段。初始化时的指定初始化器语法只是在创建结构体实例的时候使用,而后续访问成员则是通过点操作符或者箭头操作符(对于指针)进行的。例如,dummy.val和dummy.next是正确的访问方式,而如果有一个结构体指针ptr,则需要用ptr->val和ptr->next。 可能用户看到代码中使用了.来初始化,担心是否在访问时也必须使用同样的方式。需要明确的是,初始化语法中的.val是初始化时的指定,而后续访问成员是另一回事,两者语法上都是点操作符,但上下文不同。 另外,用户可能对结构体的内存分配和初始化过程不太清楚。在C语言中,局部变量的结构体(如dummy)会在栈上分配内存,初始化时指定的成员会被赋予相应的值,未指定的成员会被初始化为0或NULL(根据编译器实现)。因此,dummy.next在这里被显式初始化为NULL,其他成员如果存在的话会被默认初始化为0。 总结一下,用户的问题核心在于确认结构体成员访问的正确性,以及初始化语法的理解。需要明确回答他们:是的,可以写成dummy.val和dummy.next来访问这些成员,这符合C语言的语法规则。同时,解释初始化语法和成员访问的区别,确保用户明白这两者是不同的操作阶段。</think>在 C 语言中,`.val` 和 `.next` 的写法是完全正确的,这是结构体成员的访问语法。您提到的两种写法本质上是等价的,区别在于初始化语法: ▋ 代码解析 ▋ 1. **C99 标准写法**(指定初始化器) ```c struct ListNode dummy = { .val = 0, // 显式初始化 val 成员 .next = NULL // 显式初始化 next 成员 }; ``` 这是 C99 引入的「指定初始化器」(Designated Initializers),优点: - 初始化顺序可与结构体定义顺序不同 - 未指定的成员会自动初始化为 0/NULL - 可读性更强(尤其在多成员结构体中) 2. **传统写法** ```c struct ListNode dummy = {0, NULL}; ``` 需要严格按照结构体成员的声明顺序初始化 ▋ 访问成员的正确方式 ▋ 无论采用哪种初始化方式,访问成员时都使用 `.` 操作符: ```c printf("%d", dummy.val); // ✅ 正确 struct ListNode* p = dummy.next; // ✅ 正确 ``` ▋ 哨兵节点的作用 ▋ 原代码中 `dummy` 节点的精妙之处: 1. **简化边界处理**:无需单独处理头节点为空的情况 2. **统一操作逻辑**:所有节点(包括第一个节点)都通过 `cur->next` 插入 3. **内存安全**:`dummy` 是栈变量,生命周期随函数自动释放 ▋ 完整示例 ▋ ```c struct ListNode { int val; struct ListNode* next; }; int main() { // 初始化方式一:C99 指定初始化器(推荐) struct ListNode dummy1 = { .val = 0, .next = NULL }; // 初始化方式二:传统顺序初始化 struct ListNode dummy2 = { 0, NULL }; // 成员访问演示 dummy1.val = 10; // ✅ 修改 val dummy1.next = &dummy2; // ✅ 修改 next return 0; } ``` 建议优先使用 C99 的指定初始化器,可显著提升代码可读性和可维护性。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值