1、 第 1章 绪论 习题 1简述下列概念: 数据、数据元素、 数据项、 数据对象、数据结构、逻辑结构、存储结构 、抽象数据类型。 2试举一个数据结构的例子,叙述其逻辑结构和存储结构两方面的含义和相互关系。 3简述 逻辑结构的四种基本关系并画出它们的关系图。 4 存储结构由哪两种基本的存储方法实现? 5 选择题 ( 1)在数据结构中,从逻辑上可以把数据结构分成( )。 A 动态结构和静态结构 B 紧凑结构和非紧凑结构 C 线性结构和非线性结构 D 内部结构和外部结构 ( 2)与数据元素本身的形式、内容、相 对位置、个数无关的是数据的( )。 A 存储结构 B 存储实现 C 逻辑结 构 D 运算实现
2、 ( 3)通常要求同一逻辑结构中的所有数据元素具有相同的特性,这意味着( )。 A 数据具有同一特点 B 不仅数据元素所包含的数据项的个数要相同,而且对应数据项的类型要一致 C 每个数据元素都一样 D 数据元素所包含的数据项的个数要相等 ( 4)以下说法正确的是( )。 A 数据元素是数据的最小单位 B 数据项是数据的基本单位 C 数据结构是带有结构 的各数据项的集合 D 一些表面上很不相同的数据可以有相同的逻辑结构 ( 5) 以下与数据的存储结构无关的术语是( )。 A顺序队列 B. 链表 C. 有序表 D. 链栈 ( 6) 以下数据结构中,( )是非线性数据结构 A树 B字符串 C队 D栈
3、 6试 分析下面各程序段的时间复杂度 。 ( 1) x=90; y=100; while(y0) if(x100) x=x-10;y-; else x+; ( 2) for (i=0; i1 y=0; while(x (y+1)* (y+1) y+; ( 1) O( 1) ( 2) O( m*n) ( 3) O( n2) ( 4) O( log3n) ( 5)因为 x+共执行了 n-1+n-2+ 1= n(n-1)/2,所以执行时间为 O( n2) ( 6) O( n ) 第 2章 线性表 1 选择题 ( 1) 一个向量第一个元素的存储地址是 100,每个元素的长度为 2,则第 5 个元素的地
4、址是 ( )。 A 110 B 108 C 100 D 120 ( 2) 在 n 个结点的顺序表中,算法的时间复杂度是 O(1)的操作是 ( )。 A 访问第 i 个结点( 1 i n)和求第 i 个结点的直接前驱( 2 i n) B 在第 i 个结点后插入一个新结点( 1 i n) C 删除第 i 个结点( 1 i n) D 将 n 个结点从小到大排序 ( 3) 向一个有 127 个元素的顺序表中插入一个新元素并保持原来顺序不变,平均要移动 的 元素 个数为 ( )。 A 8 B 63.5 C 63 D 7 ( 4) 链接存储的存储结构所占存储空间 ( )。 A 分两部分,一部分存放结点值,
5、另一部分存放表示结点间关系的指针 B 只有一部分,存放结点值 C 只有一部分,存储表示结点间关系的指针 D 分两部分,一部分存放结点值,另一部分存放结点所占单元数 ( 5) 线性表若采用链式存储结构时,要求内存中可用存储单元的地址 ( )。 A 必须是连续的 B 部分地址必须是连续的 C 一定是不连续的 D 连续或不连续都可以 ( 6) 线性表在 ( ) 情况下适用于使用链式结构实现。 A 需经常修改中的结点值 需不断对进行删除插入 C 中含有大量的结点 中结点结构复杂 ( 7) 单链表的存储密度 ( )。 A 大于 1 B 等于 1 C 小于 1 D 不能确定 ( 8)将两个各有 n 个元素
6、的有序表归并成一个有序表,其最少的比较次数是( )。 A n B 2n-1 C 2n D n-1 ( 9) 在一个长度为 n 的顺序表中,在第 i 个元素( 1 i n+1)之前插入一个新元素时须向后移动( )个元素。 A n-i B n-i+1 C n-i-1 D i (10) 线性表 L=(a1, a2, an),下列说法正确的是( )。 A 每个元素都有一个直接前驱和一个直接后继 B 线性表中至少有一个元素 C 表中诸元素的排列必须是由小到大或由大到小 D 除第一个和最后一个元素外,其余每个元素都有一个且仅有一个直接前驱和直接后继。 (11) 若指定有 n 个元素的向量,则建立一个有序单
7、链表的时间复杂性的量级是( )。 A O(1) B O(n) C O(n2) D O(nlog2n) (12) 以下说法错误的是( )。 A 求表长、定位这两种运算在采用顺序存储结构时实现的效率不比采用链式存储结构时实现的效率低 B顺 序存储的线性表可以随机存取 C 由于顺序存储要求连续的存储区域,所以在存储管理上不够灵活 D 线性表的链式存储结构优于顺序存储结构 (13) 在单链表中,要将 s 所指结点插入到 p 所指结点之后,其语句应为( )。 A s-next=p+1; p-next=s; B (*p).next=s; (*s).next=(*p).next; C s-next=p-ne
8、xt; p-next=s-next; D s-next=p-next; p-next=s; (14) 在双向链表存储结构中,删除 p 所指的结点时须修改指针( )。 A p-next-prior=p-prior; p-prior-next=p-next; B p-next=p-next-next; p-next-prior=p; C p-prior-next=p; p-prior=p-prior-prior; D p-prior=p-next-next; p-next=p-prior-prior; (15) 在双向循环链表中,在 p 指针所指的结点后插入 q 所指向的新结点,其修改指针的操作是
9、( )。 A p-next=q; q-prior=p; p-next-prior=q; q-next=q; B p-next=q; p-next-prior=q; q-prior=p; q-next=p-next; C q-prior=p; q-next=p-next; p-next-prior=q; p-next=q; D q-prior=p; q-next=p-next; p-next=q; p-next-prior=q; 2算法设计 题 ( 1) 将两个递增的有序链表合并为一个递增的有序链表。要求结果链表仍使用原来两个链表的存储空间 , 不另外占用其它的存储空间。表中不允许有重复的数据。
10、 void MergeList_L(LinkList pb=Lb-next; Lc=pc=La; /用 La 的头结点作为 Lc 的头结点 while(pa pc=pa;pa=pa-next; else if(pa-datapb-data) pc-next=pb; pc=pb; pb=pb-next; else / 相等时取 La 的元素,删除 Lb 的元素 pc-next=pa;pc=pa;pa=pa-next; q=pb-next;delete pb ;pb =q; pc-next=pa?pa:pb; /插入剩余段 delete Lb; /释放 Lb 的头结点 ( 2) 将两个非递减的有序
11、链表合并为一个非递增的有序链表。要求结果链表仍使用原来两个链表的存储空间 , 不另外占用其它的存储空间。表中允许有重复的数据。 void union(LinkList pb = Lb-next; / 初始化 Lc=pc=La; /用 La 的头结点作为 Lc 的头结点 Lc-next = NULL; while ( pa | pb ) if ( !pa ) q = pb; pb = pb-next; else if ( !pb ) q = pa; pa = pa-next; else if (pa-data data ) q = pa; pa = pa-next; else q = pb; p
12、b = pb-next; q-next = Lc-next; Lc-next = q; / 插入 delete Lb; /释放 Lb 的头结点 ( 3) 已知两个链表 A 和 B 分别表示两个集合,其元素递增排列。请设计算法求出 A 与B 的交集,并存放于 A 链表中。 void Mix(LinkListpb=lb-next; 设工作指针 pa 和 pb; Lc=pc=La; /用 La 的头结点作为 Lc 的头结点 while(papc=pa;pa=pa-next; u=pb;pb=pb-next; delete u; else if(pa-datadata) u=pa;pa=pa-next
13、; delete u; else u=pb; pb=pb-next; delete u; while(pa) u=pa; pa=pa-next; delete u; 释放结点空间 while(pb) u=pb; pb=pb-next; delete u; 释放结点空间 pc-next=null; 置链表尾标记。 delete Lb; 注: 本算法中也可对 B 表不作释放空间的处理 ( 4) 已知两个链表 A 和 B 分别表示两个集合,其元素递增排列。请设计算法求出两个集合 A 和 B 的差集(即仅由在 A 中出现而不 在 B 中出现的元素所构成的集合),并以同样的形式存储,同时返回该集合的元素
14、个数。 void Difference( LinkedList A, B, *n) A 和 B 均是带头结点的递增有序的单链表,分别存储了一个集合,本算法求两集合的差集,存储于单链表 A 中, *n 是结果集合中元素个数,调用时为 0 p=A-next; p 和 q 分别是链表 A 和 B 的工作指针。 q=B-next; pre=A; pre 为 A 中 p 所指结点的前驱结点的指针。 while( p!=null pmax=L-next; /假定第一个结点中数据具有最大值 p=L-next-next; while(p != NULL )/如果下一个结点存在 if(p-data pmax-d
15、ata) pmax=p; p=p-next; return pmax-data; ( 7) 设计一个算法,通过遍历一趟,将链表中所有结点的链接方向逆转,仍利用原表的存储空间。 void inverse(LinkList L-next=NULL; while ( p) q=p-next; / q 指向 *p 的后继 p-next=L-next; L-next=p; / *p 插入在头结点之后 p = q; ( 8) 设计一个算法,删除递增有序链表中值大于 mink 且小于 maxk 的所有元素( mink和 maxk 是给定的两个参数,其值可以和表中的元素相同,也可以不同 )。 void del
16、ete(LinkList /首元结点 while (p /查找第一个值 mink 的结点 if (p) while (p / 查找第一个值 maxk 的结点 q=pre-next; pre-next=p; / 修改指针 while (q!=p) s=q-next; delete q; q=s; / 释放结点空间 /if ( 9) 已知 p 指向双向循环链表中的一个结点,其结点结构为 data、 prior、 next 三个域,写出算法 change(p),交换 p 所指向的结点和它的前缀结点的顺序。 知道双向循环链表中的一个结点,与前驱交换涉及到四个结点( p 结点,前驱结点,前驱的前驱结点,
17、后继结点)六条链。 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 结束。 ( 10) 已知长度为 n 的线性表
18、A 采用顺序存储结构,请写一时间复杂度为 O(n)、空间复杂度为 O(1)的算法,该算法删除线性表中所有值为 item 的数据元素。 题目分析 在顺序存储的线性表上删除元素,通常要涉及到一系列元素的移动(删第i 个元素,第 i+1 至第 n 个元素要依次前移)。本题要求删除线性表中所有值为 item 的数据元素,并未要求元素间的相对位置不变。因此可以考虑设头尾两个指针( i=1, j=n),从两端向中间移动,凡遇到值 item 的数据元素时,直接将右端元素左移至值为 item 的数据元素位置。 void Delete( ElemType A , int n) A 是有 n 个元素的一维数组,本
19、算法删除 A 中所有值为 item 的元素。 i=1; j=n;设置数组低、高端指针(下标)。 while( idata;top=top-link; B top=top-link;x=top-link; C x=top;top=top-link; D x=top-link; ( 5) 设有一个递归算法如下 int fact(int n) /n 大于等于 0 if(n=0) return 1; else return n*fact(n-1); 则计算 fact(n)需要调用该函数的次数为 ( ) 。 A n+1 B n-1 C n D n+2 ( 6) 栈在 ( ) 中有所应用。 A 递归调用
20、B 函数调用 C 表达式求值 D 前三个选项都有 ( 7) 为解决计算机主机与打印机间速度不匹配问题,通常设一个打印数据缓冲区。主机将要输出的数据依次写入该缓冲区,而打印机则依次从该缓冲区中取出数据。该缓冲区的逻辑结构应该是 ( ) 。 A 队列 B 栈 C 线性表 D 有序表 ( 8) 设栈 S 和队列 Q 的初始状态为空,元素 e1、 e2、 e3、 e4、 e5 和 e6 依次进入栈 S,一个元素出栈后即进入 Q,若 6 个元素出队的序列是 e2、 e4、 e3、 e6、 e5 和 e1,则栈 S 的容量至少应该是( )。 A 2 B 3 C 4 D 6 ( 9) 在一个具有 n 个单元
21、的顺序栈中,假设以地址高端作为栈底,以 top 作为栈顶指针,则当作进栈处理时, top 的变化为 ( ) 。 A top 不变 B top=0 C top- D top+ ( 10) 设计一个判别表达式中左, 右括号是否配对出现的算法,采用 ( ) 数据结构最佳。 A线性表的顺序存储结构 B 队列 C. 线性表的链式存储结构 D. 栈 ( 11) 用链接方式存储的队列,在进行删除运算时 ( ) 。 A. 仅修改头指针 B. 仅修改尾指针 C. 头、尾指针都要修改 D. 头、尾 指针可能都 要修改 ( 12) 循环队列存储在数组 A0.m中,则入队时的操作为 ( ) 。 A. rear=rea
22、r+1 B. rear=(rear+1)%(m-1) C. rear=(rear+1)%m D. rear=(rear+1)%(m+1) ( 13) 最大容量为 n 的循环队列,队尾指针是 rear,队头是 front,则队空的条件是 ( ) 。 A. (rear+1)%n=front B. rear=front C rear+1=front D. (rear-l)%n=front ( 14) 栈和队列的共同点是 ( ) 。 A. 都是先进先出 B. 都是先进后出 C. 只允 许在端点处插入和删除元素 D. 没有共同点 ( 15) 一个递归算法必须包括 ( ) 。 A. 递归部分 B. 终 止
23、条件和 递归部分 C. 迭代部分 D. 终止条件和迭代部分 ( 2) 回文是指正读反读均相同的字符序列,如 “ abba” 和 “ abdba” 均是回文,但 “ good”不是回文。试写一个算法判定给定的字符向量是否为回文。 (提示:将一半字符入栈 ) 根据提示,算法可设计为: /以下为顺序栈的存储结构定义 #define StackSize 100 /假定预分配的栈空间最多为 100 个元素 typedef char DataType;/假定栈元素的数据类型为字符 typedef struct DataType dataStackSize; int top; SeqStack; int I
24、sHuiwen( char *t) /判断 t 字符向量是否为回文,若是,返回 1,否则返回 0 SeqStack s; int i , len; char temp; InitStack( len=strlen(t); /求向量长度 for ( i=0; ilen/2; i+)/将一半字符入栈 Push( while( !EmptyStack( if( temp!=Si) return 0 ;/ 不等则返回 0 else i+; return 1 ; / 比较完毕均相等则返回 1 ( 3) 设从键盘输入一整数的序列: a1, a2, a3, , an, 试编写算法实现:用栈结构存储输入的整数
25、,当 ai -1 时,将 ai 进栈;当 ai=-1 时,输出栈顶整数并出栈。算法应对异常情况(入栈满等)给出相应 的信息。 #define maxsize 栈空间容量 void InOutS(int smaxsize) /s 是元素为整数的栈,本算法进行入栈和退栈操作。 int top=0; /top 为栈顶指针,定义 top=0 时为栈空。 for(i=1; i=n; i+) /n 个整数序列作处理。 scanf(“%d”, / 从键盘读入整数序列。 if(x!=-1) / 读入的整数不等于 -1 时入栈。 if(top=maxsize-1)printf(“ 栈满 n”);exit(0);
26、 else s+top=x; /x 入栈。 else /读入的整数等于 -1 时退栈。 if(top=0)printf( “栈空 n”);exit(0); else printf(“ 出栈元素是 %dn”,stop -); /算法结束。 ( 4) 从键盘上输入一个后缀表达式, 试编写算法 计算表达式的值。规定:逆波兰表达式的长度不超过一行,以 $符作为输入结束,操作数之间用空格分隔 ,操作符只可能有 +、 -、*、 /四种运算。例如: 234 34+2*$。 题目分析 逆波兰表达式 (即后缀表达式 )求值规则如下:设立运算数栈 OPND,对表达式从左到右扫描 (读入 ),当表达式中扫描到数时,压入 OPND 栈。当扫描到运算符时,从 OPND退出两个数,进行相应运算,结果再压入 OPND 栈。这个过程一直进行到读出表达式结束符 $,这时 OPND 栈中只有一个数,就是结果。 float expr( ) /从键盘输入逆波兰表达式,以 $表示输入结束,本算法求逆波兰式表达 式的值。 float OPND30; / OPND 是操作数栈。 init(OPND); /两栈初始化。 float num=0.0; /数字初始化。