本人坚持更新C语言,数据结构,操作系统,前端知识,可以收藏+关注随时了解😜😜😜
目录
1.链表的创建
预备知识
在创建链表之前我们需要了解链表的一些知识
1.链表中的节点由数据域和指针域组成,所以我们在定义链表的节点的时候,需要定义多种数据类型,因此需要使用结构体来定义链表的结点
2.链表的结点中的指针域都存放着下一个节点的地址,链表就是靠这些指针连接在一起
3.确定一个链表我们只需要直到他的头结点就可以,然后通过头结点的指针域向后一一寻找,得到整条链表
4.链表的头节点不存放有效数据,只有指针域,尾结点的指针域为空(NULL),NULL的含义在之前的文章中有提过
5.链表的结点我们需要动态的创建,也就是动态的分配内存
链表创建的过程
链表的创建有头插法和尾插法两种,本文介绍的是尾插法
//定义结构体
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的地址很重要,我们要将它返回。
3.接着我们定义一个尾指针pTail也指向这个头节点,注意,这里尾指针只是一个结构体指针,不需要动态内存分配,此时,头结点的指针域为空。
尾插法的思想就是让尾指针一直指向最后一个元素
4.然后我们动态的创建结点
PNODE pNew = (PNODE)malloc(sizeof(NODE)); //为新节点动态分配内存
5.将新节点接入链表
pNew->data = val; //为新节点赋值
pTail->pNext = pNew; //将新节点的地址放在头节点的指针域中,此时头节点指向这个节点
pNew->pNext = NULL; //设置尾结点的指针域为NULL
pTail = pNew; //尾指针后移
6.循环步骤5,最后返回头结点的地址
return pHead;
2.链表的遍历
我们已经知道,确定整个链表只需要知道它的头节点。所以遍历链表我们需要传递一个参数,就是头节点的地址
遍历思想:采用while循环,先定义一个指针变量指向pHead结点,
只要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++;
}
}