【数据结构】C语言从零编写一个链表

前言

链表不同于顺序表,顺序表是以数组为存储基础的数据结构,它在内存中表现为一块连续的内存空间;而链表不需要,它通过一个指针来连接各个分散的结点,形成了一个链状的结构,每个结点存放一个元素,以及一个指向下一个结点的指针,通过这样一个一个相连,最后形成了链表。

链表分为带头结点的链表和不带头结点的链表,戴头结点的链表就是会有一个头结点指向后续的整个链表,但是头结点不存放数据。本篇博客构建一个带头节点的链表。

构建单个节点的结构体

首先构建一个结构体表示链表的单个节点;其中包含该节点储存的数据,和下一个节点的指针。

typedef int E;

struct ListNode
{
    E element;
    struct ListNode * next;
};

typedef struct ListNode * Node;

typedef关键字为int类型定义了一个新的别名E。

定义了一个名为ListNode的结构体。这个结构体表示单链表中的一个节点。

编写初始化函数

初始化链表的时候,由于只有一个头节点,所以我们让该节点指向的下一个地址为NULL。

void initList(Node node)
{
    node->next = NULL;
}

初始化一个链表的头节点,使其next指针指向NULL,以表示这是一个空链表或者该节点是链表的最后一个节点。

实现链表的插入

链表的插入大概分为三个步骤

  • 首先找到需要插入的地方
  • 将需要插入的节点指向前驱节点的下一个节点
  • 将前驱节点指向需要插入的节点
int insertList(Node node,E element,int index)
{
    if (index < 1) return 0;
    while (--index)
    {
        node = node->next;
        if (node == NULL) return 0;
    }
    Node new_node = malloc(sizeof (struct ListNode));
    new_node->element = element;
    new_node->next = node->next;
    node->next = new_node;

    return 1;

}

函数在成功插入后返回 1,表示插入成功。

这样就编写完链表的插入操作了,现在来测试一下;

编写一个打印链表元素的函数:

void printList(Node head){
    while (head->next) {
        head = head->next;
        printf("%d ", head->element);
    }
}

在主函数中初始化链表 并执行测试函数:

int main()
{
    struct ListNode head;
    initList(&head);
    for (int i = 1; i <= 3; ++i) {
        insertList(&head, i * 10, i);
    }
    printList(&head); // 10 20 30

    return 0;
}

数据成功打印。

实现删除链表节点的功能

删除节点主要分三步:

  • 找到需要删除的节点
  • 将该节点的上一个节点指向需要删除节点的下一个节点
  • 释放需要删除的节点的内存空间
int deleteList(Node node,int index)
{
    if (index < 1) return 0;

    while (--index) {
        node = node->next;
        if(node == NULL) return 0;
    }

    Node tmp = node->next; // 存储待删除节点的地址
    node->next = node->next->next;
    free(tmp); // 释放地址

    return 1;
}

获取对应位置上的元素

getList函数则用于获取链表中指定索引处的元素地址。

E * getList(Node node,int index)
{
    if (index < 1) return NULL;
    do {
        node = node->next;
        if (node == NULL) return NULL;
    } while (--index);
    
    return &(node->element);
}

查找对应元素的位置

findList的目的是在一个链表中查找一个特定的元素element,并返回该元素在链表中的位置(假设从1开始计数)。

int findList(Node node, E element)
{
    int i = 1;
   node = node->next;
    while (node)
    {
        if (node->element == element) return i;
        node = node->next;
        i++;
    }

    return -1;
}

求链表的长度

int sizeList(Node node)
{
    int i = 0;
    while(node->next)
    {
        node = node->next;
        i++;
    }
    return i;
}

全部代码

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

/*
 * 链表
 */
typedef int E;

struct ListNode
{
    E element;
    struct ListNode * next;
};

typedef struct ListNode * Node;

void initList(Node node)
{
    node->next = NULL;
}

int insertList(Node node,E element,int index)
{
    if (index < 1) return 0;
    while (--index)
    {
        node = node->next;
        if (node == NULL) return 0;
    }
    Node new_node = malloc(sizeof (struct ListNode));
    new_node->element = element;
    new_node->next = node->next;
    node->next = new_node;

    return 1;

}

int deleteList(Node node,int index)
{
    if (index < 1) return 0;

    while (--index) {
        node = node->next;
        if(node == NULL) return 0;
    }

    Node tmp = node->next; // 存储待删除节点的地址
    node->next = node->next->next;
    free(tmp); // 释放地址

    return 1;
}

E * getList(Node node,int index)
{
    if (index < 1) return NULL;
    do {
        node = node->next;
        if (node == NULL) return NULL;
    } while (--index);

    return &(node->element);
}

int findList(Node node, E element)
{
    int i = 1;
   node = node->next;
    while (node)
    {
        if (node->element == element) return i;
        node = node->next;
        i++;
    }

    return -1;
}

int sizeList(Node node)
{
    int i = 0;
    while(node->next)
    {
        node = node->next;
        i++;
    }
    return i;
}

void printList(Node head){
    while (head->next) {
        head = head->next;
        printf("%d ", head->element);
    }
}

int main()
{
    struct ListNode head;
    initList(&head);
    for (int i = 1; i <= 3; ++i) {
        insertList(&head, i * 10, i);
    }
    printList(&head);

    return 0;
}
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冲鸭嘟嘟可

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值