C语言实现单链表及其打印

学习单链表之前,需要先了解顺序表

顺序表:顺序表其实可以看成一串数组,有对应的下标(如a[0] a[1]等),而且他们的地址是连续的。(如下图)

 单链表与顺序表的不同之处就是:单链表并不会和顺序表一样有对应的下标,单链表的每个空间的地址是不连续的,但是每个空间都会有一个指针指向下一个空间,所以从空间来说是连续的。(如下图)

那么问题来了,链表的每个空间是如何拥有下一个元素的地址呢?

很简单,每个空间都会有相对应的地址,那么每个空间是如何存储元素与下一个空间的地址呢?

也很简单,只需要创建一个结构体就好了,每个结构体都定义一个接收元素的变量以及接收下一个空间地址的指针就好了。(比如第一个空间地址是A,第二个是B,第三个是C,第四个是D,那么第一个空间的指针是第二个空间的地址,第二个空间的指针是第三个空间的地址,以此类推)

那么链表最后一个元素的又该指向哪呢?

当然是赋NULL,空指针。这样的话,在打印链表的时候,一旦遇到NULL就可以停止打印了。(如下图)

恭喜你,了解了单链表的简单原理,接下来就开始用C语言模拟实现单链表吧:

首先,先把该用上的头文件给包含了,以及统一全局命名int,方便以后修改元素的类型可以直接一次搞定,就不用一个一个找int来修改了,如下

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SListDatatype;//将int定义成另一个名称,更方便地更改链表元素的类型

typedef struct SListNode  //创建一个结构体空间,里面分别定义了一个元素和下一个元素的地址指针
{
    SListDatatype data;//元素
    struct SListNode* next;//指针
}SLTNode;

当定义好结构体之后(以下称为节点)就需要用到malloc函数用来创建足够的空间装下节点

如下代码:申请了n1 n2 n3 n4四个结点,并且我们将n1->data赋值1,n2赋值2,以此类推

void TestSList1()//向系统申请足够的空间放下节点并定义节点的元素
{
    SLTNode* n1 = (SLTNode*)malloc(sizeof(SLTNode));
    assert(n1);

    SLTNode* n2 = (SLTNode*)malloc(sizeof(SLTNode));
    assert(n2);

    SLTNode* n3 = (SLTNode*)malloc(sizeof(SLTNode));
    assert(n3);

    SLTNode* n4 = (SLTNode*)malloc(sizeof(SLTNode));
    assert(n4);

    n1->data = 1;
    n2->data = 2;
    n3->data = 3;
    n4->data = 4;
}

那么节点直接如何连接呢?

很简单,只需要将n1的指针指向n2,以此类推:如下代码

需要注意的是,n4是最后一个节点,并不需要指向别的地方,就让它指向空指针NULL就好了

void TestSList1()//向系统申请足够的空间放下节点并定义节点的元素
{
    SLTNode* n1 = (SLTNode*)malloc(sizeof(SLTNode));
    assert(n1);

    SLTNode* n2 = (SLTNode*)malloc(sizeof(SLTNode));
    assert(n2);

    SLTNode* n3 = (SLTNode*)malloc(sizeof(SLTNode));
    assert(n3);

    SLTNode* n4 = (SLTNode*)malloc(sizeof(SLTNode));
    assert(n4);

    n1->data = 1;
    n2->data = 2;
    n3->data = 3;
    n4->data = 4;
//将每个节点连接起来
    n1->next = n2;
    n2->next = n3;
    n3->next = n4;
    n4->next = NULL;
}

至此。单链表以及创建完成,让我们看看最终的代码:

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SListDatatype;//将int定义成另一个名称,更方便地更改链表元素的类型

typedef struct SListNode  //创建一个结构体空间,里面分别定义了一个元素和下一个元素的地址指针
{
    SListDatatype data;
    struct SListNode* next;
}SLTNode;

void TestSList1()//向系统申请足够的空间放下节点并定义节点的元素
{
    SLTNode* n1 = (SLTNode*)malloc(sizeof(SLTNode));
    assert(n1);

    SLTNode* n2 = (SLTNode*)malloc(sizeof(SLTNode));
    assert(n2);

    SLTNode* n3 = (SLTNode*)malloc(sizeof(SLTNode));
    assert(n3);

    SLTNode* n4 = (SLTNode*)malloc(sizeof(SLTNode));
    assert(n4);

    n1->data = 1;
    n2->data = 2;
    n3->data = 3;
    n4->data = 4;

    n1->next = n2;
    n2->next = n3;
    n3->next = n4;
    n4->next = NULL;
}

int main() {
    TestSList1();//调用创建节点的函数
    return 0;
}

然后调试代码并调用监视窗口看看效果:

由上图可看见,n1->next是存有n2的地址,n2->next是存有n3的地址,而最后一个n4->next是指向空,此时说明我们的单链表创建成功了。

那么如何将链表打印出来呢?

先将结果放出:

SList.h为头文件

SList.c为打印函数文件

test.c为主函数文件

首先得创建一个头文件,用来定义结构体以及包含别的头文件

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

typedef int SListDatatype;//将int定义成另一个名称,更方便地更改链表元素的类型

typedef struct SListNode  //创建一个结构体空间,里面分别定义了一个元素和下一个元素的地址指针
{
    SListDatatype data;
    struct SListNode* next;
}SLTNode;

然后再单独创建一个.c文件用来存放打印函数(注意!此文件需包含(include)上述的.h头文件

这是重点!此打印函数需要接受头节点的地址,为了记录头节点的地址,需要再创建一个变量cur用来打印

当cur不为空的时候,不断地打印cur->data的元素,并将cur = cur->next,让cur指向下一个节点,当cur指向NULL时则结束循环

由于NULL空,为了更好的显示,在循环出去以后再单独打印NULL

#include "SList.h"
void SLIstprint(SLTNode* head)//创建打印节点的函数
{
    SLTNode* cur = head;
    while (cur != NULL)
    {
        printf("%d->", cur->data);
        cur = cur->next;
    }
    printf("NULL\n");
}

最后在主函数中将打印函数放进申请结构体函数里面

#include "SList.h"

void TestSList1()//向系统申请足够的空间放下节点并定义节点的元素
{
    SLTNode* n1 = (SLTNode*)malloc(sizeof(SLTNode));
    assert(n1);

    SLTNode* n2 = (SLTNode*)malloc(sizeof(SLTNode));
    assert(n2);

    SLTNode* n3 = (SLTNode*)malloc(sizeof(SLTNode));
    assert(n3);

    SLTNode* n4 = (SLTNode*)malloc(sizeof(SLTNode));
    assert(n4);

    n1->data = 1;
    n2->data = 2;
    n3->data = 3;
    n4->data = 4;

    n1->next = n2;
    n2->next = n3;
    n3->next = n4;
    n4->next = NULL;

    SLIstprint(n1);//调用打印函数,并将n1地址传进去
}

int main() {
    TestSList1();//调用创建节点的函数
    return 0;
}

运行代码

至此,打印成功

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值