c[i][j]=a[i][k]*b[k][j]
}
3.O(n
)
4.i=n-1;
while((i>=0)&&A[i]!
=k))
j--;
return(i);
4.O(n)
5.fact(n)
{if(n<=1)
return
(1);
else
return(n*fact(n-1));
}
5.O(n)
第2章线性表
【例2-1】试编写出将两个顺序存储的有序表A和B合成一个有序表C的算法。
解:
假设A、B和C的类型为下述SqList类型:
#definemaxlen1000
typedefintelemtype
typedefstruct
{elemtypeelem[maxlen];
intlen;
}SqList;
设A和B的数据元素均为整数且为升序排列,设A的长度为m,B的长度为n,则合并后C的长度为m+n。
合并时进行A、B元素的比较,将较小的链入C中,算法描述如下:
intmerge(SqList*A,SqList*B,SqList*C)//将两个有序表A和B合成一个有序表C
{intm,n,i,j,k;
m=(*A).len;n=(*B).len;
if(m+n>maxlen-1)
{printf("overflow");
exit(0);
}
i=0;j=0;//i和j分别作为扫描顺序表A和B的指针
k=0;//k指示顺序表C中当前位置
while((i<=m)&&(j<=n))
if((*A).elem[i]<=(*B).elem[j])
{(*C).elem[k]=(*A)elem[i];
i++;k++;
}
else
{(*C).elem[k]=(*B)elem[j];
j++;k++;
}
while(i<=m)//表B已结束,表A没有结束,链入表A的剩余部分
{(*C).elem[k]=(*A).elem[i];
i++;k++;
}
while(j<=m)//表A已结束,表B没有结束,链入表B的剩余部分
{(*C).elem[k]=(*B).elem[j];
i++;k++;
}
return
(1);
}
【例2-2】写一算法实现单链表的逆置。
解:
假设单链表的表头指针用head表示,其类型为下面定义的LinkList,并且单链表不带头结点。
逆置后原来的最后一个结点成为第一个结点,于是从第一个结点开始逐个修改每个结点的指针域进行逆置,且刚被逆置的结点总是新链表的第一个结点,故令head指向它(如图2-1所示)。
typedefstructNode
{elemtypedata;
structNode*next;
}LinkList;
具体算法描述如下:
(b)第三个结点逆置
示示
图
voidcontray(LinkList*head)
{//将head单链表中所有结点按相反次序链接
LinkList*p,*q;
p=head;//p指向未被逆序的第一个结点,初始时指向原表头结点
head=NULL;
while(p!
=NULL)
{q=p;//q指向将被逆序链接的结点
p=p->next;
q->next=head;
head=q;
}
}
【例2-3】假设有一个循环链表的长度大于1,且表中既无头结点也无头指针,已知p为指向链表中某结点的指针,设计在链表中删除p所指结点的前趋结点的算法。
解:
可引入一个指针q,当q->next=p时,说明此时q所指的结点为p所指结点的前趋结点,从而可得算法如下:
voiddelete(LinkList*p)
{//在链表中删除p所指结点的前趋结点
LinkList*q,*t;
q=p;
while(q->next->next!
=p)//q->next不是p的前趋结点
q=q->next;
t=q->next;//t指向要删除结点
q->next=p;//删除t结点
free(t);
}
【例2-4】试设计实现删除单链表中值相同的多余结点的算法。
解:
该例可以这样考虑,先取开始结点的值,将它与其后的所有结点值一一比较,发现相同的就删除掉,然后再取第二结点的值,重复上述过程直到最后一个结点。
设单链表(其类型为LinkList)的头指针head指向头结点,则可按下列步骤执行:
首先,用一个指针p指向单链表中第一个表结点,然后用另一个指针q查找链表中其余结点元素,由于是单链表,故结束条件为p==NULL,同时让指针s指向q所指结点的前趋结点,当查找到结点具有q->data==p->data时删除q所指的结点,然后再修改q,直到q为空;然后使p指针后移(即p=p->next),重复进行,直到p为空时为止。
算法描述如下:
del(LinkList*head)
{//删除单链表中值相同的多余结点
LinkList*p,*s,*q;
p=head->next;
while(p!
=NULL&&p->next!
=NULL)
{s=p;//s指向要删除结点的前趋
q=p->next;
while(q!
=NULL)
{if(q->data==p->data)}//查找值相同的结点并删除
{s->next=q->next;
free(q);
q=s->next;
}
else
{s=q;
q=q->next;
}
}
p=p->next;
}
}
习题2
一、单项选择题
1.线性表是________。
1.A
A.一个有限序列,可以为空B.一个有限序列,不可以为空
C.一个无限序列,可以为空D.一个无限序列,不可以为空
2.在一个长度为n的顺序表中删除第i个元素(0<=i<=n)时,需向前移动个元素。
2.A
A.n-iB.n-i+lC.n-i-1D.i
3.线性表采用链式存储时,其地址________。
3.D
A.必须是连续的B.一定是不连续的
C.部分地址必须是连续的D.连续与否均可以
4.从一个具有n个结点的单链表中查找其值等于x的结点时,在查找成功的情况下,需平均比较________个元素结点。
4.C
A.n/2B.nC.(n+1)/2D.(n-1)/2
5.在双向循环链表中,在p所指的结点之后插入s指针所指的结点,其操作是____。
5.D
A.p->next=s;s->prior=p;
p->next->prior=s;s->next=p->next;
B.s->prior=p;s->next=p->next;
p->next=s;p->next->prior=s;
C.p->next=s;p->next->prior=s;
s->prior=p;s->next=p->next;
D.s->prior=p;s->next=p->next;
p->next->prior=s;p->next=s;
6.设单链表中指针p指向结点m,若要删除m之后的结点(若存在),则需修改指针的操作为________。
6.A
A.p->next=p->next->next;B.p=p->next;
C.p=p->next->next;D.p->next=p;
7.在一个长度为n的顺序表中向第i个元素(0
7.B
A.n-iB.n-i+lC.n-i-1D.i
8.在一个单链表中,已知q结点是p结点的前趋结点,若在q和p之间插入s结点,则须执行8.B
A.s->next=p->next;p->next=s
B.q->next=s;s->next=p
C.p->next=s->next;s->next=p
D.p->next=s;s->next=q
9.以下关于线性表的说法不正确的是______。
9.C
A.线性表中的数据元素可以是数字、字符、记录等不同类型。
B.线性表中包含的数据元素个数不是任意的。
C.线性表中的每个结点都有且只有一个直接前趋和直接后继。
D.存在这样的线性表:
表中各结点都没有直接前趋和直接后继。
10.线性表的顺序存储结构是一种_______的存储结构。
10.A
A.随机存取B.顺序存取C.索引存取D.散列存取
11.在顺序表中,只要知道_______,就可在相同时间内求出任一结点的存储地址。
11.D
A.基地址B.结点大小
C.向量大小D.基地址和结点大小
12.在等概率情况下,顺序表的插入操作要移动______结点。
12.B
A.全部B.一半
C.三分之一 D.四分之一
13.在______运算中,使用顺序表比链表好。
13.C
A.插入 B.删除
C.根据序号查找 D.根据元素值查找
14.在一个具有n个结点的有序单链表中插入一个新结点并保持该表有序的时间复杂度是_______。
14.B
A.O
(1) B.O(n)
C.O(n2)D.O(log2n)
15.设有一个栈,元素的进栈次序为A,B,C,D,E,下列是不可能的出栈序列__________。
15.C
A.A,B,C,D,EB.B,C,D,E,A
C.E,A,B,C,DD.E,D,C,B,A
16.在一个具有n个单元的顺序栈中,假定以地址低端(即0单元)作为栈底,以top作为栈顶指针,当做出栈处理时,top变化为______。
16.C
A.top不变B.top=0C.top--D.top++
17.向一个栈顶指针为hs的链栈中插入一个s结点时,应执行______。
17.B
A.hs->next=s;
B.s->next=hs;hs=s;
C.s->next=hs->next;hs->next=s;
D.s->next=hs;hs=hs->next;
18.在具有n个单元的顺序存储的循环队列中,假定front和rear分别为队头指针和队尾指针,则判断队满的条件为________。
18.D
A.rear%n==frontB.(front+l)%n==rear
C.rear%n-1==frontD.(rear+l)%n==front
19.在具有n个单元的顺序存储的循环队列中,假定front和rear分别为队头指针和队尾指针,则判断队空的条件为________。
19.C
A.rear%n==frontB.front+l=rear
C.rear==frontD.(rear+l)%n=front
20.在一个链队列中,假定front和rear分别为队首和队尾指针,则删除一个结点的操作为________。
20.A
A.front=front->next B.rear=rear->next
C.rear=front->next D.front=rear->next
二、填空题
1.线性表是一种典型的_________结构。
1.线性
2.在一个长度为n的顺序表的第i个元素之前插入一个元素,需要后移____个元素。
2.n-i+1
3.顺序表中逻辑上相邻的元素的物理位置________。
3.相邻
4.要从一个顺序表删除一个元素时,被删除元素之后的所有元素均需_______一个位置,移动过程是从_______向_______依次移动每一个元素。
4.前移,前,后
5.在线性表的顺序存储中,元素之间的逻辑关系是通过_______决定的;在线性表的链接存储中,元素之间的逻辑关系是通过_______决定的。
5.物理存储位置,链域的指针值
6.在双向链表中,每个结点含有两个指针域,一个指向_______结点,另一个指向_______结点。
6.前趋,后继
7.当对一个线性表经常进行存取操作,而很少进行插入和删除操作时,则采用_______存储结构为宜。
相反,当经常进行的是插入和删除操作时,则采用_______存储结构为宜。
7.顺序,链接
8.顺序表中逻辑上相邻的元素,物理位置_______相邻,单链表中逻辑上相邻的元素,物理位置_______相邻。
8.一定,不一定
9.线性表、栈和队列都是_______结构,可以在线性表的______位置插入和删除元素;对于栈只能在_______位置插入和删除元素;对于队列只能在_______位置插入元素和在_______位置删除元素。
9.线性,任何,栈顶,队尾,队头
10.根据线性表的链式存储结构中每个结点所含指针的个数,链表可分为_________和_______;而根据指针的联接方式,链表又可分为________和_________10.单链表,双链表,非循环链表,循环链表
11.在单链表中设置头结点的作用是________。
11.使空表和非空表统一;算法处理一致
12.对于一个具有n个结点的单链表,在已知的结点p后插入一个新结点的时间复杂度为______,在给定值为x的结点后插入一个新结点的时间复杂度为_______。
12.O
(1),O(n)
13.对于一个栈作进栈运算时,应先判别栈是否为_______,作退栈运算时,应先判别栈是否为_______,当栈中元素为m时,作进栈运算时发生上溢,则说明栈的可用最大容量为_______。
为了增加内存空间的利用率和减少发生上溢的可能性,由两个栈共享一片连续的内存空间时,应将两栈的_______分别设在这片内存空间的两端,这样只有当_______时才产生上溢。
13.栈满,栈空,m,栈底,两个栈的栈顶在栈空间的某一位置相遇
14.设有一空栈,现有输入序列1,2,3,4,5,经过push,push,pop,push,pop,push,push后,输出序列是_________。
14.2、3
15.无论对于顺序存储还是链式存储的栈和队列来说,进行插入或删除运算的时间复杂度均相同为__________。
15.O
(1)
三、简答题
1.描述以下三个概念的区别:
头指针,头结点,表头结点。
1.头指针是指向链表中第一个结点(即表头结点)的指针;在表头结点之前附设的结点称为头结点;表头结点为链表中存储线性表中第一个数据元素的结点。
若链表中附设头结点,则不管线性表是否为空表,头指针均不为空,否则表示空表的链表的头指针为空。
2.线性表的两种存储结构各有哪些优缺点?
2.线性表具有两种存储结构即顺序存储结构和链接存储结构。
线性表的顺序存储结构可以直接存取数据元素,方便灵活、效率高,但插入、删除操作时将会引起元素的大量移动,因而降低效率:
而在链接存储结构中内存采用动态分配,利用率高,但需增设指示结点之间关系的指针域,存取数据元素不如顺序存储方便,但结点的插入、删除操作较简单。
3.对于线性表的两种存储结构,如果有n个线性表同时并存,而且在处理过程中各表的长度会动态发生变化,线性表的总数也会自动改变,在此情况下,应选用哪一种存储结构?
为什么?
3.应选用链接存储结构,因为链式存储结构是用一组任意的存储单元依次存储线性表中的各元素,这里存储单元可以是连续的,也可以是不连续的:
这种存储结构对于元素的删除或插入运算是不需要移动元素的,只需修改指针即可,所以很容易实现表的容量的扩充。
4.对于线性表的两种存储结构,若线性表的总数基本稳定,且很少进行插入和删除操作,但要求以最快的速度存取线性表中的元素,应选用何种存储结构?
试说明理由。
4.应选用顺序存储结构,因为每个数据元素的存储位置和线性表的起始位置相差一个和数据元素在线性表中的序号成正比的常数。
因此,只要确定