线性表存储结构2——链式存储结构
前面我们讲的线性表的顺序存储结构,它是优缺点的,最大的缺点就是插入和删除时候需要移动大量的元素,这显然就需要耗费时间,能不能想办法解决呢?
线性表的链式存储结构的特点是,用一组任意的存储单元存储线性表的数据元素,这组存储单元可以是连续的,也可以是不连续的。这就意味着,这些数据元素可以存在内存未被占用的任意位置。
以前在顺序结构中,每个数据元素只需要存数据元素信息就可以了。
现在在链式结构中,除了要存数据元素信息外,还要存它的后继元素的存储地址。
头指针
我们把链表中第一个结点的存储位置叫做头指针,那么整个链表的存取就必须是从头指针开始进行了。
最后一个,当然意味着直接后继不存在了,所以我们规定,线性表的最后一个结点指针为“空”(通常用NULL或“ ^ ” 符号表示)。
头结点
有时,我们为了更加方便地对链表进行操作,会在单链表地第一个结点前附设一个结点,称为头结点。
头结点地数据域可以不存储任何信息,谁叫它是第一个呢。也可以存储线性表地长度,等附加信息,头结点地指针域指向第一个结点地指针。
头结点与头指针的异同
若线性表为空表,则头结点的指针域为“空”:
带有头结点的单链表:
空链表:
若线性表为空表,则头结点的指针域为“空”。
指针P
假设 P P P是指向线性表第 i i i个元素的指针,则该结点 a i a_i ai的数据域我们可以用 p − > d a t a p->data p−>data来表示, p − > d a t a p->data p−>data的值是一个数据元素,结点 a i a_i ai的指针域可以用 p − > n e x t p->next p−>next来表示, p − > n e x t p->next p−>next的值是一个指针。
单链表的插入
s->next = p->next;
p->next = s;
考虑一下,上面两句的顺序可不可以交换?
对于单链表的表头和表尾的特殊情况,操作是相同的。
单链表的删除
p->next = p->next->next
用 q 来取代 p->next,即:
q = p->next;
p->next = q->next;
单链表整表创建----头插法
单链表整表创建----尾插法
为什么不把新结点都放到最后呢,这才是排队时的正常思维,我们把每次新结点都插在终端结点的后面。
r->next = p ;
意思是,将刚才的表尾终端结点 r 的指针指向新结点 p .
r->next = p ;
r = p ;
r->next = p ;这一句应该还好理解,不太好理解的是后面这一句 r = p ; 是什么意思?
它的意思是,就是本来 r 是指 向
a
i
−
1
a_{i-1}
ai−1这个结点的,可现在它已经不是最后的结点了,现在最后的结点是
a
i
a_i
ai,所以应该要让
p
p
p结点这个最后的结点赋值给
r
r
r。因此,
r
r
r 又是最终的尾结点了。
循环结束后,应该让这个链表的指针域置空,因此有了“ r->next = NULL”