1.(3)数据结构之链表的创建和遍历(有图有注释)

 本人坚持更新C语言,数据结构,操作系统,前端知识,可以收藏+关注随时了解😜😜😜 


目录

1.链表的创建

预备知识

链表创建的过程

2.链表的遍历

3.总程序

4.运行结果


1.链表的创建

预备知识

在创建链表之前我们需要了解链表的一些知识

1.链表中的节点由数据域和指针域组成,所以我们在定义链表的节点的时候,需要定义多种数据类型,因此需要使用结构体来定义链表的结点

2.链表的结点中的指针域都存放着下一个节点的地址,链表就是靠这些指针连接在一起

3.确定一个链表我们只需要直到他的头结点就可以,然后通过头结点的指针域向后一一寻找,得到整条链表

4.链表的头节点不存放有效数据,只有指针域,尾结点的指针域为空(NULL),NULL的含义在之前的文章中有提过

5.链表的结点我们需要动态的创建,也就是动态的分配内存

60148e519e944e2c8bda4c4c950b831e.png

链表创建的过程

链表的创建有头插法和尾插法两种,本文介绍的是尾插法


//定义结构体
typedef struct Node
{
    int data;           //数据域
    struct Node *pNext; //指针域
} NODE, *PNODE;         // NODE等于struct Node,PNODE等价于struct Node*

//创建链表(尾插法)
PNODE CreateList()
{
    int len;                                   //有效节点的个数
    int val;                                   //临时存储节点数据域的值
    PNODE pHead = (PNODE)malloc(sizeof(NODE)); //分配一个不存放有效数据的的头节点
    if (NULL == pHead)                         //内存分配失败
    {
        printf("fail to distribute memory,the procedure is over!\n");
        exit(-1);
    }
    //定义一个指针变量,为结构体指针,注意,这个只是一个指针,而不是一个节点,节点需要动态的内存分配
    PNODE pTail = pHead; //若是空链表,头节点和尾节点一样
    pTail->pNext = NULL; // 此时pTail和pHead都指向了头节点,先让头节点的指针域为NULL
    printf("please input the number of linkList:\n");
    cin >> len;
    for (int i = 0; i < len; i++)
    {
        printf("please input NO.%d node's value:\n", i + 1);
        scanf("%d", &val);

        PNODE pNew = (PNODE)malloc(sizeof(NODE)); //为新节点动态分配内存
        if (NULL == pNew)
        {
            printf("fail to distribute memory,the procedure is over!\n");
            exit(-1);
        }
        pNew->data = val;    //为新节点赋值
        pTail->pNext = pNew; //将新节点的地址放在头节点的指针域中,此时头节点指向这个节点
        pNew->pNext = NULL;  //设置尾结点的指针域为NULL
        pTail = pNew;        //尾指针后移
    }
    return pHead;
}

创建过程如下:

1.首先我们定义了节点的结构体struct Node

2.接着定义头节点pHead,通过这个pHead,我们就可以确定整条链表,所以这个pHead的地址很重要,我们要将它返回。

496f5ae241a247d388fc51d33966cbdc.png

 3.接着我们定义一个尾指针pTail也指向这个头节点,注意,这里尾指针只是一个结构体指针,不需要动态内存分配,此时,头结点的指针域为空。

尾插法的思想就是让尾指针一直指向最后一个元素

b3fabb755b974d1d8f9e0ff8c3cbc719.png

4.然后我们动态的创建结点

 PNODE pNew = (PNODE)malloc(sizeof(NODE)); //为新节点动态分配内存

b889d1fa0cbc4d57b636c3780e9b8fec.png

5.将新节点接入链表

        pNew->data = val;    //为新节点赋值

        pTail->pNext = pNew; //将新节点的地址放在头节点的指针域中,此时头节点指向这个节点

        pNew->pNext = NULL;  //设置尾结点的指针域为NULL

        pTail = pNew;        //尾指针后移

feb8e9da7e774b4da79720f523c111e7.png

6.循环步骤5,最后返回头结点的地址

return pHead;

2.链表的遍历

 我们已经知道,确定整个链表只需要知道它的头节点。所以遍历链表我们需要传递一个参数,就是头节点的地址

遍历思想:采用while循环,先定义一个指针变量指向pHead结点,

6e6d8a873118476db956b711c6b90eba.png

只要p的指针域不为NULL,我们就将指针p后移,每次后移,我们都通过p->data来读取数据

直到p的指针域为NULL时,我们就停止循环

void traverse_list(PNODE pHead) //只需要头结点的地址就可以找到整个链表
{
    int i = 1;               //计数
    PNODE p = pHead;         //定义一个静态指针变量p指向头节点
    while (p->pNext != NULL) //循环遍历链表,直到遍历到最后一个节点,最后一个节点的指针域为NULL
    {
        p = p->pNext;  //先后移,因为pHead不存放有效数据                                   // p指针后移
        cout << "the NO." << i << "=" << p->data << endl; //输出链表的值
        i++;
    }
}

3.总程序

#include <iostream>
#include <malloc.h>
#include <stdio.h>
using namespace std;
//定义结构体
typedef struct Node
{
    int data;           //数据域
    struct Node *pNext; //指针域
} NODE, *PNODE;         // NODE等于struct Node,PNODE等价于struct Node*
//声明函数
PNODE CreateList();
void traverse_list(PNODE pHead);
//主函数
int main(int argc, char const *argv[])
{
    struct Node *pHead = NULL; // pHead用来存放链表头结点的地址
    pHead = CreateList();      //创建一个非循环的单链表,并将该链表的头指针返回
    traverse_list(pHead);
    return 0;
}

//创建链表(尾插法)
PNODE CreateList()
{
    int len;                                   //有效节点的个数
    int val;                                   //临时存储节点数据域的值
    PNODE pHead = (PNODE)malloc(sizeof(NODE)); //分配一个不存放有效数据的的头节点
    if (NULL == pHead)                         //内存分配失败
    {
        printf("fail to distribute memory,the procedure is over!\n");
        exit(-1);
    }
    //定义一个指针变量,为结构体指针,注意,这个只是一个指针,而不是一个节点,节点需要动态的内存分配
    PNODE pTail = pHead; //若是空链表,头节点和尾节点一样
    pTail->pNext = NULL; // 此时pTail和pHead都指向了头节点,先让头节点的指针域为NULL
    printf("please input the number of linkList:\n");
    cin >> len;
    for (int i = 0; i < len; i++)
    {
        printf("please input NO.%d node's value:\n", i + 1);
        scanf("%d", &val);

        PNODE pNew = (PNODE)malloc(sizeof(NODE)); //为新节点动态分配内存
        if (NULL == pNew)
        {
            printf("fail to distribute memory,the procedure is over!\n");
            exit(-1);
        }
        pNew->data = val;    //为新节点赋值
        pTail->pNext = pNew; //将新节点的地址放在头节点的指针域中,此时头节点指向这个节点
        pNew->pNext = NULL;  //设置尾结点的指针域为NULL
        pTail = pNew;        //尾指针后移
    }
    return pHead;
}
// 遍历链表
void traverse_list(PNODE pHead) //只需要头结点的地址就可以找到整个链表
{
    int i = 1;               //计数
    PNODE p = pHead;         //定义一个静态指针变量p指向头节点
    while (p->pNext != NULL) //循环遍历链表,直到遍历到最后一个节点,最后一个节点的指针域为NULL
    {
        p = p->pNext;  //先后移,因为pHead不存放有效数据                                   // p指针后移
        cout << "the NO." << i << "=" << p->data << endl; //输出链表的值
        i++;
    }
}

4.运行结果

5e2fee06eb1f4ea1b31bab801fb3981f.png

  • 32
    点赞
  • 67
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 41
    评论
评论 41
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

爱打羽毛球的程序员

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

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

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

打赏作者

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

抵扣说明:

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

余额充值