C语言实现单链表的基本功能详解

yizhihongxing

C语言实现单链表的基本功能详解

简介

单链表是一种常见的数据结构,由一系列的节点(Node)组成,每个节点包含数据和指向下一个节点的指针,最后一个节点的指针为NULL。C语言实现单链表需要掌握指针和动态内存分配的知识,具有一定难度。本文将详细讲解C语言实现单链表的基本功能。

基本结构

定义单链表结点的结构体,包括数据和指向下一个结点的指针,如下所示:

typedef struct node
{
    int data;
    struct node *next;
} Node;

该结构体定义了一个Node类型的节点,包含数据data和指向下一个节点的指针next。

定义头节点,头节点不存储数据,只用于表示单链表的开始。

Node *head = NULL;

head是一个指向Node类型的指针,初始值为NULL,表示链表为空。

基本功能

添加节点

添加节点是单链表最基本的操作之一,在单链表中,可以在头节点或者尾节点后面添加一个新节点。

在头节点后插入

在头节点后插入新节点,需要先创建一个新节点,然后将新节点的next指针指向head,再将head指向新节点。

void insertAtHead(int data)
{
    Node *newNode = (Node *)malloc(sizeof(Node));
    newNode->data = data;
    newNode->next = head;
    head = newNode;
}

在尾节点后插入

在尾节点后插入新节点,需要先找到尾节点,然后创建新节点,将尾节点的next指向新节点,再将新节点的next指针设置为NULL。

void insertAtTail(int data)
{
    Node *newNode = (Node *)malloc(sizeof(Node));
    newNode->data = data;
    newNode->next = NULL;

    if (head == NULL)   // 空链表,直接插入
    {
        head = newNode;
        return;
    }

    Node *p = head;
    while (p->next != NULL) 
    {
        p = p->next;
    }
    p->next = newNode;
}

删除节点

删除节点同样是单链表的基本操作之一,可以删除指定位置的节点,或者删除指定数值的节点。

删除指定位置节点

删除指定位置节点,需要先找到指定位置,然后修改前一个节点的next指针,使其指向被删除节点的下一个节点。

void deleteByPos(int pos)
{
    if (head == NULL)
    {
        printf("链表为空\n");
        return;
    }

    if (pos == 1)   // 删除头节点
    {
        Node *temp = head;
        head = head->next;
        free(temp);
        temp = NULL;
        return;
    }

    Node *p = head;
    int i = 1;
    while (p != NULL && i < pos - 1)  // 找到要删除节点的前一个节点
    {
        p = p->next;
        i++;
    }

    if (p == NULL || p->next == NULL)  // 要删除的节点不存在
    {
        printf("要删除的节点不存在\n");
        return;
    }

    Node *temp = p->next;
    p->next = temp->next;
    free(temp);
    temp = NULL;
}

删除指定数值节点

删除指定数值节点,需要遍历单链表,找到指定数值的节点,然后进行删除操作。

void deleteByData(int data)
{
    if (head == NULL)
    {
        printf("链表为空\n");
        return;
    }

    if (head->data == data)  // 删除头节点
    {
        Node *temp = head;
        head = head->next;
        free(temp);
        temp = NULL;
        return;
    }

    Node *p = head;
    while (p->next != NULL && p->next->data != data)
    {
        p = p->next;
    }

    if (p->next == NULL)  // 要删除的节点不存在
    {
        printf("要删除的节点不存在\n");
        return;
    }

    Node *temp = p->next;
    p->next = temp->next;
    free(temp);
    temp = NULL;
}

查找节点

查找节点可以按位置查找,也可以按数值查找。

按位置查找

按位置查找,需要遍历单链表,找到指定位置的节点。

Node *findByPos(int pos)
{
    if (head == NULL)
    {
        printf("链表为空\n");
        return NULL;
    }

    Node *p = head;
    int i = 1;
    while (p != NULL && i < pos)
    {
        p = p->next;
        i++;
    }

    if (p == NULL)  // 要查找的节点不存在
    {
        printf("要查找的节点不存在\n");
        return NULL;
    }

    return p;
}

按数值查找

按数值查找,同样需要遍历单链表,找到指定数值的节点。

Node *findByData(int data)
{
    if (head == NULL)
    {
        printf("链表为空\n");
        return NULL;
    }

    Node *p = head;
    while (p != NULL && p->data != data)
    {
        p = p->next;
    }

    if (p == NULL)  // 要查找的节点不存在
    {
        printf("要查找的节点不存在\n");
        return NULL;
    }

    return p;
}

示例说明

示例一:在头节点插入新节点

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

typedef struct node
{
    int data;
    struct node *next;
} Node;

Node *head = NULL;

void insertAtHead(int data)
{
    Node *newNode = (Node *)malloc(sizeof(Node));
    newNode->data = data;
    newNode->next = head;
    head = newNode;
}

int main()
{
    insertAtHead(3);
    insertAtHead(2);
    insertAtHead(1);

    Node *p = head;
    while (p != NULL)
    {
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");

    return 0;
}

输出结果:

1 2 3

示例二:在尾节点插入新节点

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

typedef struct node
{
    int data;
    struct node *next;
} Node;

Node *head = NULL;

void insertAtTail(int data)
{
    Node *newNode = (Node *)malloc(sizeof(Node));
    newNode->data = data;
    newNode->next = NULL;

    if (head == NULL)
    {
        head = newNode;
        return;
    }

    Node *p = head;
    while (p->next != NULL)
    {
        p = p->next;
    }
    p->next = newNode;
}

int main()
{
    insertAtTail(1);
    insertAtTail(2);
    insertAtTail(3);

    Node *p = head;
    while (p != NULL)
    {
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");

    return 0;
}

输出结果:

1 2 3

总结

本文主要讲解了C语言实现单链表的基本功能,包括添加节点、删除节点、查找节点等操作。需要掌握的知识点有指针和动态内存分配。单链表是一种非常常用的数据结构,掌握基本操作可以为后续数据结构和算法的学习打下基础。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言实现单链表的基本功能详解 - Python技术站

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

相关文章

  • Element-ui upload上传文件限制的解决方法

    当使用 Element-ui 的 Upload 组件时,我们可能会遇到一些文件大小或文件数量的限制问题。这里提供一些解决这类问题的方法。 限制上传文件数量 我们可以使用 Element-ui 的 limit 属性来限制可以上传的文件数量。例如,以下代码将限制用户最多只能上传 3 个文件: <el-upload :limit="3" …

    other 2023年6月27日
    00
  • Android样式和主题之选择器的实例讲解

    Android样式和主题之选择器的实例讲解 在Android开发中,样式和主题是非常重要的概念,它们可以用来定义应用程序的外观和行为。其中,选择器是一种特殊的样式,它可以根据不同的状态来改变控件的外观。本文将详细讲解如何使用选择器来定义控件的样式。 选择器的基本语法 选择器是一个XML文件,它定义了一组状态和对应的样式。以下是选择器的基本语法: <se…

    other 2023年8月20日
    00
  • 在.NET 6中使用日志组件log4net的方法

    在.NET 6中使用日志组件log4net的方法,可以通过以下步骤进行: 安装log4net 首先,需要安装log4net。这可以通过NuGet包管理器来完成,或者在项目文件中手动添加对log4net的引用。 例如,在Visual Studio中,可以通过NuGet包管理器搜索log4net,然后选择安装该包。 添加配置文件 在使用log4net前,需要为其…

    other 2023年6月27日
    00
  • ASP.NET防止页面刷新的两种解决方法小结

    我将为你详细讲解“ASP.NET防止页面刷新的两种解决方法小结”的完整攻略。 什么是页面刷新 页面刷新指的是用户在浏览器上通过刷新按钮或者F5键等方式重新加载页面,导致页面重新从服务器端获取数据并重新渲染页面的过程。 防止页面刷新的两种解决方法 1.使用AJAX技术 AJAX即异步JavaScript和XML技术,通过使用AJAX技术可以实现无需页面刷新的异…

    other 2023年6月27日
    00
  • SpringBoot读取外部配置文件的方法

    下面我来详细讲解一下“SpringBoot读取外部配置文件的方法”的完整攻略。 1. SpringBoot读取外部配置文件的方法 在 Spring Boot 中,我们可以通过在 application.properties/application.yml 文件中配置属性来自定义应用的一系列配置信息。但是有时候我们需要将配置信息放到磁盘上的其他配置文件中,以方…

    other 2023年6月25日
    00
  • linux下如何读取使用iso 镜像文件的方法

    读取使用ISO镜像文件是Linux系统中常见的操作之一。下面是Linux系统下读取使用ISO镜像文件的方法攻略: 1. 检查ISO镜像文件 首先需要检查确保要使用的ISO镜像文件是否存在,以及ISO镜像文件所在的路径和文件名是否正确。 2. 挂载ISO镜像文件 接下来需要将ISO镜像文件挂载到Linux系统上,使得文件能够被系统访问和使用。使用以下命令挂载I…

    other 2023年6月28日
    00
  • 解决python 读取npy文件太大不能完全显示的问题

    当我们使用Python读取大型np.array文件(npy格式)时,有时我们可能会遇到读取后无法完全显示的问题。这通常是由于数组过大导致的内存限制,为了解决这个问题,以下是解决方法的完整攻略: 分段读取 当数组太大时,我们可以分段读取。这种方法使用Python迭代器来访问数组的各个部分,并将它们分别存储在内存中。我们可以使用以下代码来读取大型npy文件: i…

    other 2023年6月27日
    00
  • 解读C++中枚举(enum)的使用

    解读C++中枚举(enum)的使用攻略 枚举(enum)是C++中一种用于定义命名常量的数据类型。它允许我们为一组相关的常量赋予有意义的名称,使代码更易读、更易维护。本攻略将详细介绍C++中枚举的使用方法,并提供两个示例说明。 1. 定义枚举类型 在C++中,我们可以使用enum关键字来定义枚举类型。以下是定义枚举类型的语法: enum 枚举类型名 { 常量…

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