一、选择题
1. D
2. B
3. B
4. B
5. B
6. B
7. D
8. B
9. C
10. B
11. C
12. C
13. B
14. D
15. A
16. B
17. B
18. C
19. A
20. C
21. D
22. A
23. A
24. A
二、填空题
1. 首元素其直接前驱结点的链域的值
2. HL→next =NULL; HL=HL→next
3. 有限、一对一
4. O(1) 随机存取
5. 表中一半表长和该元素在表中的位置
6. 必定不一定
7. O(1) O(n)
8. 前驱结点的地址 O(n)
9. n-i+1 n-i
10. s->left=p p->right
三、判断题
1. ×
2. ×
3. ×
4. ×
5. ×
6. ×
7. √
8. ×
9. ×
10. ×
11. ×
四、简答题
1. 线性表为:(78,50,40,60,34,90)
2. (36, 12, 8, 50, 25, 5, 15)
3. 解答:
尾指针是指向终端结点的指针,用它来表示单循环链表可以使得查找链表的开始结点和终端结点都很方便,设一带头结点的单循环链表,其尾指针为rear,则开始结点和终端结点的位置分别是rear->next->next和rear, 查找时间都是O(1)。
若用头指针来表示该链表,则查找终端结点的时间为O(n)。
五、编程题
1. 解答:由于在单链表中只给出一个头指针,所以只能用遍历的方法来数单链表中的结点个数了。算法如下:
int ListLength ( LinkList L )
{
int len=0 ;
ListNode *p;
p=L; //设该表有头结点
while ( p->next )
{
p=p->next;
len++;
}
return len;
}
2. int searchmin(linklist l)
{
int min;
int *p;
p=l;
min=p->data;
p=p->next;
while (p->next< >nil)
{
if (min>p->data) min=p->data;
p=p->next;
}
return min;
}
3. int searchmax(linklist l)
{ int max;
int *p;
p=l;
max=p->data;
p=p->next;
while (p->next< >nil)
{
if (max
p=p->next;
}
return max;
}
4. 顺序表:要将该表逆置,可以将表中的开始结点与终端结点互换,第二个结点与倒数第二个结点互换,如此反复,就可将整个表逆置了。
算法如下:
// 顺序表结构定义同上题
void ReverseList( Seqlist *L)
{
DataType temp ; //设置临时空间用于存放data
int i;
for (i=0;i<=L->length/2;i++)//L->length/2为整除运算
{ temp = L->data[i]; //交换数据
L -> data[ i ] = L -> data[ L -> length-1-i];
L -> data[ L -> length - 1 - i ] = temp;
}
}
5. int CountX(LNode* HL,ElemType x)
{ int i=0; LNode* p=HL;//i为计数器
while(p!=NULL)
{ if (P->data==x) i++;
p=p->next;
}//while, 出循环时i中的值即为x结点个数
return i;
}//CountX
6. 解答:因已知顺序表L是递增有序表,所以只要从顺序表终端结点(设为i位置元素)开始向前寻找到第一个小于或等于x的元素位置i后插入该位置即可。
在寻找过程中,由于大于x的元素都应放在x之后,所以可边寻找,边后移元素,当找到第一个小于或等于x的元素位置i时,该位置也空出来了。
算法如下:
//顺序表存储结构如题7
void InsertIncreaseList( Seqlist *L , Datatype x )
{
int i;
if(L->length>=ListSize)
Error("overflow");
for(i=L->length;i>0 && L->data[i-1]>x;i--)
L->data[i]=L->data[i]; // 比较并移动元素
L->data[i] =x;
L->length++;
}
7. void mergelklist(lklist *ha,lklist *hb,lklist *&hc)
{
lklist *s=hc=0;
while(ha!=0 && hb!=0)
if(ha->data
else {if(s==0) hc=s=hb; else {s->next=hb; s=hb;};hb=hb->next;}
if(ha==0) s->next=hb; else s->next=ha;
}
8. 解答:由于要进行的是两单链表的连接,所以应找到放在前面的那张表的表尾结点,再将后表的开始结点链接到前表的终端结点后即可。该算法的主要时间消耗是用在寻找第一张表的终端尾结点上。这两张单链表的连接顺序无要求,并且已知两表的表长,则为了提高算法效率,可选表长小的单链表在前的方式连接。
具体算法如下:
LinkList Link( LinkList L1 , LinkList L2,int m,int n )
{//将两个单链表连接在一起
ListNode *p , *q, *s ;
//s指向短表的头结点,q指向长表的开始结点,回收长表头结点空间
if(m<=n)
{s=L1;q=L2->next;free(L2);}
else
{s=L2;q=L1->next;free(L1);}
p=s;
while(p->next)p=p->next; //查找短表终端结点
p->next = q; //将长表的开始结点链接在短表终端结点后
return s;
}
本算法的主要操作时间花费在查找短表的终端结点上,所以本算的法时间复杂度为:O(min(m,n))
9. typedef int datatype;
typedef struct node {datatype data; struct node *next;}lklist;
void delredundant(lklist *&head)
{
lklist *p,*q,*s;
for(p=head;p!=0;p=p->next)
{
for(q=p->next,s=q;q!=0; )
if (q->data==p->data) {s->next=q->next; free(q);q=s->next;} else {s=q,q=q->next;}
}
}