【非空单循环链表】是链式存储结构的其中一种,下面是各个词汇的意思:
-
先说【单】的意思:
- 这里指的是【单循环】的,另外在别的地方你会碰到一些不一样的循环链表,比如说是【多重链】的。
-
单循环
-
【单循环链表】常在表的首尾位置上进行操作,用【尾指针rear】、【开始结点a1】、【终端结点an】分别表示,查找时间为O(1)。
-
将【终端结点的指针域NULL】指向【表头结点】或【开始结点】,这就是单循环
-
从任一结点出发都可访问到表中所有结点
-
【单链表】从一已知结点出发,只能访问到该结点及其后续结点,无法找到该结点之前的其它结点。
-
【单循环链表】则从任一结点出发都可以访问到表中的所有结点
-
-
-
多重链
-
将【表中结点】链接在多个环上,这样就形成了多重链
-
-
- 这里指的是【单循环】的,另外在别的地方你会碰到一些不一样的循环链表,比如说是【多重链】的。
-
再说【循环链表】的意思:
-
在这个表中的【最后一个结点的指针域】指向【头结点】,使它整个链表成为一个循环链表
-
循环链表中没有NULL指针。
-
涉及遍历操作时,其终止条件就不再是像【非循环链表】那样判别p或p->next是否为空,而是判别它们是否等于某一指定指针,如头指针或尾指针等。
-
-
-
最后说【非空】的意思:
-
要求【单循环链表】为非空,如果是空的,那么就不存在上面刚讲到的【尾指针rear】、【开始结点a1】、【终端结点an】这些。
-
比如,已知头指针h指向一个带头结点的非空单循环链表,结点结构为,其中next是指向直接后继结点的指针,p是尾指针,q为临时指针。现要删除该链表的第一个元素,正确的语句序列是( )
A.h->next=h->next->next;
q=h->next;
free(q);
B.q=h->next;
h->next=h->next->next;
free(q);
C.q=h->next;
h->next=q->next;
if(p!=q)p=h;
free(q);
D.q=h->next;
h->next=q->next;
if(p==q)p=h;
free(q);
首先,我们可以看到的信息是,这个非空单循环链表的结点结构为 ,而其中的next是指向【直接后继结点】的指针,那么我介绍一下自己的思路,如下:
我喜欢把指针画为这样的符号:,(可在三角形内写上相应的指针名),故这里讲到的这个结点结构,也可以按我的思路画为这样:
所以,一般来说,有讲到【头结点】的,就可以把data写为:
这里写的头就是指【头结点】。
有讲到【尾结点】的,就可以把data写为:
这里写的尾就是指【尾结点】。
所以,题目说将【头指针h】指向一个【带头结点的非空单循环链表】,可以画为:
从图中可以看出,next都是直接指向【下一个结点,也称为后继结点】的指针,h是头指针,p是尾指针,那么我们现在要删除该链表的第一个元素,我理解为把【头结点】给删掉,那么就是把直接指到【下一个结点】去,也就是我们最后的目的如下:
当然,现在我们还不能这样,因为【头指针h】是要指向头结点,在头结点删除之前,
的位置不能变,所以我们可以使用【临时指针q】,即
,让
先代替
指到最后要指的位置上,如下:
【箭头指向的位置】就是h->next的意思
【箭头指向的位置】就是q->next的意思
【箭头指向的位置】就是p->next的意思
在我画的符号的三角形中,h就是头指针h的位置,q就是临时指针q的位置,p就是尾指针p的位置
故我们需执行q=h->next,先将【箭头指向的位置】确定为临时指针q的位置。
换种理解,执行q=h->next的目的是:让【临时指针q】获得新的指针引用(即【头指针h】的指针引用)
接着程序员执行h->next=q->next,这样将【箭头指向的位置,也就是新的头结点位置】 赋给【
箭头指向的位置】,【头指针h】也就找到了新的头结点的位置,并指向那个位置。
因为刚才我们执行了q=h->next,所以,
h->next=q->next当然也可以写成 h->next=h->next->next
程序员还会防范这个非空单循环链表可能出现的该表只有一种元素的情况,即头结点和尾结点是同一个,p==q
那么这时,尾指针p也是指向这个结点,临时指针q也是指向这个结点,即:
程序员就会在这里执行一步, 即if(p==q)p=h; 也就是如果头结点和尾结点是同一个,则将【头指针h的位置】直接作为【尾指针p的位置】
而后程序员再执行free(q), 临时指针q这时没用了,因为全部上下只剩这一个元素了嘛,如果再删掉这个元素,这个表就不是非空的了,就不是【非空单循环链表】了,故这个时候就可以将临时指针q给释放掉了。
那这里为什么要p=h,使【尾指针p的位置】与【头指针h的位置】保持一致呢?因为我们要将该表形成一个循环啊!这是一个【非空单循环链表】!!
所以总结来说,我们就是得这么执行:
- q=h->next;
- h->next=q->next;
- if(p==q)p=h;
- free(q);