资源描述
.数据结构C语言版第2版课后习题答案李冬梅 2015.3目 录第1章绪论1第2章线性表5第3章栈和队列13第4章串、数组和广义表26第5章树和二叉树33第6章图43第7章查找54第8章排序6565 / 66.第1章 绪论1简述下列概念:数据、数据元素、数据项、数据对象、数据结构、逻辑结构、存储结构、抽象数据类型。答案:数据:是客观事物的符号表示,指所有能输入到计算机中并被计算机程序处理的符号的总称。如数学计算中用到的整数和实数,文本编辑所用到的字符串,多媒体程序处理的图形、图像、声音、动画等通过特殊编码定义后的数据。数据元素:是数据的基本单位,在计算机中通常作为一个整体进行考虑和处理。在有些情况下,数据元素也称为元素、结点、记录等。数据元素用于完整地描述一个对象,如一个学生记录,树中棋盘的一个格局状态、图中的一个顶点等。数据项:是组成数据元素的、有独立含义的、不可分割的最小单位。例如,学生基本信息表中的学号、姓名、性别等都是数据项。数据对象:是性质相同的数据元素的集合,是数据的一个子集。例如:整数数据对象是集合N=0,1,2,字母字符数据对象是集合C=A,B,Z, a,b,z,学生基本信息表也可是一个数据对象。数据结构:是相互之间存在一种或多种特定关系的数据元素的集合。换句话说,数据结构是带结构的数据元素的集合,结构就是指数据元素之间存在的关系。逻辑结构:从逻辑关系上描述数据,它与数据的存储无关,是独立于计算机的。因此,数据的逻辑结构可以看作是从具体问题抽象出来的数学模型。存储结构:数据对象在计算机中的存储表示,也称为物理结构。抽象数据类型:由用户定义的,表示应用问题的数学模型,以及定义在这个模型上的一组操作的总称。具体包括三部分:数据对象、数据对象上关系的集合和对数据对象的基本操作的集合。2试举一个数据结构的例子,叙述其逻辑结构和存储结构两方面的含义和相互关系。答案:例如有一张学生基本信息表,包括学生的学号、姓名、性别、籍贯、专业等。每个学生基本信息记录对应一个数据元素,学生记录按顺序号排列,形成了学生基本信息记录的线性序列。对于整个表来说,只有一个开始结点和一个终端结点,其他的结点则各有一个也只有一个直接前趋和直接后继。学生记录之间的这种关系就确定了学生表的逻辑结构,即线性结构。这些学生记录在计算机中的存储表示就是存储结构。如果用连续的存储单元来存放这些记录,则称为顺序存储结构;如果存储单元不连续,而是随机存放各个记录,然后用指针进行链接,则称为链式存储结构。即相同的逻辑结构,可以对应不同的存储结构。3简述逻辑结构的四种基本关系并画出它们的关系图。答案:1集合结构数据元素之间除了属于同一集合的关系外,别无其他关系。例如,确定一名学生是否为班级成员,只需将班级看做一个集合结构。2线性结构数据元素之间存在一对一的关系。例如,将学生信息数据按照其入学报到的时间先后顺序进行排列,将组成一个线性结构。3树结构数据元素之间存在一对多的关系。例如,在班级的管理体系中,班长管理多个组长,每位组长管理多名组员,从而构成树形结构。4图结构或网状结构数据元素之间存在多对多的关系。例如,多位同学之间的朋友关系,任何两位同学都可以是朋友,从而构成图形结构或网状结构。其中树结构和图结构都属于非线性结构。 四类基本逻辑结构关系图4存储结构由哪两种基本的存储方法实现?答案:1顺序存储结构顺序存储结构是借助元素在存储器中的相对位置来表示数据元素之间的逻辑关系,通常借助程序设计语言的数组类型来描述。2链式存储结构顺序存储结构要求所有的元素依次存放在一片连续的存储空间中,而链式存储结构,无需占用一整块存储空间。但为了表示结点之间的关系,需要给每个结点附加指针字段,用于存放后继元素的存储地址。所以链式存储结构通常借助于程序设计语言的指针类型来描述。5选择题1在数据结构中,从逻辑上可以把数据结构分成 。A动态结构和静态结构 B紧凑结构和非紧凑结构C线性结构和非线性结构 D内部结构和外部结构答案:C2与数据元素本身的形式、内容、相对位置、个数无关的是数据的 。A存储结构 B存储实现C逻辑结构 D运算实现答案:C3通常要求同一逻辑结构中的所有数据元素具有相同的特性,这意味着 。 A数据具有同一特点B不仅数据元素所包含的数据项的个数要相同,而且对应数据项的类型要一致C每个数据元素都一样D数据元素所包含的数据项的个数要相等答案:B4以下说法正确的是 。A数据元素是数据的最小单位B数据项是数据的基本单位C数据结构是带有结构的各数据项的集合D一些表面上很不相同的数据可以有相同的逻辑结构答案:D解释:数据元素是数据的基本单位,数据项是数据的最小单位,数据结构是带有结构的各数据元素的集合。5算法的时间复杂度取决于 。A问题的规模B待处理数据的初态C计算机的配置DA和B答案:D解释:算法的时间复杂度不仅与问题的规模有关,还与问题的其他因素有关。如某些排序的算法,其执行时间与待排序记录的初始状态有关。为此,有时会对算法有最好、最坏以及平均时间复杂度的评价。6以下数据结构中,是非线性数据结构A树 B字符串 C队列 D栈答案:A6试分析下面各程序段的时间复杂度。1x=90; y=100;while0if100x=x-10;y-;else x+;答案:O解释:程序的执行次数为常数阶。2for i=0; ifor j=0; jaij=0;答案:O解释:语句aij=0;的执行次数为m*n。3s=0;for i=0; iforj=0; js+=Bij;sum=s;答案:O解释:语句s+=Bij;的执行次数为n2。4i=1; whilei i=i*3;答案:O解释:语句i=i*3;的执行次数为log3n。5x=0;fori=1; ifor j=1; jx+;答案:O解释:语句x+;的执行次数为n-1+n-2+1= n/2。6x=n; /n1y=0;whilex* y+;答案:O解释:语句y+;的执行次数为。第2章 线性表1选择题1顺序表中第一个元素的存储地址是100,每个元素的长度为2,则第5个元素的地址是 。A110 B108 C100 D120答案:B解释:顺序表中的数据连续存储,所以第5个元素的地址为:100+2*4=108。2在n个结点的顺序表中,算法的时间复杂度是O的操作是 。A访问第i个结点1in和求第i个结点的直接前驱2in B在第i个结点后插入一个新结点1inC删除第i个结点1inD将n个结点从小到大排序答案:A解释:在顺序表中插入一个结点的时间复杂度都是O,排序的时间复杂度为O或O。顺序表是一种随机存取结构,访问第i个结点和求第i个结点的直接前驱都可以直接通过数组的下标直接定位,时间复杂度是O。3向一个有127个元素的顺序表中插入一个新元素并保持原来顺序不变,平均要移动的元素个数为 。A8 B63.5 C63 D7答案:B解释:平均要移动的元素个数为:n/2。4链接存储的存储结构所占存储空间 。A分两部分,一部分存放结点值,另一部分存放表示结点间关系的指针B只有一部分,存放结点值C只有一部分,存储表示结点间关系的指针D分两部分,一部分存放结点值,另一部分存放结点所占单元数答案:A5线性表若采用链式存储结构时,要求内存中可用存储单元的地址 。A必须是连续的 B部分地址必须是连续的C一定是不连续的 D连续或不连续都可以答案:D6线性表在 情况下适用于使用链式结构实现。A需经常修改中的结点值 需不断对进行删除插入 C中含有大量的结点 中结点结构复杂答案:B解释:链表最大的优点在于插入和删除时不需要移动数据,直接修改指针即可。7单链表的存储密度 。A大于1 B等于1 C小于1 D不能确定答案:C解释:存储密度是指一个结点数据本身所占的存储空间和整个结点所占的存储空间之比,假设单链表一个结点本身所占的空间为D,指针域所占的空间为N,则存储密度为:D/,一定小于1。8将两个各有n个元素的有序表归并成一个有序表,其最少的比较次数是 。An B2n-1 C2n Dn-1答案:A解释:当第一个有序表中所有的元素都小于或大于第二个表中的元素,只需要用第二个表中的第一个元素依次与第一个表的元素比较,总计比较n次。9在一个长度为n的顺序表中,在第i个元素1in+1之前插入一个新元素时须向后移动 个元素。An-i Bn-i+1 Cn-i-1 DI答案:B 线性表L=,下列说法正确的是 。A每个元素都有一个直接前驱和一个直接后继B线性表中至少有一个元素C表中诸元素的排列必须是由小到大或由大到小D除第一个和最后一个元素外,其余每个元素都有一个且仅有一个直接前驱和直接后继。答案:D 创建一个包括n个结点的有序单链表的时间复杂度是 。AO BO CO DO答案:C解释:单链表创建的时间复杂度是O,而要建立一个有序的单链表,则每生成一个新结点时需要和已有的结点进行比较,确定合适的插入位置,所以时间复杂度是O。 以下说法错误的是 。A求表长、定位这两种运算在采用顺序存储结构时实现的效率不比采用链式存储结构时实现的效率低B顺序存储的线性表可以随机存取C由于顺序存储要求连续的存储区域,所以在存储管理上不够灵活D线性表的链式存储结构优于顺序存储结构答案:D解释:链式存储结构和顺序存储结构各有优缺点,有不同的适用场合。 在单链表中,要将s所指结点插入到p所指结点之后,其语句应为 。As-next=p+1;p-next=s;B.next=s;.next=.next;Cs-next=p-next;p-next=s-next;Ds-next=p-next;p-next=s; 答案:D 在双向链表存储结构中,删除p所指的结点时须修改指针 。Ap-next-prior=p-prior;p-prior-next=p-next;Bp-next=p-next-next;p-next-prior=p;Cp-prior-next=p;p-prior=p-prior-prior;Dp-prior=p-next-next;p-next=p-prior-prior;答案:A 在双向循环链表中,在p指针所指的结点后插入q所指向的新结点,其修改指针的操作是 。Ap-next=q; q-prior=p;p-next-prior=q;q-next=q;Bp-next=q;p-next-prior=q;q-prior=p;q-next=p-next;Cq-prior=p;q-next=p-next;p-next-prior=q;p-next=q;Dq-prior=p;q-next=p-next;p-next=q;p-next-prior=q;答案:C2算法设计题1将两个递增的有序链表合并为一个递增的有序链表。要求结果链表仍使用原来两个链表的存储空间, 不另外占用其它的存储空间。表中不允许有重复的数据。题目分析合并后的新表使用头指针Lc指向,pa和pb分别是链表La和Lb的工作指针,初始化为相应链表的第一个结点,从第一个结点开始进行比较,当两个链表La和Lb均为到达表尾结点时,依次摘取其中较小者重新链接在Lc表的最后。如果两个表中的元素相等,只摘取La表中的元素,删除Lb表中的元素,这样确保合并后表中无重复的元素。当一个表到达表尾结点,为空时,将非空表的剩余元素直接链接在Lc表的最后。算法描述void MergeList/合并链表La和Lb,合并后的新表使用头指针Lc指向pa=La-next; pb=Lb-next; /pa和pb分别是链表La和Lb的工作指针,初始化为相应链表的第一个结点 Lc=pc=La; /用La的头结点作为Lc的头结点 whileifdatadatapc-next=pa;pc=pa;pa=pa-next;/取较小者La中的元素,将pa链接在pc的后面,pa指针后移 else ifdatapb-data pc-next=pb; pc=pb; pb=pb-next; /取较小者Lb中的元素,将pb链接在pc的后面,pb指针后移 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将两个非递减的有序链表合并为一个非递增的有序链表。要求结果链表仍使用原来两个链表的存储空间, 不另外占用其它的存储空间。表中允许有重复的数据。题目分析合并后的新表使用头指针Lc指向,pa和pb分别是链表La和Lb的工作指针,初始化为相应链表的第一个结点,从第一个结点开始进行比较,当两个链表La和Lb均为到达表尾结点时,依次摘取其中较小者重新链接在Lc表的表头结点之后,如果两个表中的元素相等,只摘取La表中的元素,保留Lb表中的元素。当一个表到达表尾结点,为空时,将非空表的剩余元素依次摘取,链接在Lc表的表头结点之后。算法描述void MergeList /合并链表La和Lb,合并后的新表使用头指针Lc指向 pa=La-next; pb=Lb-next; /pa和pb分别是链表La和Lb的工作指针,初始化为相应链表的第一个结点 Lc=pc=La; /用La的头结点作为Lc的头结点 Lc-next=NULL; while/只要存在一个非空表,用q指向待摘取的元素 if q=pb; pb=pb-next;/La表为空,用q指向pb,pb指针后移 else if q=pa; pa=pa-next; /Lb表为空,用q指向pa,pa指针后移 else ifdatadata q=pa; pa=pa-next;/取较小者包括相等La中的元素,用q指向pa,pa指针后移else q=pb; pb=pb-next;/取较小者Lb中的元素,用q指向pb,pb指针后移 q-next = Lc-next; Lc-next = q; /将q指向的结点插在Lc 表的表头结点之后delete Lb; /释放Lb的头结点 3已知两个链表A和B分别表示两个集合,其元素递增排列。请设计算法求出A与B的交集,并存放于A链表中。题目分析只有同时出现在两集合中的元素才出现在结果表中,合并后的新表使用头指针Lc指向。pa和pb分别是链表La和Lb的工作指针,初始化为相应链表的第一个结点,从第一个结点开始进行比较,当两个链表La和Lb均为到达表尾结点时,如果两个表中相等的元素时,摘取La表中的元素,删除Lb表中的元素;如果其中一个表中的元素较小时,删除此表中较小的元素,此表的工作指针后移。当链表La和Lb有一个到达表尾结点,为空时,依次删除另一个非空表中的所有元素。算法描述void Mix pa=La-next;pb=Lb-next;pa和pb分别是链表La和Lb的工作指针,初始化为相应链表的第一个结点Lc=pc=La; /用La的头结点作为Lc的头结点while ifdata=pb-data交集并入结果表中。 pc-next=pa;pc=pa;pa=pa-next;u=pb;pb=pb-next; delete u;else ifdatadata u=pa;pa=pa-next; delete u;else u=pb; pb=pb-next; delete u;whileu=pa; pa=pa-next; delete u; 释放结点空间while u=pb; pb=pb-next; delete u;释放结点空间pc-next=null;置链表尾标记。delete Lb; /释放Lb的头结点 4已知两个链表A和B分别表示两个集合,其元素递增排列。请设计算法求出两个集合A和B 的差集即仅由在A中出现而不在B中出现的元素所构成的集合,并以同样的形式存储,同时返回该集合的元素个数。题目分析求两个集合A和B的差集是指在A中删除A和B中共有的元素,即删除链表中的相应结点,所以要保存待删除结点的前驱,使用指针pre指向前驱结点。pa和pb分别是链表La和Lb的工作指针,初始化为相应链表的第一个结点,从第一个结点开始进行比较,当两个链表La和Lb均为到达表尾结点时,如果La表中的元素小于Lb表中的元素,pre置为La表的工作指针pa删除Lb表中的元素;如果其中一个表中的元素较小时,删除此表中较小的元素,此表的工作指针后移。当链表La和Lb有一个为空时,依次删除另一个非空表中的所有元素。算法描述void DifferenceLinkList& La, LinkList& Lb,int *n差集的结果存储于单链表La中,*n是结果集合中元素个数,调用时为0pa=La-next; pb=Lb-next;pa和pb分别是链表La和Lb的工作指针,初始化为相应链表的第一个结点 pre=La;pre为La中pa所指结点的前驱结点的指针whilepa&pbifpa-datadatapre=pa;pa=pa-next;*n+; A链表中当前结点指针后移else ifpa-dataq-dataq=q-next;B链表中当前结点指针后移 else pre-next=pa-next;处理A,B中元素值相同的结点,应删除 u=pa; pa=pa-next;delete u; 删除结点5设计算法将一个带头结点的单链表A分解为两个具有相同结构的链表B、C,其中B表的结点为A表中值小于零的结点,而C表的结点为A表中值大于零的结点链表A中的元素为非零整数,要求B、C表利用A表的结点。题目分析B表的头结点使用原来A表的头结点,为C表新申请一个头结点。从A表的第一个结点开始,依次取其每个结点p,判断结点p的值是否小于0,利用前插法,将小于0的结点插入B表,大于等于0的结点插入C表。算法描述void DisCompose B=A;B-next= NULL;B表初始化 C=new LNode;为C申请结点空间 C-next=NULL;C初始化为空表 p=A-next; p为工作指针 whiler=p-next; 暂存p的后继 ifdatap-next=B-next; B-next=p; 将小于0的结点链入B表,前插法 else p-next=C-next; C-next=p; 将大于等于0的结点链入C表,前插法 p=r;p指向新的待处理结点。 6设计一个算法,通过一趟遍历在单链表中确定值最大的结点。题目分析假定第一个结点中数据具有最大值,依次与下一个元素比较,若其小于下一个元素,则设其下一个元素为最大值,反复进行比较,直到遍历完该链表。算法描述ElemType Max ifnext=NULL return NULL;pmax=L-next; /假定第一个结点中数据具有最大值p=L-next-next;while/如果下一个结点存在ifdata pmax-data pmax=p;/如果p的值大于pmax的值,则重新赋值p=p-next;/遍历链表return pmax-data;7设计一个算法,通过遍历一趟,将链表中所有结点的链接方向逆转,仍利用原表的存储空间。题目分析从首元结点开始,逐个地把链表L的当前结点p插入新的链表头部。算法描述void inverse / 逆置带头结点的单链表 L p=L-next; L-next=NULL; while q=p-next; / q指向*p的后继 p-next=L-next; L-next=p; / *p插入在头结点之后 p = q; 8设计一个算法,删除递增有序链表中值大于mink且小于maxk的所有元素mink和maxk是给定的两个参数,其值可以和表中的元素相同,也可以不同 。题目分析分别查找第一个值mink的结点和第一个值 maxk的结点,再修改指针,删除值大于mink且小于maxk的所有元素。算法描述void delete p=L-next; /首元结点 while data pre=p; p=p-next; /查找第一个值mink的结点 if while data p=p-next; / 查找第一个值 maxk的结点 q=pre-next; pre-next=p; / 修改指针 while s=q-next; delete q; q=s; / 释放结点空间 /if9已知p指向双向循环链表中的一个结点,其结点结构为data、prior、next三个域,写出算法change,交换p所指向的结点和它的前缀结点的顺序。题目分析知道双向循环链表中的一个结点,与前驱交换涉及到四个结点p结点,前驱结点,前驱的前驱结点,后继结点六条链。算法描述void ExchangeLinkedList pp是双向循环链表中的一个结点,本算法将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的线性表A采用顺序存储结构,请写一时间复杂度为O、空间复杂度为O的算法,该算法删除线性表中所有值为item的数据元素。题目分析 在顺序存储的线性表上删除元素,通常要涉及到一系列元素的移动删第i个元素,第i+1至第n个元素要依次前移。本题要求删除线性表中所有值为item的数据元素,并未要求元素间的相对位置不变。因此可以考虑设头尾两个指针i=1,j=n,从两端向中间移动,凡遇到值item的数据元素时,直接将右端元素左移至值为item的数据元素位置。算法描述void DeleteElemType A ,int nA是有n个元素的一维数组,本算法删除A中所有值为item的元素。i=1;j=n;设置数组低、高端指针下标。 whileij whileij & Ai!=itemi+;若值不为item,左移指针。 ifijwhileij & Aj=itemj-;若右端元素为item,指针左移 ifijAi+=Aj-;第3章 栈和队列1选择题1若让元素1,2,3,4,5依次进栈,则出栈次序不可能出现在 种情况。A5,4,3,2,1 B2,1,5,4,3 C4,3,1,2,5 D2,3,5,4,1答案:C解释:栈是后进先出的线性表,不难发现C选项中元素1比元素2先出栈,违背了栈的后进先出原则,所以不可能出现C选项所示的情况。2若已知一个栈的入栈序列是1,2,3,n,其输出序列为p1,p2,p3,pn,若p1=n,则pi为 。Ai Bn-i Cn-i+1 D不确定答案:C解释:栈是后进先出的线性表,一个栈的入栈序列是1,2,3,n,而输出序列的第一个元素为n,说明1,2,3,n一次性全部进栈,再进行输出,所以p1=n,p2=n-1,pi=n-i+1。3数组用来表示一个循环队列,为当前队列头元素的前一位置,为队尾元素的位置,假定队列中元素的个数小于,计算队列中元素个数的公式为 。Ar-f B%n Cn+r-fDn+r-f%n答案:D解释:对于非循环队列,尾指针和头指针的差值便是队列的长度,而对于循环队列,差值可能为负数,所以需要将差值加上MAXSIZE本题为n,然后与MAXSIZE本题为n求余,即n+r-f%n。4链式栈结点为:,top指向栈顶.若想摘除栈顶结点,并将删除结点的值保存到x中,则应执行操作。Ax=top-data;top=top-link;Btop=top-link;x=top-link; Cx=top;top=top-link; Dx=top-link;答案:A解释:x=top-data将结点的值保存到x中,top=top-link栈顶指针指向栈顶下一结点,即摘除栈顶结点。5设有一个递归算法如下 int fact /n大于等于0 ifn return 1; else return n*fact; 则计算fact需要调用该函数的次数为。An+1Bn-1C nD n+2答案:A解释:特殊值法。设n=0,易知仅调用一次fact函数,故选A。6栈在中有所应用。A递归调用B函数调用C表达式求值D前三个选项都有答案:D解释:递归调用、函数调用、表达式求值均用到了栈的后进先出性质。7为解决计算机主机与打印机间速度不匹配问题,通常设一个打印数据缓冲区。主机将要输出的数据依次写入该缓冲区,而打印机则依次从该缓冲区中取出数据。该缓冲区的逻辑结构应该是。A队列 B栈 C 线性表 D有序表答案:A解释:解决缓冲区问题应利用一种先进先出的线性表,而队列正是一种先进先出的线性表。8设栈S和队列Q的初始状态为空,元素e1、e2、e3、e4、e5和e6依次进入栈S,一个元素出栈后即进入Q,若6个元素出队的序列是e2、e4、e3、e6、e5和e1,则栈S的容量至少应该是。A2 B3 C4 D 6答案:B解释:元素出队的序列是e2、e4、e3、e6、e5和e1,可知元素入队的序列是e2、e4、e3、e6、e5和e1,即元素出栈的序列也是e2、e4、e3、e6、e5和e1,而元素e1、e2、e3、e4、e5和e6依次进入栈,易知栈S中最多同时存在3个元素,故栈S的容量至少为3。9若一个栈以向量V1.n存储,初始栈顶指针top设为n+1,则元素x进栈的正确操作是。Atop+; Vtop=x;BVtop=x; top+;Ctop-; Vtop=x;DVtop=x; top-;答案:C解释:初始栈顶指针top为n+1,说明元素从数组向量的高端地址进栈,又因为元素存储在向量空间V1.n中,所以进栈时top指针先下移变为n,之后将元素x存储在Vn。10设计一个判别表达式中左,右括号是否配对出现的算法,采用数据结构最佳。A线性表的顺序存储结构B队列C. 线性表的链式存储结构D. 栈答案:D解释:利用栈的后进先出原则。11用链接方式存储的队列,在进行删除运算时。A. 仅修改头指针 B. 仅修改尾指针C. 头、尾指针都要修改 D. 头、尾指针可能都要修改答案:D解释:一般情况下只修改头指针,但是,当删除的是队列中最后一个元素时,队尾指针也丢失了,因此需对队尾指针重新赋值。12循环队列存储在数组A0.m中,则入队时的操作为。A. rear=rear+1 B. rear=% C. rear=%mD. rear=%答案:D解释:数组A0.m中共含有m+1个元素,故在求模运算时应除以m+1。13最大容量为n的循环队列,队尾指针是rear,队头是front,则队空的条件是。 A. %n=front B. rear=front Crear+1=front D. %n=front答案:B解释:最大容量为n的循环队列,队满条件是%n=front,队空条件是rear=front。14栈和队列的共同点是。A. 都是先进先出 B. 都是先进后出C. 只允许在端点处插入和删除元素 D. 没有共同点答案:C解释:栈只允许在栈顶处进行插入和删除元素,队列只允许在队尾插入元素和在队头删除元素。15一个递归算法必须包括。A. 递归部分B. 终止条件和递归部分C. 迭代部分 D. 终止条件和迭代部分答案:B2算法设计题1将编号为0和1的两个栈存放于一个数组空间Vm中,栈底分别处于数组的两端。当第0号栈的栈顶指针top0等于-1时该栈为空,当第1号栈的栈顶指针top1等于m时该栈为空。两个栈均从两端向中间增长。试编写双栈初始化,判断栈空、栈满、进栈和出栈等算法的函数。双栈数据结构的定义如下:Typedef structint top2,bot2;/栈顶和栈底指针 SElemType *V;/栈数组 int m;/栈最大可容纳元素个数DblStack题目分析两栈共享向量空间,将两栈栈底设在向量两端,初始时,左栈顶指针为-1,右栈顶为m。两栈顶指针相邻时为栈满。两栈顶相向、迎面增长,栈顶指针指向栈顶元素。算法描述栈初始化intInitS.top0=-1;S.top1=m;return1;/初始化成功入栈操作:intpushi为栈号,i=0表示左栈,i=1为右栈,x是入栈元素。入栈成功返回1,失败返回0ifi1cout栈号输入不对endl;exit;if cout栈已满endl;return;switchcase0: S.V+S.top0=x;return;break;case1: S.V-S.top1=x;return;push退栈操作ElemType pop退栈。i代表栈号,i=0时为左栈,i=1时为右栈。退栈成功时返回退栈元素否则返回-1ifi1cout栈号输入错误endl;exit;switchcase0:if cout栈空endl;return-1;elsereturn;case1:ifS.top1=m cout栈空endl;return;elsereturn;switch 算法结束判断栈空intEmpty;return;算法讨论请注意算法中两栈入栈和退栈时的栈顶指针的计算。左栈是通常意义下的栈,而右栈入栈操作时,其栈顶指针左移减1,退栈时,栈顶指针右移加1。2回文是指正读反读均相同的字符序列,如abba和abdba均是回文,但good不是回文。试写一个算法判定给定的字符向量是否为回文。题目分析将字符串前一半入栈,然后,栈中元素和字符串后一半进行比较。即将第一个出栈元素和后一半串中第一个字符比较,若相等,则再出栈一个元素与后一个字符比较,直至栈空,结论为字符序列是回文。在出栈元素与串中字符比较不等时,结论字符序列不是回文。算法描述#define StackSize 100 /假定预分配的栈空间最多为100个元素typedef char DataType;/假定栈元素的数据类型为字符typedef structDataType dataStackSize;int top;SeqStack;int IsHuiwen/判断t字符向量是否为回文,若是,返回1,否则返回0SeqStack s;int i , len;char temp;InitStack;len=strlen; /求向量长度for i=0; i/将一半字符入栈Push;while !EmptyStack/ 每弹出一个字符与相应字符比较temp=Pop ;if return 0 ;/ 不等则返回0else i+;return 1 ; / 比较完毕均相等则返回 13设从键盘输入一整数的序列:a1, a2, a3,an,试编写算法实现:用栈结构存储输入的整数,当ai-1时,将ai进栈;当ai=-1时,输出栈顶整数并出栈。算法应对异常情况入栈满等给出相应的信息。算法描述#define maxsize 栈空间容量void InOutS/s是元素为整数的栈,本算法进行入栈和退栈操作。int top=0; /top为栈顶指针,定义top=0时为栈空。fori=1; i /n个整数序列作处理。cinx; /从键盘读入整数序列。if / 读入的整数不等于-1时入栈。ifcout栈满endl;exit;else s+top=x; /x入栈。else /读入的整数等于-1时退栈。ifcout栈空endl;exit; else cout出栈元素是stop-endl;/算法结束。4从键盘上输入一个后缀表达式,试编写算法计算表达式的值。规定:逆波兰表达式的长度不超过一行,以$符作为输入结束,操作数之间用空格分隔,操作符只可能有+、-、*、/四种运算。例如:234 34+2*$。题目分析逆波兰表达式求值规则如下:设立运算数栈OPND,对表达式从左到右扫描,当表达式中扫描到数时,压入OPND栈。当扫描到运算符时,从OPND退出两个数,进行相应运算,结果再压入OPND栈。这个过程一直进行到读出表达式结束符$,这时OPND栈中只有一个数,就是结果。算法描述float expr/从键盘输入逆波兰表达式,以$表示输入结束,本算法求逆波兰式表达式的值。float OPND30; / OPND是操作数栈。init; /两栈初始化。float num=0.0; /数字初始化。cinx;/x是字符型变量。whileswitch case0=x=9:while=0&x|x=. /拼数if /处理整数num=num*10+ord-ord; cinx;else /处理小数部分。scale=10.0; cinx;while=0&xnum=num+ord-ord/scale;scale=scale*10; cinx; /elsepush; num=0.0;/数压入栈,下个数初始化 case x= :break; /遇空格,继续读下一个字符。 case x=+:pushOPND,pop+pop;break; case x=-:x1=pop;x2=pop;push;break; case x=*:pushOPND,pop*pop;break; case x=/:x1=pop;x2=pop;push;break; default: /其它符号不作处理。 /结束switchcinx;/读入表达式中下一个字符。 /结束whilex!=$cout后缀表达式的值为pop;/算法结束。算法讨论假设输入的后缀表达式是正确的,未作错误检查。算法中拼数部分是核心。若遇到大于等于0且小于等于9的字符,认为是数。这种字符的序号减去字符0的序号得出数。对于整数,每读入一个数字字符,前面得到的部分数要乘上10再加新读入的数得到新的部分数。当读到小数点,认为数的整数部分已完,要接着处理小数部分。小数部分的数要除以10或10的幂数变成十分位,百分位,千分位数等等,与前面部分数相加。在拼数过程中,若遇非数字字符,表示数已拼完,将数压入栈中,并且将变量num恢复为0,准备下一个数。这时对新读入的字符进入+、-、*、/及空格的判断,因此在结束处理数字字符的case后,不能加入break语句。5假设以I和O分别表示入栈和出栈操作。栈的初态和终态均为空,入栈和出栈的操作序列可表示为仅由I和O组成的序列,称可以操作的序列为合法序列,否则称为非法序列。下面所示的序列中哪些是合法的? A. IOIIOIOO B. IOOIOIIO C. IIIOIOIO D. IIIOOIOO通过对的分析,写出一个算法,判定所给的操作序列是否合法。若合法,返回true,否则返回false假定被判定的操作序列已存入一维数组中。答案:A和D是合法序列,B和C 是非法序列。设被判定的操作序列已存入一维数组A中。int Judge /判断字符数组A中的输入输出序列是否是合法序列。如是,返回true,否则返回false。 i=0; /i为下标。 j=k=0; /j和k分别为I和字母O的的个数。 while /当未到字符数组尾就作。 switch caseI: j+; break; /入栈次数增1。 caseO: k+; ifjcout序列非法ednl;exit; i+; /不论Ai是I或O,指针i均后移。 if cout序列非法endl;return; else cout序列合法endl;return; /算法结束。 算法讨论在入栈出栈序列即由I和O组成的字符串的任一位置,入栈次数I的个数都必须大于等于出栈次数即O的个数,否则视作非法序列,立即给出信息,退出算法。整个序列即读到字符数组中字符串的结束标记0,入栈次数必须等于出栈次数题目中要求栈的初态和终态都为空,否则视为非法序列。6假设以带头结点的循环链表表示队列,并且只设一个指针指向队尾元素站点 ,试编写相应的置空队、判队空 、入队和出队等算法。题目分析置空队就是建立一个头节点,并把头尾指针都指向头节点,头节点是不存放数据的;判队空就是当头指针等于尾指针时,队空;入队时,将新的节点插入到链队列的尾部,同时将尾指针指向这个节点;出队时,删除的是队头节点,要注意队列的长度大于1还是等于1的情况,这个时候要注意尾指针的修改,如果等于1,则要删除尾指针指向的节点。算法描述/先定义链队结构:typedef struct queuenodeDatatype data;struct queuenode *next;QueueNode; /以上是结点类型的定义typedef structqueuenode *rear;LinkQueue; /只设一个指向队尾元素的指针(1) 置空队void InitQueue /置空队:就是使头结点成为队尾元素QueueNode *s;Q-rear = Q-rear-next;/将队尾指针指向头结点while rear!=Q-rear-next/当队列非空,将队中元素逐个出队s=Q-rear-next;Q-rear-next=s-next;delete s;/回收结点空间(2) 判队空int EmptyQueue /判队空。当头结点的next指针指向自己时为空队return Q-rear-next-next=Q-rear-next;(3) 入队void EnQueue
展开阅读全文