C语言-单向不循环链表的常见考点

C语言-单向不循环链表的五大常见考点

一、前言

上一篇中我们着重介绍了单向不循环链表的基本操作。本篇将详细介绍单向不循环链表的常见五个考点

  • 链表反转-使用三指针迭代法
  • 合并两个已升序链表
  • 找中间节点-使用快慢指针法
  • 删除倒数第k个节点
  • 检测链表是否有环-使用快慢指针法

二、详细代码

链表反转-使用三指针迭代法

Node* reverse_list(Node* head)
{
    Node* prev = NULL;
    Node* cur = head;
    while (cur)
    {
        Node* next = cur->next;
        cur->next = prev;
        prev = cur;
        cur = next;
    }
    return prev;
}

原理解释:
创建两个指针,分别为prev(新头),cur(当前要拆的节点)
进入循环,使用next存放后继,防止找不到节点
将当前节点的next指向prev,完成反转
将prev和cur继续后推进,继续处理下一个节点

合并两个已升序链表

Node* merge_two_lists(Node* l1, Node* l2)
{
    Node dummy, * tail = &dummy;
    dummy.next = NULL;

    while (l1 && l2)
    {
        if (l1->data <= l2->data)
        {
            tail->next = l1;
            l1 = l1->next;
        }
        else
        {
            tail->next = l2;
            l2 = l2->next;
        }
        tail = tail->next;
    }
    tail->next = l1 ? l1 : l2;
    return dummy.next;
}

原理解释:
创建两个指针dummy和tail,dummy作为新链表的虚拟头节点,tail用于跟踪新链表的尾部
遍历两个链表,比较当前节点的值,将较小的节点连接到tail后面,并移动相应的指针
当其中一个链表遍历完后,将另一个链表的剩余部分连接到tail后面
返回dummy的下一个节点作为新链表的头指针

找中间节点-使用快慢指针法,若节点为偶数,返回中间偏右的节点

Node* find_middle_node(Node* head)
{
    Node* slow = head, *fast = head;
    while (fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
    }
    return slow;
}

原理解释:
创建两个指针slow和fast,初始都指向链表头节点
进入循环,slow每次移动一步,fast每次移动两步
当fast到达链表末尾时,slow正好位于链表的中间位置

删除倒数第k个节点

int delete_kth_from_end(Node** head, int k)
{
    if (*head == NULL || k <= 0) return -1;
    Node* dummy = create_node(0);
    dummy->next = *head;
    Node* first = dummy;
    Node* second = dummy;
    for (int i = 0; i < k + 1; i++)
    {
        if (first == NULL)
        {
            free(dummy);
            return -1; // k大于链表长度
        }
        first = first->next;
    }
    while (first)
    {
        first = first->next;
        second = second->next;
    }
    Node* temp = second->next;
    second->next = second->next->next;
    free(temp);
    *head = dummy->next;
    free(dummy);
    return 0;
}

原理解释:
创建一个哨兵节点dummy,指向链表头
使用两个指针first和second,初始都指向dummy
先让first指针移动k+1步,这样first和second之间就有k个节点的距离
然后同时移动first和second指针,直到first到达链表末尾
此时,second指针正好指向倒数第k个节点的前一个节点
调整second的next指针,跳过倒数第k个节点,从而将其删除

检测链表是否有环-使用快慢指针法

int has_cycle(Node* head)
{
    Node* slow = head;
    Node* fast = head;
    while (fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        if (slow == fast)
            return 1; // 有环
    }
    return 0; // 无环
}

原理解释:
创建两个指针slow和fast,初始都指向链表头节点
进入循环,slow每次移动一步,fast每次移动两步
如果链表中存在环,slow和fast最终会在环内相遇

三、额外补充

上一篇单向不循环链表的基本操作链接为:https://www.cnblogs.com/hex0110/p/19455430

posted @ 2026-01-21 09:46  tanyee  阅读(2)  评论(0)    收藏  举报