首页 > 编程语言 >【程序员面试高频算法】一篇文章搞定链表,附C语言源码,建议收藏!

【程序员面试高频算法】一篇文章搞定链表,附C语言源码,建议收藏!

时间:2024-11-22 22:07:23浏览次数:1  
标签:current head NULL ListNode list next 链表 源码 C语言

一个程序员对计算机底层原理的理解,决定了他职业生涯的上限。
图片

单链表是面试中频繁考察的重点之一。

今天,我们就来深入剖析单链表,涵盖其定义、特点、优缺点、适用场景,以及一系列高频算法题(增删改查、翻转、找倒数第k个节点、判断是否有环等)的解法,并附上C语言源码,让你轻松掌握这一关键知识点。
‌单链表的定义‌

单链表是一种线性数据结构,由一系列节点组成,每个节点包含数据域和指向下一个节点的指针。这种结构通过指针将各个节点连接起来,形成一条链。

‌单链表的特点‌
动态性:链表长度不固定,可随需求增加或减少节点。

节点不连续:链表节点在内存中无需连续存储,有助于内存利用。

‌单链表的优缺点‌
优点

插入和删除操作高效,特别是在链表头部或中间位置。

适用于元素数量不固定的动态场景。

缺点

查询效率低,无法直接通过索引访问元素,需从头节点顺序遍历。
‌单链表的使用场景‌
链表是非常重要的数据结构,应用场景广泛。

适用于实现栈、队列、树等复杂数据结构。

在需要频繁插入和删除操作的场景中表现出色,如动态数据集合、缓存淘汰策略等。

相较于数组,链表在处理元素动态变化的场景时更具优势;但在频繁查询元素的场景中,数组更为合适。

单链表因其动态性和灵活性,在处理元素不固定且需要频繁插入、删除的场景中具有重要的应用价值。

代码实现

一、数据结构定义

// 定义单链表节点结构体
typedef struct ListNode {
    int val;
    struct ListNode* next;
} ListNode;

// 定义单链表结构体(包含头节点)
typedef struct LinkedList {
    ListNode* head;
} LinkedList;

// 创建一个新节点
ListNode* createNode(int val) {
    ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
    newNode->val = val;
    newNode->next = NULL;
    return newNode;
}

// 创建一个空链表
LinkedList* createLinkedList() {
    LinkedList* list = (LinkedList*)malloc(sizeof(LinkedList));
    list->head = NULL;
    return list;
}

二、增删改查操作
插入操作

  1. 头部插入
// 在链表头部插入新节点
void insertAtHead(LinkedList* list, int val) {
    ListNode* newNode = createNode(val);
    newNode->next = list->head;
    list->head = newNode;
}
  1. 中间插入
// 在指定位置(假设位置从1开始计数)之后插入新节点
void insertAfterPosition(LinkedList* list, int position, int val) {
    ListNode* newNode = createNode(val);
    ListNode* current = list->head;
    int count = 1;
    while (current!= NULL && count < position) {
        current = current->next;
        count++;
    }
    if (current!= NULL) {
        newNode->next = current->next;
        current->next = newNode;
    } else {
        printf("Position out of range.\n");
    }
}
  1. 尾部插入
// 在链表尾部插入新节点
void insertAtTail(LinkedList* list, int val) {
    ListNode* newNode = createNode(val);
    if (list->head == NULL) {
        list->head = newNode;
        return;
    }
    ListNode* current = list->head;
    while (current->next!= NULL) {
        current = current->next;
    }
    current->next = newNode;
}

删除操作

  1. 删除头部节点
// 删除链表头部节点
void deleteHead(LinkedList* list) {
    if (list->head!= NULL) {
        ListNode* temp = list->head;
        list->head = list->head->next;
        free(temp);
    } else {
        printf("List is empty.\n");
    }
}
  1. 删除中间节点
// 删除指定位置(假设位置从1开始计数)的节点
void deleteAtPosition(LinkedList* list, int position) {
    ListNode* current = list->head;
    ListNode* prev = NULL;
    int count = 1;
    while (current!= NULL && count < position) {
        prev = current;
        current = current->next;
        count++;
    }
    if (current!= NULL) {
        if (prev == NULL) {
            list->head = current->next;
        } else {
            prev->next = current->next;
        }
        free(current);
    } else {
        printf("Position out of range.\n");
    }
}
  1. 删除尾部节点
// 删除链表尾部节点
void deleteTail(LinkedList* list) {
    if (list->head == NULL) {
        printf("List is empty.\n");
        return;
    }
    ListNode* current = list->head;
    ListNode* prev = NULL;
    while (current->next!= NULL) {
        prev = current;
        current = current->next;
    }
    if (prev == NULL) {
        list->head = NULL;
    } else {
        prev->next = NULL;
    }
    free(current);
}

查询操作

// 查询链表中是否存在指定值
int searchList(LinkedList* list, int val) {
    ListNode* current = list->head;
    while (current!= NULL) {
        if (current->val == val) {
            return 1;
        }
        current = current->next;
    }
    return 0;
}

修改操作

// 修改指定位置(假设位置从1开始计数)节点的值
void modifyAtPosition(LinkedList* list, int position, int newVal) {
    ListNode* current = list->head;
    int count = 1;
    while (current!= NULL && count < position) {
        current = current->next;
        count++;
    }
    if (current!= NULL) {
        current->val = newVal;
    } else {
        printf("Position out of range.\n");
    }
}

三、算法进阶

翻转链表

// 翻转单链表
ListNode* reverseList(LinkedList* list) {
    ListNode* prev = NULL;
    ListNode* current = list->head;
    ListNode* next = NULL;
    while (current!= NULL) {
        next = current->next;
        current->next = prev;
        prev = current;
        current = next;
    }
    list->head = prev;
    return list->head;
}

找链表的倒数第 k 个节点

// 找到单链表的倒数第 k 个节点
ListNode* findKthFromEnd(LinkedList* list, int k) {
    ListNode* slow = list->head;
    ListNode* fast = list->head;
    // 让快指针先走 k 步
    for (int i = 0; i < k; i++) {
        if (fast == NULL) {
            printf("k is larger than the length of the list.\n");
            return NULL;
        }
        fast = fast->next;
    }
    // 然后慢指针和快指针一起走,当快指针走到链表末尾时,慢指针就是倒数第 k 个节点
    while (fast!= NULL) {
        slow = slow->next;
        fast = fast->next;
    }
    return slow;
}

判断单链表是否有环

// 判断单链表是否有环
int hasCycle(LinkedList* list) {
    ListNode* slow = list->head;
    ListNode* fast = list->head;
    while (fast!= NULL && fast->next!= NULL) {
        slow = slow->next;
        fast = fast->next->next;
        if (slow == fast) {
            return 1; // 有环
        }
    }
    return 0; // 无环
}

希望这篇文章能对你有所帮助,记得收藏起来哦,方便随时查阅和复习。

标签:current,head,NULL,ListNode,list,next,链表,源码,C语言
From: https://www.cnblogs.com/newtonaicoding/p/18563834

相关文章

  • 【计算机毕业设计选题】最新毕设选题----基于微信小程序的校园心理咨询服务系统的设计
    博主介绍:原计算机互联网大厂开发,十年开发经验,带领技术团队几十名,专注技术开发,计算机毕设实战导师,专注Java、Python、小程序、安卓、深度学习和算法开发研究。主要服务内容:选题定题、开题报告、任务书、程序开发、文档编写和辅导、文档降重、程序讲解、答辩辅导等,欢迎咨询~......
  • 计算机毕业设计推荐】基于SpringBoot+Vue的甜品店管理系统的设计与实现 【附源码+数据
    ✍✍计算机编程指导师⭐⭐个人介绍:自己非常喜欢研究技术问题!专业做Java、Python、小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。⛽⛽实战项目:有源码或者技术上的问题欢迎在评论区一起讨论交流!⚡⚡Java实战|SpringBoot/SSMPython实战项目|Django微信小程......
  • 【计算机毕业设计选题推荐】基于springboot+vue的实践性教学系统的设计与实现 【附源
    ✍✍计算机编程指导师⭐⭐个人介绍:自己非常喜欢研究技术问题!专业做Java、Python、小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。⛽⛽实战项目:有源码或者技术上的问题欢迎在评论区一起讨论交流!⚡⚡Java实战|SpringBoot/SSMPython实战项目|Django微信小程......
  • C语言 ———— 速通指针 我们要了解什么?
    我们学习C语言指针,最应该了解的应该是它的本质,它在C语言中很多时候是与地址等价的;在这里,指针str指向的就是内存中a的地址,如果这是arr数组,那么在使用时,str==arr,原因是arr这个数组名就是数组首元素地址,而str这个指针的具象化就是如图,一个指向arr首元素的箭头,在调用str时,实际上......
  • C语言初体验
    在还未接触C语言之前,对编程一窍不通,而在学习了一段时间后,恰似打开了一扇新世界的大门,从”helloworld“到现在的能够独立做出一道简单的编程题,收获颇深,成就感满满。在开始学习之前还是十分畏惧的,毕竟对此没有一点了解,就是一个完全崭新的东西让我们来学习,虽然如此,对于我们来说......
  • C语言内存函数
    目录1.mencpy使用和模拟实现2.memmove使用和模拟实现3.memset函数的使用4.memcmp函数的使用5.小结1.mencpy使用和模拟实现void*memcpy(void*destination,constvoid*source,size_tnum); 函数memcpy从source的位置开始向后复制num个字节的数据到destina......
  • SSM仓库员工管理系统88qro--(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容一、项目背景与意义随着物流行业的快速发展,仓库作为物流链条中的重要环节,其管理效率直接影响到整个物流体系的运作。仓库员工作为仓库运营的核心力......
  • SSM殡仪馆管理系统s5n80(程序+源码+数据库+调试部署+开发环境)
    题目:殡仪馆管理系统进度安排:(1)2024年11月1日-2024年11月15日 确定选题,下达任务书,撰写开题报告;(2)2024年11月15日-2024年12月20日提交开题报告定稿;(3)2024年12月21日-2025年3月14日 完成选题的设计、论文大纲的撰写;(4)2025年3月15日-2025年3月21日  毕业(设计)论文中期检查......
  • SSM本地美食推荐平台evbxz(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容一、研究背景与意义在当今快节奏的生活中,人们对美食的需求日益增加,但往往难以找到真正符合口味和需求的餐厅。本地美食推荐平台的出现,旨在解决这一......
  • SSM安康学院新型冠状病毒肺炎疫情专题网53wrh--(程序+源码+数据库+调试部署+开发环境)
    题目:SSM安康学院新型冠状病毒肺炎疫情专题网53wrh进度安排:(1)2024年11月1日-2024年11月15日 确定选题,下达任务书,撰写开题报告;(2)2024年11月15日-2024年12月20日提交开题报告定稿;(3)2024年12月21日-2025年3月14日 完成选题的设计、论文大纲的撰写;(4)2025年3月15日-2025年3月2......