单链表的实现--C 语言版,详细讲解+代码实现

本文介绍了如何使用C语言实现单链表,包括创建数据结构体、初始化链表、头插法和后插法插入数据、删除节点以及遍历链表。文中提供了详细的代码实现,并通过一个示例展示了如何操作链表。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

单链表的实现–C 语言版,详细讲解+代码实现



前言

用C语言实现单链表


一、单链表的介绍

首先,由n个数据特征相同的元素组成的有序序列,叫做线性表。
线性表由以下特点:
1.存在唯一一个被称为“第一个”的数据元素
2.存在唯一一个被称为“最后一个”的数据元素
3.除了第一个元素外,任何元素都只有一个前驱
4.除了最后一个元素外,任何一个元素都只有一个后继。
顺序表这边简单分为线性表和链式表,线性表就是存储地址相邻的一组数据,简单可以理解为一个相同数据结构的数组。
链式表简单理解就是地址不相邻的一个序列,序列中的相邻元素由一个指针来指向
链式表中的结点一般由两部分组成,一部分用于存放数据,可以是一个结构体,另一个是地址,存放这个结点的后继(下一个结点)的地址,方便寻找。
链式表中,一般将第一个结点成为头节点,这个结点不存放数据,在初始化时初始化这一个结点,这个节点的名字一般也是这个单链表的名字,之所以创造这个头节点,主要是为了方便编程,有这个头节点在,整个链表的操作基本都是一致的,不存在例外情况。
头节点中可以存储链表的长度,以增加链表操作的拓展性,最后一个结点的指针为null
在这里插入图片描述

二、代码实现

1. 创建数据结构体

结构体这边第一个元素是结点存储的数据,为方便操作就将数据存储类型设计为int型,另一个元素是下一个结点的地址,我们将其命名为next。

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

2. 初始化

所谓初始化,就是创建一个头节点,这边将头节点的数据存储为链表的长度,由于是头指针,链表中还没有其他结点,所以将头节点的next设为null。

//初始化
Node* initList(){
    Node* list = (Node*)malloc(sizeof(Node));
 //   Node* list ;
    list->data=0;
    list->next=NULL;
    return list;

3. 插入数据(头插法)

头插法就是新插入的数据都会放到第一个,然后原本存在的数据会往后移动,由于头节点中并不存储实际的数据,所以本据中第一个指的就是头节点后的第一个数据。
简单描述就是:
1.初始化一个结点,结点的data储存的是要插入的数据。
2.调整地址,由于是头插法,要将元素插到第一个(头节点之后),所以我们需要做的就是 将新的结点的地址指向原本的第一个结点,然后将头节点的地址指向新节点。

//头插法
void headinsert(Node* list,int data){
    Node* node=(Node*)malloc(sizeof(Node));
    node->data=data;
    node->next=list->next;
    list->next=node;
    list->data++;  //链表的长度+1
}

3. 插入数据(后插法)

后插法就是将要插入的数据查到序列的尾部。
1.首先创建一个新的结点,结点的data存储要插入的数据。
2.将链表的结点进行循环,直到链表的next为空,停止循环,意味着当前的结点就是原本序列的最后一个结点,再将最后一个结点的指针指向新的结点,新的结点的指针设为null即可。
这边之所以要创造一个新的结点并将第一个结点赋值给它是因为这边的变量都是和地址有关的,当进行操作时,变量的地址变化之后一般不能重复使用。

void tailinsert(Node* list,int data){
    Node* node=(Node*)malloc(sizeof(Node));
    node->data=data;
    node->next=NULL;
    
    Node* nodes=(Node*)malloc(sizeof(Node));
    nodes = list->next;
    while (nodes->next)
    {
        nodes = nodes->next;
    }
    nodes->next=node;
    list->data++;//链表的长度+1
}

4. 删除

删除就是将要拥有要删除的data值的结点从链表中移除
步骤为:
1. 找到这个结点
2. 删除这个结点
由于第一个结点就可能是要删除的结点,同时,为了能够将数据删除后拼接这个结点的前后段,所以我们需要定义两个辅助结点
思路可以理解为:
删除当前结点后,上一个结点的next指向当前结点的next

void delete(Node* list,int data){
    Node* pre = list;
    Node* node = list->next;
    while (node)
    {
        if(node->data==data){
            pre->next=node->next;
            list->data--;
            // free(node);
            break;
        }
        pre=pre->next;
        node = node->next;
    }
}

5.遍历

遍历就是将单链表中的元素都输出一遍
直接从第一个结点开始循环输出即可。

void show(Node* list){
    Node* node = list->next;
    while (node)
    {
        printf("%d\n",node->data);
        node = node->next;
    }
}

6.运行

int main(){
    Node* list = initList();
    headinsert(list,1);
    headinsert(list,2);
    headinsert(list,3);
    tailinsert(list,4);
    tailinsert(list,5);
    tailinsert(list,6);
    delete(list,3);
    show(list);
    return 0;
}

在这里插入图片描述


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值