​​​​​​​C语言实现单链表基本操作方法

yizhihongxing

下面是C语言实现单链表基本操作方法的完整攻略:

1. 定义单链表结构体

首先,需要定义一个单链表结构体,来描述节点的信息。结构体应该包含两个部分:数据域和指针域。数据域存储节点的值,指针域存储指向下一个节点的指针。

struct ListNode {
    int val;                // 数据域,此处数据类型为 int
    struct ListNode *next;  // 指针域,指向下一个节点
};

2. 添加节点

添加节点是单链表的最基本操作。我们需要定义一个函数来实现添加节点的功能。

首先,我们需要创建一个新节点,并为它分配内存空间。然后,根据需求将新节点插入到链表中,这需要找到要插入的位置,即要插入节点的前一个节点。最后,将新节点插入到链表中,并调整前一个节点和后一个节点的指针。

void insertNode(struct ListNode **head, int val) {
    // 创建新节点,并为其分配内存空间
    struct ListNode* newNode = (struct ListNode*)malloc(sizeof(struct ListNode));
    newNode->val = val;
    newNode->next = NULL;

    // 特判链表为空的情况
    if (*head == NULL) {
        *head = newNode;
        return;
    }

    // 找到要插入的位置,即要插入节点的前一个节点
    struct ListNode* prev = NULL;
    struct ListNode* curr = *head;
    while (curr && curr->val < val) {
        prev = curr;
        curr = curr->next;
    }

    // 将新节点插入到链表中
    if (prev == NULL) {
        // 如果要插入到链表头部
        newNode->next = *head;
        *head = newNode;
    } else {
        // 如果要插入到链表中间或尾部
        newNode->next = prev->next;
        prev->next = newNode;
    }
}

上述函数中,使用了一个双重指针的技巧,用来修改头结点。具体实现过程如下:

struct ListNode* head = NULL;
...
insertNode(&head, 3);

3. 删除节点

删除节点是单链表的另一个基本操作。我们也需要定义一个函数来实现删除节点的功能。

在删除节点之前,我们需要首先找到要删除的节点,即要删除节点的前一个节点。然后,将前一个节点的指针指向要删除节点的下一个节点,再将要删除节点的空间释放。

void deleteNode(struct ListNode **head, int val) {
    // 特判链表为空的情况
    if (*head == NULL) {
        return;
    }

    // 特判要删除的节点为头结点的情况
    if ((*head)->val == val) {
        struct ListNode* temp = *head;
        *head = (*head)->next;
        free(temp);
        return;
    }

    // 找到要删除的节点,即要删除节点的前一个节点
    struct ListNode* prev = NULL;
    struct ListNode* curr = *head;
    while (curr && curr->val != val) {
        prev = curr;
        curr = curr->next;
    }

    // 删除节点,并释放空间
    if (curr) {
        prev->next = curr->next;
        free(curr);
    }
}

上述函数中也使用了双重指针的技巧。

示例说明

下面通过两个示例来说明如何使用上述函数操作单链表。

示例1:添加节点

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

struct ListNode {
    int val;
    struct ListNode *next;
};

void insertNode(struct ListNode **head, int val) {
    struct ListNode* newNode = (struct ListNode*)malloc(sizeof(struct ListNode));
    newNode->val = val;
    newNode->next = NULL;
    if (*head == NULL) {
        *head = newNode;
        return;
    }
    struct ListNode* prev = NULL;
    struct ListNode* curr = *head;
    while (curr && curr->val < val) {
        prev = curr;
        curr = curr->next;
    }
    if (prev == NULL) {
        newNode->next = *head;
        *head = newNode;
    } else {
        newNode->next = prev->next;
        prev->next = newNode;
    }
}

int main() {
    struct ListNode* head = NULL;
    insertNode(&head, 3);
    insertNode(&head, 1);
    insertNode(&head, 2);
    insertNode(&head, 4);
    insertNode(&head, 5);
    struct ListNode* curr = head;
    while (curr) {
        printf("%d ", curr->val);
        curr = curr->next;
    }
    return 0;
}

输出结果为:1 2 3 4 5。

示例2:删除节点

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

struct ListNode {
    int val;
    struct ListNode *next;
};

void insertNode(struct ListNode **head, int val) {
    struct ListNode* newNode = (struct ListNode*)malloc(sizeof(struct ListNode));
    newNode->val = val;
    newNode->next = NULL;
    if (*head == NULL) {
        *head = newNode;
        return;
    }
    struct ListNode* prev = NULL;
    struct ListNode* curr = *head;
    while (curr && curr->val < val) {
        prev = curr;
        curr = curr->next;
    }
    if (prev == NULL) {
        newNode->next = *head;
        *head = newNode;
    } else {
        newNode->next = prev->next;
        prev->next = newNode;
    }
}

void deleteNode(struct ListNode **head, int val) {
    if (*head == NULL) {
        return;
    }
    if ((*head)->val == val) {
        struct ListNode* temp = *head;
        *head = (*head)->next;
        free(temp);
        return;
    }
    struct ListNode* prev = NULL;
    struct ListNode* curr = *head;
    while (curr && curr->val != val) {
        prev = curr;
        curr = curr->next;
    }
    if (curr) {
        prev->next = curr->next;
        free(curr);
    }
}

int main() {
    struct ListNode* head = NULL;
    insertNode(&head, 3);
    insertNode(&head, 1);
    insertNode(&head, 2);
    insertNode(&head, 4);
    insertNode(&head, 5);
    deleteNode(&head, 3);
    deleteNode(&head, 1);
    struct ListNode* curr = head;
    while (curr) {
        printf("%d ", curr->val);
        curr = curr->next;
    }
    return 0;
}

输出结果为:2 4 5。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:​​​​​​​C语言实现单链表基本操作方法 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • 基于HTML5上使用iScroll实现下拉刷新,上拉加载更多

    以下是“基于HTML5上使用iScroll实现下拉刷新,上拉加载更多”的完整攻略: 1. 安装 iScroll 首先,我们需要在 HTML 中引入 iScroll 脚本文件。可以通过以下方式引入: <script type="text/javascript" src="iscroll.js"></sc…

    other 2023年6月25日
    00
  • Redis连接池配置及初始化实现

    下面我将详细讲解Redis连接池的配置及初始化实现攻略,包含以下几个方面的内容: Redis连接池介绍 Redis连接池配置 Redis连接池初始化实现 示例说明 1. Redis连接池介绍 Redis连接池是一种可以重复利用Redis连接的技术,通过连接池可以有效地减少连接Redis的时间并提高并发能力。它的工作原理是创建多个Redis连接,将这些连接存放…

    other 2023年6月20日
    00
  • Win10 Build 10565快速预览版为什么有ISO镜像下载地址?

    Win10 Build 10565快速预览版为什么有ISO镜像下载地址? 微软发布的Windows 10 Build 10565快速预览版是操作系统的一个早期版本,用于测试和收集用户反馈。为了方便用户安装和测试该版本,微软提供了ISO镜像下载地址。以下是详细的攻略: 步骤一:了解ISO镜像的作用 ISO镜像是一个完整的操作系统映像文件,包含了操作系统的所有文…

    other 2023年8月4日
    00
  • 常用批处理内部命令使用详解

    常用批处理内部命令使用详解 简介 批处理是可以用来批量执行指令的脚本语言,常用于Windows系统中。批处理有许多内部命令可以使用,此文档将详细讲解批处理中常用的内部命令及其用法。 命令说明 ECHO ECHO命令可以输出文字、变量或命令的执行结果到屏幕上。 语法: ECHO [ON | OFF] [message] 示例: 输出“Hello World!”…

    other 2023年6月26日
    00
  • dicom医学图像处理:fo-dicom网络传输之c-echoandc-store

    以下是“DICOM医学图像处理:fo-dicom网络传输之C-ECHO和C-STORE”的完整攻略: DICOM医学图像处理:fo-dicom网络传输之C-ECHO和C-STORE DICOM(数字成像和通信医学)是医学图像中广泛使用的标准。在DICOM中,C-ECHO和C-STORE是两个常用的网络传输协议,用于检查DICOM设备之间的连接和传输图像。本攻…

    other 2023年5月7日
    00
  • Android原生集成RN最新版教程

    下面是针对“Android原生集成RN最新版教程”的完整攻略。 什么是Android原生集成RN Android原生集成RN是指将React Native(以下简称RN)框架集成到Android原生应用程序中,在Android原生应用程序中使用RN开发页面和模块。RN是Facebook推出的跨平台开发框架,使得开发者可以用相同的代码基础编写iOS和Andro…

    other 2023年6月26日
    00
  • 让你Python到很爽的加速递归函数的装饰器

    为了优化递归函数的执行效率,我们可以使用装饰器来将递归转化为迭代,从而提高代码的性能。以下是让你Python到很爽的加速递归函数的装饰器的完整攻略。 步骤1:编写递归函数 首先,我们需要编写一个递归函数,以便后面使用装饰器进行优化。以下是一个经典的斐波那契数列递归实现: def fibonacci(n): if n <= 1: return n els…

    other 2023年6月27日
    00
  • vue动态路由实现多级嵌套面包屑的思路与方法

    Vue动态路由实现多级嵌套面包屑的思路与方法 在Vue中,我们可以通过动态路由来实现多级嵌套面包屑导航。下面是一个完整的攻略,包含了思路和方法,并提供了两个示例说明。 思路 实现多级嵌套面包屑导航的思路如下: 在路由配置中定义每个路由的meta字段,用于存储面包屑导航的信息。 在组件中使用$route对象获取当前路由信息,并根据meta字段生成面包屑导航数据…

    other 2023年7月27日
    00
合作推广
合作推广
分享本页
返回顶部