你的考试笔记之数据结构——四、关于线性表的几个key points
精简到只有考试会用到的知识
1.表的逆置
(1)表的部分逆置
①解法一:将头结点摘下,然后从第一个结点开始,依次插入到头结点的后面(头插法建立单链表),直到最后一个结点为止,这样就实现了链表的逆置
假设有线性表L,L由两部分a和b组成,即L=ab,将其逆置,成为L=ba。
由线性代数知识,从部分到整体,我们可以得到两种方法:
ab →a-1b →a-1b-1 →(a-1b-1)-1→ba
ab→(ab)-1 →b-1a-1→ba-1→ba
主要是实现单链表的逆置,下面是实现代码:
LinkList Reverse_1(LinkList ){ /*L是带头结点的单链表,本算法将L就地逆置*/
{
LNode *p, *r; //p为工作指针,r为p的后继,以防断链
p=L->next; //从第一个元素结点开始
L->next=NULL; //先将头结点L的next域置为NULL
while(p!=NULL) //依次将元素结点摘下
{
r=p->next; //暂存p的后继
p->next=L->next; //将p结点插入到头结点之后
L->next-p;
p=r;
}
return L;
}
②解法二:假设pre、p和r指向3个相邻的结点,如下图所示,经过若干操作后,*pre之前的结点的指针都已调整完毕,它们的 next都指向其原前驱结点,就完成了逆置。
现在令*p 结点的next域指向*pre结点,注意到一旦调整指针的指向,*p 的后继结点的链就会断开,为此需要用r来指向原*p的后继结点。处理时需要注意两点:一是在处理第一个结点时,应将其next域置为NULL,而不是指向头结点(因为它将作为新表的尾结点);二是在处理完最后一个结点后,需要将头结点的指针指向它。
LinkList Reverse_2 (LinkList L) //依次遍历线性表L,并将结点指针反转
{
LNode *pre,*p=L->next, *r=p->next;
p->next=NULL; //处理第一个结点
while (r!=NULL)
{ //r为空,则说明p为最后一个结点
pre=p; //依次继续遍历
p=r;
r=r->next;
p->next=pre; //指针反转
}
L->next=p; //处理最后一个结点
return L;
}
上述两个算法的时间复杂度为O(n),空间复杂度为O(1)。
2.找单链表的中间结点或倒数第K个结点
(1)找链表的中间结点
设指针p和q都指向链表L的头结点,指针p每次走一步(指向p->next),指针q每次走两步,循环下去直到q指针指向链表末尾(q->next=null),此时p指针所指结点为链表中间结点。
部分代码如下:
p=q=L;
while(q->next!=null)
{
p=p->next;
q=q->next;
if(q->next!=null)
q=q->next;
}
(2)找链表倒数第K个结点
设指针p和q都指向链表L的第一个结点,count=0计数,指针p先移动,每次走一步(指向p->next)当指针p移动到第K个结点,q指针与指针q同时向后移动,循环下去直到q指针指向链表末尾(q->next=null),此时p指针所指结点为链表找链表倒数第K个结点。
count=0;
p=q=L->next;
while(p!=null)
{
if(count<k)
count++;
else q=q->next;
p=p->next;
}
3.空链表判定
(1)对头指针为head的带头结点单链表,判定该表为空的条件是head->next== null;
(2)不带头结点单链表,判定该表为空的条件是head== null;
(3)带头结点双循环链表L,判定该表为空的条件是L->piror== L&&L->next ==L;
先写这些吧后续会补充其他重要点