9、用指针处理链表问题(何为p=p->next;何为p->next=p?)

其实中间还有一个二维数组指针问题,不过,先放一放吧,把链表这块的问题先理一理。

1.关于链表的几个概念点:

一个单链表的头结点,头指针,(开始结点)首结点,(终端结点)尾结点,尾指针的描述。我觉得这个还是相当重要的一个点的,我开始学的时候就对这个有点迷糊,又是头结点,又是头指针的。但是理解了其中的含义后,对链表的理解又更进一步了,废话不多说

首结点:第一个有效结点,也就是第一个存放有效数据的结点。

尾结点:最后一个有效结点,也就是最后一个存放有效数据的结点。

头结点:位置在首结点之前,不存放有效数据,也不存放整个链表有效结点的个数,为什么要加上一个头结点?因为可以方便对链表进行操作。头结点的数据类型与首结点数据类型一致。

头指针(一般用head表示):指向头结点的指针变量,存放了头结点的地址(注意不是首结点)

尾指针:指向尾结点的指针变量,它的地址部分为NULL。

一般来说,确定一个链表只需要知道头指针一个参数即可。

那什么是链表呢?形象一点来说就是:幼儿园的老师带着孩子出去散步,老师牵着第1个孩子的手,第1个小孩的另一只手牵着第2个小孩.....这就是一个“链”,最后一个孩子有一只手空着,它是就是(终端结点)尾结点。要找到这个队伍,就必须先找到老师,然后顺序找到每一个孩子。

链表指针是C语言的一个难点,但也是重点,学懂了非常有用。要仔细讲就必须先讲变量、指针。
什么是变量?所谓变量,不要浅显的认为会变得量就是变量。套用网上很有意思的一段的问话:“教室变不变?”变,因为每天有不同的人在里面上课,但又不变,因为教室始终在那,没有变大或变小。这就是变量:有一个不变的地址和一块可变的存储空间。正常情况下,我们只看到变量这个房间里面的东西,也就是其内容,但不会关注变量的地址,但是C语言的指针,就是这个房间的地址。我们声明变量就相当于盖了间房子存放东西,我们可以直接观看房子里的东西,而声明指针,就是相当于获得了一个定位器,当用指针指向某个变量时,就是用指针给变量定位,以后我们就可以用指针找到他所“跟踪”的变量并可以获得里面的内容。
那结构体呢?结构体就相当于是有好几个房子组成的别墅,几个房子绑定在一起使用。假设现在有很多这种别墅分布在一个大迷宫里,每间别墅里都有一间房子。里面放了另一个别墅的位置信息,现在你手拿定位器找到了第一栋别墅,从里面得到了你想要的东西(链表的数据部分),然后把下一栋别墅的位置计入你的定位器(p = p->next),再走向下一栋别墅……如此走下去,知道走到某地下一栋别墅信息没有了(p->next == NULL),你的旅行结束。这就是链表一次遍历的过程。

2、个人对链表的一些疑难点:

其实在单链表中,每个指针都设有两个域,一个是数据域,另一个是指针域,其中的指针域是存有下一个结点的地址,指向下一个结点(是指向整个结点,包括指针域,而不是仅仅指向下一个结点的数据域,下图只是为了形象而将箭头指向数据域)

那么问题来了,链表中p=p->next 表达的具体含义是什么呢?在网上查阅了一些资料后,得到以下说法:

->是一个整体,它是用于指向结构体、C++中的class等含有子数据的指针用来取子数据。换种说法,如果我们在C语言中定义了一个结构体,然后申明一个指针指向这个结构体,那么我们要用指针取出结构体中的数据,就要用到“->”.

举个例子:

struct Data
{
    int a,b,c;
};     //定义结构体
struct Data * p;    //定义结构体指针
struct Data A = {1,2,3};    //声明变量A
int x;    //声明一个变量x
p = &A ;     //让p指向A
x = p->a;    //这句话的意思就是取出p所指向的结构体中包含的数据项a赋值给x
/*由于此时p指向A,因而 p->a == A。a,也就是1*/


对于一开始的问题 p = p->next;在C语言的链表中,这里的next应该是一个与p同类型的结构体指针,其定义格式应该是:

struct Data
{
    int a;
    struct Data * next;
};    //定义结构体
…………
main()
{
    struct Data * p;    //声明结构体指针变量p
    ……
    p = p->next;    //将next中的值赋给p
}

所以说,以上面这段代码为例,首先定义了一个结构体数据类型struct Data,在其中定义了数据域值a,和结构体指针变量next,此结构体指针变量next中,存放了下一结点的地址。在主函数main中定义一个数据类型为struct Data指针变量p,所以p->next本质为结构体指针变量p中next的值,抛开链表问题理解,就相当于普通的结构体指针的应用,在前面的结构体数组中有详细记录,这里简单描述,如果p指向一个结构体变量stu,则以下3种用法等价:

  • stu.成员名(如stu.num = 101)
  • (*p).成员名(如(*p).num = 101)
  • p->成员名(如p->num = 101)

所以,在链表中,p则相当于stu,而在p中有一个成员变量为next,p->next形象表达就是:p.next=某个值(这个值为下一结点的地址)。这样就不难理解p=p->next的意思了,就是将next的值(下一结点的地址)赋值给p。这样的结果是什么呢?原本取p结点的下一结点是p->next,现在实际上是取p->next->next了,相当于p节点往后移动;那么同理,p->next=p,此语句将p指针地址赋给p的下一个节点,相当于将 p->next 节点往前移动,本来取p->next节点的下一个节点是 p->next->next ,现在实际上变成取 p->next 了,比如:

假设p的地址为A,p->next的地址为B,p->next->next的地址为C,p->next->next->next的地址为D

p->next(即B)原本的下一个节点是p->next->next(即C)
通过执行语句p=p->next;
p->next的地址就变成了C,p->next->next的地址如果存在的话就是D,不存在即是null.

p->next(即B)原本的下一个节点是p->next->next(即C)
通过执行语句p->next=p;
p->next的地址就变成了A,p->next->next就变成了B.

 只能说这部分要靠自己努力理解了,当初听课时就觉得很容易,可越学到后面,概念就越模糊,以至于后面的增删改算法学的一脸懵逼了,现在遇到这个还是要琢磨一会,争取做到一眼就望穿的那种境界。

  • 144
    点赞
  • 420
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值