数据结构张铭测验Word文档格式.docx
《数据结构张铭测验Word文档格式.docx》由会员分享,可在线阅读,更多相关《数据结构张铭测验Word文档格式.docx(62页珍藏版)》请在冰豆网上搜索。
![数据结构张铭测验Word文档格式.docx](https://file1.bdocx.com/fileroot1/2023-1/29/3eb10c96-507e-4a0f-b2d8-e773c089a520/3eb10c96-507e-4a0f-b2d8-e773c089a5201.gif)
charstring[MAX_LENGTH];
strings*pNext;
}
如果有后续工作如反复增删结点,效率很高.并且可以使用不连续的空间。
操作过程相对复杂,容易出错.而且排序过程需要从表头开始沿链索一个结点一个结点的比较搜索,相当费时。
3.索引存储
是顺序存储的一种推广.使用一个字符串chardata[500],其中将大小长度不等的数据结点(单词)顺序存储其中.令使用一个字符指针数组char*index[n],存储一系列指针,每个指针指向存储区域的一个数据结点.
排序时,直接对index中的地址值进行调换修改即可,而不用修改data中的任何内容。
索引存储的优点是:
由于单词长度不同,在存储时充分考虑了这个因素,可以节省空间,此外由于交换的不是单词本身而是单词的地址,可以节省时间,从时空两方面得到了优化。
【排序结果】
B899,B9,CRSI,CXY,PAB,PABC,5C,7
2、解答:
本题没有指明这100个实数是否存在相等的情况,在这里,我们考虑存在多个最大值的情形(即100个实数可能有相等的),为了保存其位置,利用intpos[100](因为有可能这100个实数都是相同的)来保存最大值的所有位置。
1.用int类型的数组来保存这100个元素,没有注意题目中说的是“每个元素的值都是实数”。
2.求最大值的时候代码如下:
temp=0;
for(inti=0;
i<
100;
i++)
if(Num[i]>
temp)
temp=Num[i];
评注:
这样是错误的,例如:
当Num[i]都是负数的时候。
3.未考虑可能存在多个最大值的情况,只保存了一个最大值的位置。
本题可以采用的存储结构有顺序(数组),链表和索引。
本题最好使用数组存储结构。
由于其他存储方法需要记录附加信息,使得空间有效利用不能够最大化。
因此在空间上顺序存储是最优的。
时间上,无论如何此题都要遍历所有的数,因此O(n)为可能的最优时间代价。
加之此题的规模较小,因此使用大家最熟悉的顺序存储是较为优先的选择。
【算法描述】
1.由于最大值可能不止一个,甚至可能都是最大值,所以创建一个长度为100的整型数组pos[100],用来记录最大值的位置。
2.初始情况,取这个数组的第一个位置为最大值所在的位置,存入变量position中。
3.假设有n(1≤n≤99)个最大值,那么pos[0,1,2,…,n-1]记录这些最大值的位置,且pos[n]=-1(-1是标记值,表明pos数组下标为n-1及以前的元素记录了最大值的位置);
假设有n(n=100)个最大值,那么pos[0,1,2,…,n-1]记录这些最大值的位置,pos数组不再设-1的标记值。
具体源码如下:
#include<
iostream.h>
voidmain(){
//存放100个实数的数组
doubleNum[100]={4543.9,4543.9,3,45,654.7,7,66,35,45,4,6,4543.9,5,46,54,6,43,5.980,34};
//记录最大值所在位置的数组
intpos[100];
//初始设定数组的第1个元素为最大值
intposition=0;
//j指示位置数组pos的下标
intj=1;
for(inti=1;
++i)
Num[position]){
position=i;
//记下新的最大值的位置
j=1;
//位置数组pos的下标恢复为1,下标为0的位置为position预留
elseif(Num[i]==Num[position])
pos[j++]=i;
//记下重复最大值的位置
//位置数组pos的下标为0的位置为position预留
pos[0]=position;
//-1为标识值,表示位置数组pos下标为0,1,2…(j-1)的位置存
//放的是最大值所在的位置
if(j<
100)
pos[j]=-1;
cout<
<
"
最大值为:
Num[position]<
endl;
最大值所在的位置为:
for(i=0;
i<
++i){
if(pos[i]==-1)
//-1是标识值
break;
第"
(pos[i]+1)<
个元素"
3、解答:
【逻辑结构】
逻辑结构由结点集合K和关系集合R来表示,以学生每周的课程表为例:
将每天的课程安排数据作为结点,一共引入7个结点,它们的名称依次为“星期一”,“
星期二”,“星期三”,……,“星期日”。
全部结点组成结点集K。
这些结点是复合类型,是一个结构体,包括当日课程的名称,时间和地点等。
这些结点两两之间有一个时间关系r,r={(“星期一“,“星期二”),(“星期二”,“星期三”),(“星期三”,“星期四”),(“星期四”,“星期五”),(“星期五”,“星期六”),(“星期六”,“星期日”)。
此集合中的6个元素描述了“时间先后”关系r。
此外,还引入一个关系r*={“星期日”,“星期一”},r*只含有一个元素,以表示星期日和下一周工作日的时间顺序。
r和r*共同构成关系集R。
其中r属于线性结构。
R是一种环行的关系。
【存储结构】
几种可行的存储方案比较
1.顺序表:
见图一
优点:
逻辑清晰,查阅修改方便;
缺点:
需要占用整块的存储空间,对空间要求较大
星期
课次
一
二
三
四
五
六
日
1~2
课程名
上课地点
授课老师…
3~4
5~6
7~8
9~10
图一顺序表存储课程表
2.索引
图二索引结构的课程表
构造索引表,其中的指针分别指向每一天的课程
逻辑较清晰,不占用整块的存储空间,缺点:
算法较复杂,附加的空间代价较高(有索引表)
3.链表:
链接的方法是可以采纳的一个方法,每个指针都指向逻辑关系中的紧邻后继,最后一个结点的指针指向首结点,构成一个循环链表.链表结构检索较繁琐.
【相关运算】
常见的运算包括增、删、查、改运算,课程表的抽象数据类型可以定义如下:
template<
classELEM>
classtable
//当程序使用此table模板时,应该在前面附加#include<
table>
{
public:
//创建一张空课程表
table<
ELEM>
t;
//创建一张天数为k的课程表,可默认k为7
t(intk);
//设置某天的课程(时间地点等),该结点的地址可由索引表找出
virtualvoidSetcourse(ELEM&
pday)=0;
//把一个新的结点插入课程表,使该结点在表中位置是nPos如果nPos=-1
//则插入到表尾部(同时地址加入索引表)
virtualvoidAddday(constELEM*pday,intnPos=-1)=0;
//删除课程表中某天(结点),释放该结点的空间,该结点的地址可由索引表找出
virtualvoidRemoveday(ELEM&
//清空整个课程表,成功返回true
virtualboolClearall()=0;
//清空某天(结点)的所有内容,该结点的地址可由索引表找出,成功返回true
virtualboolClearday(ELEM&
pday)=0;
//修改某天(结点)的课程(时间地点等),该结点的地址可由索引表找出
virtualvoidChangecourse(ELEM&
//输出某天(结点)的课程内容,该结点的地址可由索引表找出
virtualvoidPrintday(ELEM&
pday)=0;
//输出所有课程内容(结点)
virtualvoidPrintList()=0;
//根据系统时间查询当天课程
virtualvoidCurrent()=0;
//统计课程总数
virtualintNumber()=0;
//析构函数,清空课程表
~table();
private:
ELEM*m_index;
//索引表头指针
}
第二章线性表、栈和队列练习
本章练习
1、(教材习题2.1)给出一个算法,求单链表X中,内容为a的结点地址。
2、(教材习题2.5)给出一个算法,求出循环表中结点的个数。
3、(教材习题2.8)编号为1,2,3,4的四辆列车,顺序开进一个栈式结构的站台;
问开出车站的顺序有多少种可能,请具体写出来。
4、(教材习题2.10)环状的队列,写出计算队列元素个数的程序。
5、(教材习题2.19)现有4个元素作为双端队列的输入,问可以得到多少种不同的排列?
参考答案
第二章线性表、栈和队列练习答案
本题没有指明是否存在多个内容为a的地址,在这里,我们考虑存在多个结点内容为a的情形。
没有考虑内容为a的地址可能有多个。
由于链表中内容为a的结点数目不确定,可以选择用一个新链表来存放找到的结点地址。
这样的存储结构
优于定长数组。
本题中涉及到两个链表:
原链表ListNode和用于存储结点地址的新链表ListAddress。
1.
设pfirst和qfirst分别是这两个链表的头指针,p,q为指针变量。
2.
p从链表X的表头开始向后移动,每当遇到原链表中内容为a的结点,就在新链表中增
加一个结点记录下其地址(用指针指向该结点来进行记录),如此循环直到链表X的表尾。
structListNode
//链表结点定义
ELEMdata;
//数据类型为ELEM
ListNode*plink;
//指向后继结点的指针
};
ListNode*pfirst;
//pfirst指向原链表第一个结点
ListNode*p;
//原链表的指针变量,程序运行时可对其所指结点进行各种运算
p=pfirst;
//指向头指针
StructListAddress
//用于存放地址的新链表
ListNode*address;
//存放地址,类型为指向链表X的结点的指针
ListAddress*qlink;
//新链表的指针变量
ListAddress*qfirst;
//qfirst指向新链表第一个结点
qfirst->
qlink=NULL;
//空表
ListAddress*q=qfirst;
voidfind(ELEMa)
//用于查找内容为a的结点,并记录其地址,参数为待查数据a
while(p!
=NULL)
//未到达链表尾结点
if(p->
data==a)
//找到符合条件的结点,插入新链表
q->
qlink=newListAddress;
//创建内存空间
qlink->
address=p;
//存储指向该结点的指针
q=q->
qlink;
//指针向后移
p=p->
plink;
//指针后移继续查找
}
判断已经遍历整个循环表的方法:
使用一个指针变量link从链表首元素向后遍历整个链表,直到link==first时,说明该结点即尾结点。
设空表时结点数count为0(此时first->
link=first),每经过一个结点count加1,直到到达尾结点。
structListNode
ListNode*link;
intLength(ListNode*first)
//first为循环表的头指针
p=first;
intcount=0;
//用于记录结点数,空链表时结点数为0
while(p->
link!
=first)
//未到达尾结点
link;
count++;
//结点数加1
returncount;
3、解答:
有14种可能:
【思路】
先进站的车可以先开,也可以后开。
只有一种情况不可能:
编号大的车开出后,比其编号小的车反序开出。
也即编号大的车开出后,编号比其小的车只能由大到小依次开出(中间可以插入编号更大的车,但此车后面的编号小的车也要遵守此规则)。
例如312的开出顺序是不可能的。
对所有车进行全排列共有24种出法。
但4开头的只能有一种:
4321。
所以少了3的全排列-1=5种。
三开头的时候,必须先2后1开出,先1后2时4的位置有三种:
3124、3142、3412,所以少了三种。
1或2开头的时候,后面的车如果是4,则最后两辆必须是3、2或3、1。
所以又少了1423、2413两种。
总共少了5+3+2=10种,有24-10=14种开出法。
下面用+表示进站,-表示出站:
1234:
1+
1-
2+
2-
3+
3-
4+
4-
1243:
4-
3-
1324:
1342:
2-
1432:
2134:
2143:
2314:
2341:
1-
2431:
3214:
3–
2–
1–
4-
3241:
3421:
4321:
1-
4、解答:
对于顺序队列
intQueue:
:
length_of_queue()
if(IsEmpty())return0;
if(front<
=rear)returnrear-front;
elsereturnmaxsize+rear-front;
对于链式队列
inttotal=0;
for(ListPtrtemp=front;
temp!
=rear;
temp=temp->
link)total++;
returntotal;
5、解答:
双端队列可以在队列的两端进行插入和删除操作,既可在队尾进行插入/删除,又可在队头进行插入/删除。
但第一个元素从左或右入队没有区别,以后每个元素都有两种入队方式。
即有2^3=8种方法。
不妨设元素为a,b,c,d,各种排列如下:
第一次放入a:
a
第二次放入b:
abba
第三次放入c:
cababccbabac
第四次放入d:
dcabcabddabcabcddcbacbaddbacbacd
故共有8种。
第三章字符串练习
1、(教材习题3.1)设有字符串变量StringA='
'
,B='
MULE'
,C='
OLD'
,D='
MY'
;
请计算下列表达式
(a)A+B
(b)B+A
(c)D+C+B
(d)B.substr(3,2)
(e)C.substr(1,1)
(f)A.str1ength()
(g)D.str1ength()
(h)B.Find('
L'
)
(i)C.FindLast('
D'
(j)D.insert(B,2)
(k)B.insert(B,1)
(1)B.remove(2,2)
(m)B.remove(0,5)
2、(教材习题3.2)计算下列字符串P的特征向量N[i]
(a)'
ABCDEFGH'
(b)'
IIIIIIII'
(c)'
BABBABAB'
注意串内字符间有空格隔开
3、设计算法用顺序结构存储的串s和串t的一个最长公共子串。
4、编写程序,统计在输入字符串中各个不同字符出现的频度并将结果存入文件(字符串中的合法字符为A-Z这26个字母和