数据结构实用教程习题答案.docx
- 文档编号:10184933
- 上传时间:2023-02-09
- 格式:DOCX
- 页数:54
- 大小:344.31KB
数据结构实用教程习题答案.docx
《数据结构实用教程习题答案.docx》由会员分享,可在线阅读,更多相关《数据结构实用教程习题答案.docx(54页珍藏版)》请在冰豆网上搜索。
数据结构实用教程习题答案
1绪论
1.1回答下列概念:
数据结构,数据的逻辑结构,数据的存储结构,算法
数据结构:
按照某种逻辑关系组织起来的一批数据,用一定的存储方式存储在计算机的存储器中,并在这些数据上定义一个运算的集合,就称为一个数据结构。
数据的逻辑结构:
数据元素之间的逻辑关系,是根据实际问题抽象出来的数学模型。
数据的存储结构:
是指数据的逻辑结构到计算机存储器的映射。
算法:
是指对数据元素进行加工和处理
1.2数据结构研究的三方面内容是什么?
它们之间有什么联系和区别?
三方面内容:
数据的逻辑结构、数据的存储结构和数据运算的集合。
联系和区别:
数据的逻辑结构是数学模型,数据的存储结构是指逻辑结构到存储区域的映射,运算是定义在逻辑结构上,实现在存储结构上。
1.3简述数据结构中讨论的三种经典结构及其逻辑特征。
三种经典结构:
线性表、树和图。
线性表:
有且仅有一个开始结点和一个终端结点,其余的内部结点都有且仅有一个前趋结点和一个后继结点,数据元素间存在着一对一的相互关系。
树:
有且仅有一个开始结点,可有若干个终端结点,其余的内部结点都有且仅有一个前趋结点,可以有若干个后继结点,数据元素间存在着一对多的层次关系。
图:
可有若干个开始结点和终端结点,其余的内部结点可以有若干个前趋结点和若干个后继结点,数据元素间存在着多对多的网状关系。
1.4实现数据存储结构的常用存储方法有哪几种?
简述各种方法的基本思想。
常用存储方法有四种:
顺序存储、链接存储、索引存储、散列存储。
各种方法的基本思想:
顺序存储:
把逻辑上相邻的数据元素存储在物理位置上相邻的存储单元里。
链接存储:
通过附加指针域表示数据元素之间的关系。
索引存储:
除了存储数据元素,还要建立附加索引表来标识数据元素的地址。
散列存储:
根据数据元素的关键字直接计算出该结点的存储地址,称为关键字-地址转换法。
1.5算法的特性是什么?
如何定性的评价一个算法的优劣?
算法的特性:
有穷性、确定性、可行性、输入、输出。
算法的定性评价标准有:
正确性、可读性、健壮性、简单性。
1.6算法的定量评价标准是什么?
算法的定量评价标准有:
时间复杂度和空间复杂度。
时间复杂度:
是一个算法运行时所耗费的系统时间,也就是算法的时间效率。
空间复杂度:
是一个算法运行时所耗费的存储空间,也就是算法的空间效率。
1.7写出下列程序段中带标号语句的频度,并给出执行各程序段的时间复杂度(n为整数)。
(1)i=1;
(2)s=1;
while(i 【1】i++;【1】s=s*i; (3)s=0;(4)i=1; for(i=l;i for(j=n;j>=i;j--)【1】i++; 【1】s=s+i+j; (5)i=1;(6)x=1;y=100; while(i 【1】i=i*2;【1】x++;y--; }While(x 答: (1)n-1,O(n) (2)n,O(n)(3)(n+2)(n-1)/2,O(n2) (4),O()(5)㏒(n-1)+1,O(n)(6)50,O (1) 2线性表 2.1回答下列概念: 线性结构,线性表,顺序表,单链表,静态链表 线性结构: 设Data_Structure=(D,S),r∈S,相对r,D中有且仅有一个开始结点和一个终端结点,其余的内部结点都有且仅有一个前趋和一个后继,则称Data_Structure是相对r的线性结构。 线性表: 是具有相同属性的n(n≥0)个数据元素的有限序列。 顺序表: 顺序表(SequentialList)是采用顺序存储结构的线性表。 单链表: 每个结点只附加一个指向后继的指针域,这样的链表称为单链表 (SingleLinkedList) 静态链表: 用数组实现的链表,指针就变换为数组的下标,结点即为数组中的下标变量,由于需要预先分配一个较大的数组空间,因此这种链表称之为静态链表。 2.2比较顺序表和链表这两种线性表不同存储结构的特点。 1.逻辑关系的表示: 顺序表隐含表示关系,链表显示表示关系。 2.存储密度: 顺序表的存储密度大,而链表的存储密度小。 3.存储分配方式: 顺序表的存储空间是预先静态分配的一块连续存储空间,在程序执行之前必须明确规定它的存储规模。 链表不用事先估计存储规模,动态分配和释放存储空间,存储空间可连续也可不连续。 4.存取方法: 顺序表可以随机存取,链表必须顺序存取。 5.插入、删除操作: 在顺序表中做插入、删除时平均移动表中一半的元素;在链表中作插入、删除时,只要修改指针域,而不需要移动元素。 所以顺序表的插入、删除效率低,链表的插入、删除效率高。 6.实现语言: 顺序表容易实现,任何高级语言中都有数组类型。 而链表的操作是基于指针的,对于没有提供指针类型的高级语言,必须采用静态链表。 总之,两种存储结构各有长短,选择那一种由实际问题中的主要因素决定。 通常“较稳定”的线性表选择顺序存储,而频繁做插入、删除的线性表,即动态性较强的线性表宜选择链接存储。 2.3已知长度为n的线性表A中的元素是整数,写算法求线性表中值大于item的元素个数。 分两种情况编写函数: (1)线性表采用顺序存储; (2)线性表采用单链表存储。 (1)线性表采用顺序存储 #defineMAX1024 typedefintDataType; typedefstruct {DataTypedata[MAX]; intlast; }SeqList; intLocateElem(SeqList*L,DataTypeitem) {inti,j=0; for(i=0;i<=L->last;i++) if(L->data[i]>item)j++; returnj;} (2)线性表采用单链表存储 typedefintDataType; typedefstructNode {DataTypedata; structNode*next; }LinkList; LinkList*locateElem(LinkList*L,DataTypeitem) {LinkList*p=L->next; inti=0; while(p) {if(p->data>item)i++;p=p->next;} returni; } 2.4已知长度为n的线性表A中的元素是整数,写算法删除线性表中所有值为item的数据元素。 分两种情况编写函数: (1)线性表采用顺序存储; (2)线性表采用单链表存储。 (1)线性表采用顺序存储 #defineMAX1024 typedefintDataType; typedefstruct {DataTypedata[MAX]; intlast; }SeqList; intLocateElem(SeqList*L,DataTypeitem) {inti=0; While(i<=L->last) if(L->data[i]==item) {for(j=i+1;j<=L->last;j++)L->data[j-1]=L->data[j];L->last--;} Elsei++; } (2)线性表采用单链表存储 typedefintDataType; typedefstructNode {DataTypedata; structNode*next; }LinkList; intdeleteDupNode(LinkList*L,DataTypeitem) {LinkList*p,*q,*r; q=L;p=L->next; while(p) if(p->data==item){q->next=p->next;free(p);p=q->next;} else{q=p;p=p->next;} } 2.5设长度为Max的顺序表L中包含n个整数且递增有序。 试写一算法,将x插入到顺序表的适当位置上,以保持表的有序性,并且分析算法的时间复杂度。 #defineMAX1024 typedefintDataType; typedefstruct {DataTypedata[MAX]; intlast; }SeqList; intinserts(SeqList*L,DataTypex) {inti; if(L->last==Max-1){printf(“full”);return0;} i=L->last; while(i>=0&&L->data[i]>x) L->data[i+1]=L->data[i--];//“相当于L->data[i+1]=L->data[i];i--;” L->data[i+1]=x;L->last++;return1; } 2.6设带头结点的单链表L中的数据元素是整型数且递增有序。 试写一算法,将x插入到单链表的适当位置上,以保持表的有序性,并且分析算法的时间复杂度。 typedefintDataType; typedefstructNode {DataTypedata; structNode*next; }LinkList; voidInsertList(LinkList*L,datetypex) {LinkList*p,*s; s=(LinkList*)malloc(sizeof(Linklist)); s->data=x; p=L; while((p->next)&&(p->next->data p=p->next; s->next=p->next;p->next=s; } 2.7试写一算法实现对不带头结点的单链表H进行就地逆置。 typedefintDataType; typedefstructNode {DataTypedata; structNode*next; }LinkList; LinkList*Reverse(LinkList*H) {LinkList*p,*q; if(! H)return; p=H->next;q=H->next;H->next=NULL; While(q) {q=q->next;p->next=H;H=p;p=q;} returnH; } 2.8若带头结点的单链表L中的数据元素是整型数,编写算法对单链表L进行排序。 typedefintDataType; typedefstructNode {DataTypedata; structNode*next; }LinkList; voidInsertList(LinkList*L) {LinkList*p,*q,*s; if(! L->next||! L->next->next)return; q=L->next->next;L->next->next=NULL; while(q) {s=q;q=q->next; p=L; while((p->next)&&(p->next->data s->next=p->next;p->next=s; } } 2.9设单链表X和单链表Y分别存储了两个字符串,设计算法找出X中第一个不在Y中出现的字符。 typedefcharDataType; typedefstructNode {DataTypedata; structNode*next; }LinkList; linklist*search(linklist*x,linklist*y) {linklist*p,*q; p=x;q=y; while(p&&q) {if(p->data! =q->data)q=q->next; else{p=p->next;q=y;} }returnp;} 2.10已知递增有序的两个单链表A和B各存储了一个集合。 设计算法实现求两个集合的交集运算C=A∩B。 typedefintDataType; typedefstructNode {DataTypedata; structNode*next; }LinkList; LinkList*union(LinkList*A,LinkList*B) {LinkList*C,*p,*q,*s*r; p=A->next;q=B->next; C=A;r=C; while(p&&q) {if(p->data==q->data) {r->next=p;r=p; p=p->next; q=q->next; } elseif(p->data elseq=q->next; } r->next=NULL; free(B);returnC; } 2.11已知递增有序的两个单链表A和B,编写算法将A、B归并成一个递增有序的单链表C。 typedefintDataType; typedefstructNode {DataTypedata; structNode*next; }LinkList; LinkList*union(LinkList*A,LinkList*B) {LinkList*C,*p,*q,*s*r; p=A->next;q=B->next; C=A;r=C; while(p&&q) {if(p->data<=q->data) {s=p;p=p->next;} else {s=q;q=q->next;} r->next=s;r=s; } if(! q)r->next=q; elser->next=p; free(B); returnC; } 3栈和队列 3.1回答下列概念: 栈,队列,顺序栈,链队列 栈: 栈(Stack)是运算受限的线性表,限制它的插入和删除操作仅在表的一端进行。 队列: 只允许在表的一端进行插入,而在表的另一端进行删除,将这种线性表称为队或队列(Queue)。 顺序栈: 采用顺序方式存储的栈称为顺序栈(SequentialStack)。 链队列: 采用链接方法存储的队列称为链队列(LinkedQueue)。 3.2栈和队列各有什么特点? 简述栈、队列和线性表的差别。 栈(Stack)是运算受限的线性表,限制它的插入和删除操作仅在表的一端进行,又称为后进先出的线性表(LastInFirstOut),简称LIFO表。 只允许在表的一端进行插入,而在表的另一端进行删除,将这种线性表称为队或队列(Queue),又叫先进先出的线性表,简称为FIFO(FirstInFirstOut)表。 这三种结构有很多的相似之处,其差别主要体现在运算上,具有不同的运算特点。 同线性表的运算相比,栈和队列在操做上受到限制。 线性表可以在元素序列的任何位置上进行插入、删除操作,查找运算往往是线性表上使用频率最高的操作。 查找、插入、删除的时间复杂度一般为O(n)。 栈和队列的插入和删除运算都限制在线性表的表端完成,在栈和队列上不需要查找运算。 栈和队列的插入及删除运算时间复杂度都可以为O (1)。 3.3设有编号为1,2,3,4的四辆车,顺序进入一个栈式结构的站台,试写出这四辆车开出车站的所有可能的顺序。 1234213432144321 124321433241 132423143421 13422341 14322431 3.4若数列1、2、3、4、5、6顺序进栈,假设P表示入栈操作,S表示出栈操作,例如: 操作序列PSPSPSPSPSPS,可得到出栈序列为: 123456。 依此类推,请回答: (1)能否得到出栈序列325641? 若能,请写出对应的操作序列。 (2)能否得到出栈序列154623? 若能,请写出对应的操作序列。 (3)对应操作序列: PPSSPPSPSPSS,得到的出栈序列是什么? (4)对应操作序列: PPPPSPSSPSSS,得到的出栈序列是什么? (5)从上面的结果中你能总结出什么结论? (1)能得到325641。 在123依次进栈后,3和2出栈,得部分输出序列32;然后4,5入栈,5出栈,得部分出栈序列325;6入栈并出栈,得部分输出序列3256;最后退栈,直到栈空。 得输出序列325641。 其操作序列为PPPSSPPSPSSS。 (2)不能得到输出顺序为154623的序列。 部分合法操作序列为ADAAAADDAD,得到部分输出序列1546后,栈中元素为23,3在栈顶,故不可能2先出栈,得不到输出序列154623。 (3)214563 (4)453621 (5)借助栈由输入序列12……n得到输出序列p1p2……pn,则在输出序列中不可能存在这样的情形: 存在着i 即序列中大的数出栈后,比它小的数只能由大到小出栈(中间可以插入编号更大的数)。 3.5对于循环顺序队列,判断队空、队满的条件是什么? 写出求队列长度的公式。 判断队空的条件是: sq->front=sq->rear 判断队满的条件是: (sq->rear+1)%MAXSIZE==sq->front 求队列长度的公式为: m=(sq->rear-sq->front+MAXSIZE)%MAXSIZE; 3.6通常称正读和反读都相同的字符序列为“回文”,例如,“abcdeedcba”、“abcdcba”是回文。 若字符序列存储在一个单链表中,编写算法判断此字符序列是否为回文。 (提示: 将一半字符先依次进栈) #definemaxsize100 typedefchardatatype1; typedefstruct {datatype1data[maxsize]; inttop; }seqstack; typedefintdatatype; typedefstructnode {datatypedata; structnode*next; }Linklist; Duichen(Linklist*head) {inti=1; Linklist*p; seqstack*s; s=initSeqStack(); p=head->next;n=0; while(p){n++;p=p->next;} p=head->next; while(i<=n/2) {push(s,p->data);i++;} if(n%2! =0)p=p->next; while(p&&p->data==pop(s)) p=p->next; if(p)return0elsereturn1; } 3.7两个栈共享数组a[m]空间,栈底分别设在两端,此时栈空、栈满的条件是什么? 试写出两个栈公用的算法: Top(i),Push(i,x)和Pop(i),其中i为栈的序号0或1。 #definem100 typedefchardatatype; typedefstructnode {datatypea[m]; inttop0,top1; }seqstack; Seqstackss,*s=&ss; intpush(inti,datatypex) {if(s->top1==s->top0+1){printf(“full”);return0;} if(i==0){s->top0++;s->a[s->top0]=x;} else{s->top1--;s->a[s->top1]=x;} return1; } datatypepop(inti) {if(i==0) {if(s->top0==-1){printf(“empty”);return0;} s->top0--; returns->a[s->top0+1]; } else{if(s->top1==m){printf(“empty”);return0;} s->top1++; returns->a[s->top1-1]; } } datatypetop(inti) {if(i==0) {if(s->top0==-1){printf(“empty”);return0;} returns->a[s->top0]; } else{if(s->top1==m){printf(“empty”);return0;} returns->a[s->top1]; } } 3.8假设以数组a[m]存放循环队列的元素,同时设变量rear和length分别作为队尾指针和队中元素个数,试给出判别此循环队列的队满条件,并写出相应入队和出队的算法(在出队的算法中要返回队头元素)。 #definem100 intenqueue(inta[],intrear,intlength,intx) {if(length==m) {printf(“queueisfull”);return0;} rear=(rear+1)%m; a[rear]=x; length++; returnlength; } intdequeue(inta[],intrear,intlength,int*x) {if(length==0) {printf(“queueempty”);return0;} *x=a[(rear-length+m)%m]; length--; returnlength; 4多维数组及广义表 4.1回答下列概念: 三元组表、广义表、十字链表 三元组表: 稀疏矩阵中的非零元素三元组组成的线性表。 广义表: 也称为列表(Lists)是n(n≥0)个元素a1,a2,…,ai,…,an的有限序列, 元素ai可以是原子或者是子表(子表亦是广义表)。 十字链表: 稀疏矩阵(即三元组表)的一种链接存储结构。 稀疏矩阵中每个非零元素都用 一个包含五个域的结点来表示,存储非零元素所在行的行号域i,存储非零元素 所在列的列号域j,存储非零元素值的值域v,以及行指针域right和列指针域 down,分别指向同一行中的下一个非零元素结点和同一列中的下一个非零元素 结点。 4.2二维数组在采用顺序存储时,元素的排列方式有哪两种? 行优先和列优先。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 实用教程 习题 答案