当前位置:网站首页>C语言关于链表的代码看不懂?一篇文章让你拿捏二级指针并深入理解函数参数列表中传参的多种形式
C语言关于链表的代码看不懂?一篇文章让你拿捏二级指针并深入理解函数参数列表中传参的多种形式
2022-07-06 18:06:00 【叶落秋白】
作者简介:别人以梦为马,而我要以码为梦。我是叶落秋白,努力学后端中
个人主页:叶落秋白的主页
系列专栏:数据结构干货分享
推荐一款模拟面试、刷题神器进入刷题的世界
前言
这篇博客即将解决你看不懂或者不会写链表的基本操作的问题,对于初学者而言,有很多地方肯定是费解的。比如函数的参数列表的多样化,动态分配内存空间函数malloc等,其实这些知识和指针联系紧密,尤其是二级指针。那么开始好好的学习这篇博客吧!
目录
二级指针讲解
简述:其实就是一个指针指向另一个指针的地址。
我们都知道指针指向地址,但是指针自身也是一个变量,当然也可以被二级指针所指向。
语法:形如 int x = 10; int *q = &x; int **p = & q;
那么这里的q指针指向x的地址,p指针指向指针q的地址,*q可以得到x的值,*p可以得到q指针本身,**p也可以得到x的值。
代码示例:
int main(void)
{
int x = 10;
int* q = &x;
int** p = &q;
printf("x 的地址为: %d\n", &x);
printf("q 指向的地址为:%d\n", q);
printf("*p的值为: %d\n", *p); //p指向指针q的地址,那么*p是解引用操作,
//就等于了q本身
printf("x 的值为: %d\n", x);
printf("q 存取的值为: %d\n", *q);
printf("**p的值为: %d\n", **p); //**p相当于解引用解了两次,第一次先得到q本身,
//第二次得到q指向地址的值
return 0;
}
运行结果:
链表的应用
这里以带头结点的双链表为例
定义双链表的结构体
typedef int ElemType;//将整型数据重命名为int
typedef int Status;//整型重命名为Status
//双链表的数据结构定义
typedef struct DouNode {
ElemType data; //数据域
struct DouNode* head; //前驱指针
struct DouNode* next; //后继指针
}DousList, * LinkList;// 结点指针
代码解释:
利用typedef对数据类型进行重命名,只要在后面遇到的 ElemType和 Status都是整型就够了。双链表结构体包含三个部分:数据域、前驱指针、后继指针,与单链表的区别就是多了一个前驱指针。然后大括号结束部分也是重命名,此时DousList和DouNode效果一样,都是结构体名,然后LinkList是指向结点的指针。
具体使用:
LinkList L,L是一个指针,DousList *P,P也是一个指针,属于两种创建方式。
创建双链表
使用两种正确的创建链表形式和一种错误的形式,对比着记忆创建方法
传入一级指针
这种方式并不能成功创建
代码演示:
void CreateDouList(LinkList L, int n)
{
LinkList ptr;
int i;
L = (LinkList)malloc(sizeof(DousList)); //为头结点申请空间
L->next = NULL;
L->head = NULL;
L->data = n;//L->data记录结点的个数
ptr = L;
for (i = 0; i < n; i++)
{
int value = 0;
scanf("%d",&value);
LinkList me = (LinkList)malloc(sizeof(DouNode));
me->data = value; //节点数据域
me->next = NULL;
me->head = NULL;
ptr->next = me;
me->head = ptr;
ptr = ptr->next; //尾插法建表
}
}
代码解析:
这里的参数列表是 LinkList L 和 整型数据 n,L是传入的链表头结点指针,n是用来记录插入数据的个数的,在下面的for循环用做循环的次数。接下来使用malloc函数为L链表分配内存空间,malloc需要用指针来接收,左边的括号是分配的指针类型,右边的括号是分配的内存空间大小。分配空间完成之后初始化前驱和后继指针为空,数据域data记录数据的个数。ptr指针初始等于L指针,接下来进入n次循环,创建待插入结点指针me并进行分配内存空间和初始化,最后三行代码进行尾插法建立链表:
尾插法:
先让ptr的后继指针指向me,然后me的head指针指向ptr,这就相当于在链表头把me结点插入链表,然后ptr指向这个插入的新结点,这就保证了每次插入的结点都在上一个插入的结点之后。
但是这样真的在链表中插入数据了吗 ,来看看调试结果:
进入遍历的程序时,让创建的ptr指针指向L链表的后继,立马就出现了空指针异常,但是上面明明插入数据了,原因是什么呢? 很明显,这里的链表L并未完成插入数据。这是因为我们在创建链表的函数里传入的只是链表的指针L,那么在函数里这个指针只是一个副本,在这里给他增大内存空间并不会影响到实参链表,这和普通数据类型的值传递和地址传递的情况一致。
我们利用传入指针地址来解决这个问题,两个方法:指针的引用和二级指针
传入指针的引用
函数的实现部分完全不用修改,只要形参列表加上一个引用符"&"即可。
void CreateDouList(LinkList &L, int n);
查看调试结果:
同样的调试方法,传入指针的引用之后可以清晰的看到L的data等于5,也就是存了五个数据,然后对于的后继结点的值都和尾插的结果一致,最后一个结点的后继指针正好指向NULL,完全符合我们的设计的代码。
传入指针的引用之后,函数里链表的空间变化会导致实参里的链表空间变化,这样做才能使插入操作完成,将结点插入到链表内。
传入二级指针
这个和指针的引用原理一样,我主要分享给你们使用的形式
注意调用的时候实参要加“&”符,例:CreateDouList(&L,n);
void CreateDouList(LinkList *L, int n)
{
LinkList ptr;
int i;
*L = (LinkList)malloc(sizeof(DousList)); //为头结点申请空间
(*L)->next = NULL;
(*L)->head = NULL;
(*L)->data = n;//L->data记录结点的个数
ptr = (*L);
printf("开始插入数据:\n");
for (i = 0; i < n; i++)
{
int value = 0;
scanf("%d",&value);
LinkList me = (LinkList)malloc(sizeof(DouNode));
me->data = value; //节点数据域
me->next = NULL;
me->head = NULL;
ptr->next = me;
me->head = ptr;
ptr = ptr->next; //尾插法建表
}
}
这里形参列表的参数是 LinkList *L,和DousLIst **L效果一样,是一个二级指针。如果用到指向链表的指针就需要一次接引用操作,写成(*L)的形式。然后再去分配空间、进行初始化、赋值给链表指针ptr等操作,这样链表二级指针L的改变也会使实参的链表发生改变,可以查看调试结果。
调试结果:
刷题网推荐
数据结构对于小白来说并不是特别友好,好多知识几天不看就会抛之脑后一定要多巩固学到的知识,因此刷题必不可少。在这里我给大家介绍一个我认为对小白比较友好的刷题平台—牛客网
这些都是经典的链表题,多加练习一定可以巩固知识,拿捏个链表还会是问题吗。
希望大家可以充分利用时间,巩固所学,冲击大厂,让我们共同进步!
边栏推荐
- 百度飞将BMN时序动作定位框架 | 数据准备与训练指南 (下)
- Share a general compilation method of so dynamic library
- tansig和logsig的差异,为什么BP喜欢用tansig
- 2022 Google CTF segfault Labyrinth WP
- 安全保护能力是什么意思?等保不同级别保护能力分别是怎样?
- 2022 Google CTF SEGFAULT LABYRINTH wp
- 2022 Google CTF SEGFAULT LABYRINTH wp
- LeetCode. 剑指offer 62. 圆圈中最后剩下的数
- 对C语言数组的再认识
- 拖拽改变顺序
猜你喜欢
AI 从代码中自动生成注释文档
Clickhouse fields are grouped and aggregated, and SQL is queried according to the granularity of any time period
AI automatically generates annotation documents from code
制作带照明的DIY焊接排烟器
454-百度面经1
tansig和logsig的差异,为什么BP喜欢用tansig
新工作感悟~辞旧迎新~
【C语言进阶篇】指针的8道笔试题
Yunna | work order management measures, how to carry out work order management
mongodb查看表是否导入成功
随机推荐
从底层结构开始学习FPGA----FIFO IP的定制与测试
剑指 Offer II 035. 最小时间差-快速排序加数据转换
Telnet,SSH1,SSH2,Telnet/SSL,Rlogin,Serial,TAPI,RAW
设置Wordpress伪静态连接(无宝塔)
Your cache folder contains root-owned files, due to a bug in npm ERR! previous versions of npm which
鼠标右键 自定义
C language instance_ four
Spark TPCDS Data Gen
Google released a security update to fix 0 days that have been used in chrome
AcWing 346. 走廊泼水节 题解(推公式、最小生成树)
Appium基础 — Appium Inspector定位工具(一)
永久的摇篮
Js逆向——捅了【马蜂窝】的ob混淆与加速乐
Instructions for using the domain analysis tool bloodhound
AcWing 1140. 最短网络 (最小生成树)
What does security capability mean? What are the protection capabilities of different levels of ISO?
Transformation transformation operator
Sword finger offer II 035 Minimum time difference - quick sort plus data conversion
Long press the button to execute the function
机器学习:随机梯度下降(SGD)与梯度下降(GD)的区别与代码实现。