1.设计一个递归算法,删除不带头结点的单链表L中的所有值为x的结点。
解:设f(L,x)的功能是删除以L为首结点指针的单链表中所有值等于x的结点,显然f(L->next,x)的功能是删除以L->next为首结点指针的单链表中所有值等于x的结点。由此,可以推出递归模型如下。
终止条件:f(L,x)≡不做任何事情; 若L为空表
递归主体:f(L,x)≡删除*L结点;f(L->next,x); 若L->data == x
f(L,x)≡f(L->next,x); 其他情况
下面展示一些 代码
。
void Del_X3(Linklist &L,ElemType x){
//递归实现在单链表L中删除值为X的结点
LNode *p;
if(L == NULL)
return ;
if(L->data == x){
p=L;
L=L->next;
free(p);
Del_X_3(L,x); //递归调用
}
else //若L所指结点的值不为x
Del_X_3(L->next, x); //递归调用
2.某线性表用带表头结点的循环单链表存储,头指针为head,当head->next->next=head成立时,线性表长度可能是(0或1
)
解析:对一个空循环单链表,有head->next == head,推理head->next->next==head->next ==head.对含有1个元素的循环单链表,头结点的next域指向该唯一元素结点,该元素结点的next域指向头结点,因此也有head->next->next=head.
3.设L为带头结点的单链表,编写算法实现从尾到头反向输出每个结点的值。
解析:从头到尾输出比较简单。求解本题,可以先将链表逆置,改变链表方向,然后从头到尾实现反向输出。
也可以用栈,访问到一个结点就把这个结点放入栈,最后从栈顶输出。
下面我用递归方法,每访问一个结点时,先递归输出它后面的结点,再输出该结点本身。
下面展示一些 代码
。
void R_Print(LinkList L){
//从尾到头输出单链表L中的每个结点值
if(L->next!=NULL){
R_Print(L->next); //递归
}
if(L!=NULL)
print(L->data); //输出
}
4.一个链表最常用的操作是在最后一个元素之后插入一个元素和删除第一个元素,则选用(c
)最节省时间。
A.不带头结点的单循环链表
B.双链表
C.不带头结点且有尾指针的单循环链表
D.单链表
解析:对于A,在最后一个元素之后插入元素的情况和普通单链表相同,时间复杂度为O(n);而删除表中第一个元素时,为保持单循环链表的性质(尾结点的指针指向第一个结点),需要先遍历整个链表找到尾结点,再做删除操作,时间复杂度为O(n).对于B,双链表的情况与单链表的相同,一个是O(n),一个是O(1).对于C,与A的分析对比,有尾结点的指针,省去了遍历链表的过程,因此时间复杂度均为O(1).对于D,要在最后一个元素之后插入一个新元素,需要遍历整个链表才能找到插入位置,时间复杂度为O(n);删除第一个元素的时间复杂度为O(1)。