本站
非官方网站,信息完全免费,仅供参考,不收取任何费用,具体请以官网公布为准!
数据结构线性表练习题及答案
一 选择题
1. 下述哪一条是顺序存储结构的优点?(A)。
A.存储密度大 B.插入运算方便 C.删除运算方便 D.可方便地用于各种逻辑结构的存储表示
2.下面关于线性表的叙述中,错误的是哪一个?(B)
A.线性表采用顺序存储,必须占用一片连续的存储单元。
B.线性表采用顺序存储,便于进行插入和删除操作。
C.线性表采用链接存储,不必占用一片连续的存储单元。
D.线性表采用链接存储,便于插入和删除操作。
3.线性表是具有n个( C)的有限序列(n>0)。
A.表元素 B.字符 C.数据元素 D.数据项 E.信息项
4.若某线性表最常用的操作是存取任一指定序号的元素和在最后进行插入和删除运算,则利用(A)存储方式最节省时间。
A.顺序表 B.双链表 C.带头结点的双循环链表 D.单循环链表
5.某线性表中最常用的操作是在最后一个元素之后插入一个元素和删除第一个元素,则采用(D)存储方式最节省运算时间。
A.单链表 B.仅有头指针的单循环链表 C.双链表 D.仅有尾指针的单循环链表
6.设一个链表最常用的操作是在末尾插入结点和删除尾结点,则选用(D)最节省时间。
A. 单链表 B.单循环链表 C. 带尾指针的单循环链表 D.带头结点的双循环链表
7.若某表最常用的操作是在最后一个结点之后插入一个结点或删除最后一个结点。则采用(D)存储方式最节省运算时间。
A.单链表 B.双链表 C.单循环链表 D.带头结点的双循环链表
8. 静态链表中指针表示的是(C)。
A. 内存地址 B.数组下标 C.下一元素地址 D.左、右孩子地址
9. 链表不具有的特点是(B)。
A.插入、删除不需要移动元素 B.可随机访问任一元素 C.不必事先估计存储空间 D.所需空间与线性长度成正比
10. 下面的叙述不正确的是(B,C)。
A.线性表在链式存储时,查找第i个元素的时间同i的值成正比
B. 线性表在链式存储时,查找第i个元素的时间同i的值无关
C. 线性表在顺序存储时,查找第i个元素的时间同i 的值成正比
D. 线性表在顺序存储时,查找第i个元素的时间同i的值无关
11. 对于顺序存储的线性表,访问结点和增加、删除结点的时间复杂度为(C)。
A.O(n) O(n) B. O(n) O(1) C. O(1) O(n) D. O(1) O(1)
二、判断题
1. 链表中的头结点仅起到标识的作用。(×)
2. 顺序存储结构的主要缺点是不利于插入或删除操作。(√)
3.线性表采用链表存储时,结点和结点内部的存储空间可以是不连续的。(√)
4.顺序存储方式插入和删除时效率太低,因此它不如链式存储方式好。(×)
5. 对任何数据结构链式存储结构一定优于顺序存储结构。(×)
6.顺序存储方式只能用于存储线性结构。(×)
7.集合与线性表的区别在于是否按关键字排序。(×)
8. 所谓静态链表就是一直不发生变化的链表。(×)
9. 线性表的特点是每个元素都有一个前驱和一个后继。(×)
10. 取线性表的第i个元素的时间同i的大小有关. (×)
11. 循环链表不是线性表. (×)
12. 线性表只能用顺序存储结构实现。(×)
13. 线性表就是顺序存储的表。(×)
14.为了很方便的插入和删除数据,可以使用双向链表存放数据。(√)
15. 顺序存储方式的优点是存储密度大,且插入、删除运算效率高。(×)
16. 链表是采用链式存储结构的线性表,进行插入、删除操作时,在链表中比在顺序存储结构中效率高。 (√)
三、填空
1.当线性表的元素总数基本稳定,且很少进行插入和删除操作,但要求以最快的速度存取线性表中的元素时,应采用__顺序__存储结构。
2.线性表L=(a1,a2,…,an)用数组表示,假定删除表中任一元素的概率相同,则删除一个元素平均需要移动元素的个数是__(n-1)/2__。
3.设单链表的结点结构为(data,next),next为指针域,已知指针px指向单链表中data为x的结点,指针py指向data为y的新结点 , 若将结点y插入结点x之后,则需要执行以下语句:py->next=px->next; px->next=py;
4.在一个长度为n的顺序表中第i个元素(1<=i<=n)之前插入一个元素时,需向后移动 n-i+1个元素。
5.在单链表中设置头结点的作用是主要是使插入和删除等操作统一,在第一个元素之前插入元素和删除第一个结点不必另作判断。另外,不论链表是否为空,链表指针不变。。
6.对于一个具有n个结点的单链表,在已知的结点*p后插入一个新结点的时间复杂度为O(1),在给定值为x的结点后插入一个新结点的时间复杂度为O(n)。
7.根据线性表的链式存储结构中每一个结点包含的指针个数,将线性链表分成单链表和多重链表;而又根据指针的连接方式,链表又可分成(动态)链表和静态链表。
8. 在双向循环链表中,向p所指的结点之后插入指针f所指的结点,其操作是f->next=p->next、f->prior=p、p->next->prior=f、p->next=f。
四、应用题
1.线性表有两种存储结构:一是顺序表,二是链表。试问:
(1)如果有 n个线性表同时并存,并且在处理过程中各表的长度会动态变化,线性表的总数也会自动地改变。在此情况下,应选用哪种存储结构? 为什么?
答:选链式存储结构。它可动态申请内存空间,不受表长度(即表中元素个数)的影响,插入、删除时间复杂度为O(1)。
(2)若线性表的总数基本稳定,且很少进行插入和删除,但要求以最快的速度存取线性表中的元素,那么应采用哪种存储结构?为什么?
答:选顺序存储结构。顺序表可以随机存取,时间复杂度为O(1)。
2.线性表的顺序存储结构具有三个弱点:其一,在作插入或删除操作时,需移动大量元素;其二,由于难以估计,必须预先分配较大的空间,往往使存储空间不能得到充分利用;其三,表的容量难以扩充。线性表的链式存储结构是否一定都能够克服上述三个弱点,试讨论之。
答:链式存储结构一般说克服了顺序存储结构的三个弱点。首先,插入、删除不需移动元素,只修改指针,时间复杂度为O(1);其次,不需要预先分配空间,可根据需要动态申请空间;其三,表容量只受可用内存空间的限制。其缺点是因为指针增加了空间开销,当空间不允许时,就不能克服顺序存储的缺点。
3.若较频繁地对一个线性表进行插入和删除操作,该线性表宜采用何种存储结构?为什么?
答:采用链式存储结构,它根据实际需要申请内存空间,而当不需要时又可将不用结点空间返还给系统。在链式存储结构中插入和删除操作不需要移动元素。
4.线性表(a1,a2,…,an)用顺序映射表示时,ai和ai+1(1<=i<n〉的物理位置相邻吗?链接表示时呢?
答:顺序映射时,ai与ai+1的物理位置相邻;链表表示时ai与ai+1的物理位置不要求相邻。
5. 说明在线性表的链式存储结构中,头指针与头结点之间的根本区别;头结点与首元结点的关系。
答:在线性表的链式存储结构中,头指针指链表的指针,若链表有头结点则是链表的头结点的指针,头指针具有标识作用,故常用头指针冠以链表的名字。头结点是为了操作的统一、方便而设立的,放在第一元素结点之前,其数据域一般无意义(当然有些情况下也可存放链表的长度、用做监视哨等等),有头结点后,对在第一元素结点前插入结点和删除第一结点,其操作与对其它结点的操作统一了。而且无论链表是否为空,头指针均不为空。首元结点也就是第一元素结点,它是头结点后边的第一个结点。
五、算法设计题
1. 假设有两个按元素值递增次序排列的线性表,均以单链表形式存储。请编写算法将这两个单链表归并为一个按元素值递减次序排列的单链表,并要求利用原来两个单链表的结点存放归并后的单链表。
答: [题目分析]因为两链表已按元素值递增次序排列,将其合并时,均从第一个结点起进行比较,将小的链入链表中,同时后移链表工作指针。该问题要求结果链表按元素值递减次序排列。故在合并的同时,将链表结点逆置。
LinkedList Union(LinkedList la,lb)
∥la,lb分别是带头结点的两个单链表的头指针,链表中的元素值按递增序排列,本算法将两链表合并成一个按元素值递减次序排列的单链表。
{ pa=la->next; pb=lb->next;∥pa,pb分别是链表la和lb的工作指针
la->next=null; ∥la作结果链表的头指针,先将结果链表初始化为空。
while(pa!=null && pb!=null) ∥当两链表均不为空时作
if(pa->data<=pb->data)
{ r=pa->next; ∥将pa 的后继结点暂存于r。
pa->next=la->next; ∥将pa结点链于结果表中,同时逆置。
la->next=pa;
pa=r; ∥恢复pa为当前待比较结点。
}
else
{r=pb->next; ∥ 将pb 的后继结点暂存于r。
pb->next=la->next; ∥将pb结点链于结果表中,同时逆置。
la->next=pb;
pb=r; ∥恢复pb为当前待比较结点。
}
while(pa!=null) ∥将la表的剩余部分链入结果表,并逆置。
{r=pa->next; pa->next=la->next; la->next=pa; pa=r; }
while(pb!=null)
{r=pb->next; pb->next=la->next; la->next=pb; pb=r; }
}∥算法Union结束。
[算法讨论]上面两链表均不为空的表达式也可简写为while(pa&&pb),两递增有序表合并成递减有序表时,上述算法是边合并边逆置。也可先合并完,再作链表逆置。后者不如前者优化。算法中最后两个while语句,不可能执行两个,只能二者取一,即哪个表尚未到尾,就将其逆置到结果表中,即将剩余结点依次前插入到结果表的头结点后面。
2. 试编写在带头结点的单链表中删除(一个)最小值结点的(高效)算法。void delete(Linklist &L)
答: [题目分析] 本题要求在单链表中删除最小值结点。单链表中删除结点,为使结点删除后不出现“断链”,应知道被删结点的前驱。而“最小值结点”是在遍历整个链表后才能知道。所以算法应首先遍历链表,求得最小值结点及其前驱。遍历结束后再执行删除操作。
LinkedList Delete(LinkedList L)
∥L是带头结点的单链表,本算法删除其最小值结点。
{p=L->next; ∥p为工作指针。指向待处理的结点。假定链表非空。
pre=L; ∥pre指向最小值结点的前驱。
q=p; ∥q指向最小值结点,初始假定第一元素结点是最小值结点。
while(p->next!=null)
{if(p->next->datadata){pre=p;q=p->next;} ∥查最小值结点
p=p->next; ∥指针后移。
}
pre->next=q->next;∥从链表上删除最小值结点
free(q); ∥释放最小值结点空间
}∥结束算法delete。
[算法讨论] 算法中函数头是按本教材类C描述语言书写的。原题中void delete(linklist &L),是按C++的“引用”来写的,目的是实现变量的“传址”,克服了C语言函数传递只是“值传递”的缺点。
3. 已知非空线性链表由list指出,链结点的构造为(data,link).请写一算法,将链表中数据域值最小的那个链结点移到链表的最前面。要求:不得额外申请新的链结点。
答: [题目分析] 本题要求将链表中数据域值最小的结点移到链表的最前面。首先要查找最小值结点。将其移到链表最前面,实质上是将该结点从链表上摘下(不是删除并回收空间),再插入到链表的最前面。
LinkedList delinsert(LinkedList list)
∥list是非空线性链表,链结点结构是(data,link),data是数据域,link是链域。
∥本算法将链表中数据域值最小的那个结点移到链表的最前面。
{p=list->link;∥p是链表的工作指针
pre=list; ∥pre指向链表中数据域最小值结点的前驱。
q=p; ∥q指向数据域最小值结点,初始假定是第一结点
while (p->link!=null)
{if(p->link->datadata){pre=p;q=p->link;} ∥找到新的最小值结点;
p=p->link;
}
if (q!=list->link) ∥若最小值是第一元素结点,则不需再操作
{pre->link=q->link; ∥将最小值结点从链表上摘下;
q->link= list->link; ∥将q结点插到链表最前面。
list->link=q;
}
}∥算法结束
[算法讨论] 算法中假定list带有头结点,否则,插入操作变为q->link=list;list=q。
4. 已知p指向双向循环链表中的一个结点,其结点结构为data、llink、rlink三个域,写出算法change(p),交换p所指向的结点和它的前缀结点的顺序。
答: [题目分析] 知道双向循环链表中的一个结点,与前驱交换涉及到四个结点(p结点,前驱结点,前驱的前驱结点,后继结点)六条链。
void Exchange(LinkedList p)
∥p是双向循环链表中的一个结点,本算法将p所指结点与其前驱结点交换。
{q=p->llink;
q->llink->rlink=p; ∥p的前驱的前驱之后继为p
p->llink=q->llink; ∥p的前驱指向其前驱的前驱。
q->rlink=p->rlink; ∥p的前驱的后继为p的后继。
q->llink=p; ∥p与其前驱交换
p->rlink->llink=q; ∥p的后继的前驱指向原p的前驱
p->rlink=q; ∥p的后继指向其原来的前驱
}∥算法exchange结束。
5. 线性表(a1,a2,a3,…,an)中元素递增有序且按顺序存储于计算机内。要求设计一算法完成:
(1) 用最少时间在表中查找数值为x的元素。
(2) 若找到将其与后继元素位置相交换。
(3) 若找不到将其插入表中并使表中元素仍递增有序。
答: [题目分析] 顺序存储的线性表递增有序,可以顺序查找,也可折半查找。题目要求“用最少的时间在表中查找数值为x的元素”,这里应使用折半查找方法。
void SearchExchangeInsert(ElemType a[];ElemType x)
∥a是具有n个元素的递增有序线性表,顺序存储。本算法在表中查找数值为x的元素,如查到则与其后继交换位置;如查不到,则插入表中,且使表仍递增有序。
{ low=0;high=n-1; ∥low和high指向线性表下界和上界的下标
while(low<=high)
{mid=(low+high)/2; ∥找中间位置
if(a[mid]==x) break; ∥找到x,退出while循环。
else if (a[mid] <x) low=mid+1;∥到中点mid的右半去查。
else high=mid-1; ∥到中点mid的左部去查。
}
if(a[mid]==x && mid!=n)∥ 若最后一个元素与x相等,则不存在与其后继交换的操作。
{t=a[mid];a[mid]=a[mid+1];a[mid+1]=t;} ∥ 数值x与其后继元素位置交换。
if(low>high) ∥查找失败,插入数据元素x
{for(i=n-1;i>high;i--) a[i+1]=a[i];∥后移元素。
a[i+1]=x;∥插入x。
} ∥结束插入
}∥结束本算法。
[算法讨论] 首先是线性表的描述。算法中使用一维数组a表示线性表,未使用包含数据元素的一维数组和指示线性表长度的结构体。若使用结构体,对元素的引用应使用a.elem[i]。另外元素类型就假定是ElemType,未指明具体类型。其次,C中一维数组下标从0开始,若说有n个元素的一维数组,其最后一个元素的下标应是n-1。第三,本算法可以写成三个函数,查找函数,交换后继函数与插入函数。写成三个函数显得逻辑清晰,易读。
海南高考志愿填报 http://www.xuecan.net/yanzhao/