数据结构第4章课后习题答案

简介: 数据结构第4章课后习题答案

1选择题

(1)串是一种特殊的线性表,其特殊性体现在(  )。

 A可以顺序存储               B数据元素是一个字符    

C可以链式存储               D数据元素可以是多个字符若

答案:B

(2)串下面关于串的的叙述中,(  )是不正确的?

A.串是字符的有限序列         B.空串是由空格构成的串

C.模式匹配是串的一种重要运算  D.串既可以采用顺序存储,也可以采用链式存储

答案:B

解释:空格常常是串的字符集合中的一个元素,有一个或多个空格组成的串成为空格串,零个字符的串成为空串,其长度为零。

(3)串“ababaaababaa”的next数组为(  )。

A.012345678999   B.012121111212  C011234223456    D.0123012322345

答案:C

(4)串“ababaabab”的nextval为(  )。

A010104101      B.010102101      C.010100011       D.010101011

答案:A

(5)串的长度是指(  )。

A.串中所含不同字母的个数       B.串中所含字符的个数

C.串中所含不同字符的个数       D.串中所含非空格字符的个数

答案:B

解释:串中字符的数目称为串的长度。

(6)假设以行序为主序存储二维数组A=array[1..100,1..100],设每个数据元素占2个存储单元,基地址为10,则LOC[5,5]=(  )。

A.808            B818            C.1010             D.1020

答案:B

解释:以行序为主,则LOC[5,5]=[5-1*100+5-1]*2+10=818

(7)设有数组A[i,j],数组的每个元素长度为3字节,i的值为1到8,j的值为1到10,数组从内存首地址BA开始顺序存放,当用以列为主存放时,元素A[5,8]的存储首地址为(  )。

A.BA+141        BBA+180         C.BA+222         D.BA+225

答案:B

解释:以列序为主,则LOC[5,8]=[8-1*8+5-1]*3+BA=BA+180

(8)设有一个10阶的对称矩阵A,采用压缩存储方式,以行序为主存储,a11为第一元素,其存储地址为1,每个元素占一个地址空间,则a85的地址为(  )。

A.13             B.32             C33               D.40

答案:C

(9)若对n阶对称矩阵A以行序为主序方式将其下三角形的元素(包括主对角线上所有元素)依次存放于一维数组B[1..(n(n+1))/2]中,则在B中确定aij(i<j)的位置k的关系为(  )。

A.i*(i-1)/2+j      Bj*(j-1)/2+i     C.i*(i+1)/2+j      D.j*(j+1)/2+i

答案:B

(10)二维数组A的每个元素是由10个字符组成的串,其行下标i=0,1,…,8,列下标j=1,2,…,10。若A按行先存储,元素A[8,5]的起始地址与当A按列先存储时的元素(    )的起始地址相同。设每个字符占一个字节。

A.A[8,5]         B.A[3,10]         C. A[5,8]          D.A[0,9]

答案:B

解释:设数组从内存首地址M开始顺序存放,若数组按行先存储,元素A[8,5]的起始地址为:M+[(8-0)*10+(5-1)]*1=M+84;若数组按列先存储,易计算出元素A[3,10]的起始地址为:M+[(10-1)*9+(3-0)]*1=M+84。故选B。

(11)设二维数组A[1.. m,1.. n](即m行n列)按行存储在数组B[1.. m*n]中,则二维数组元素A[i,j]在一维数组B中的下标为(  )。

A(i-1)*n+j       B.(i-1)*n+j-1      C.i*(j-1)         D.j*m+i-1

答案:A

解释:特殊值法。取i=j=1,易知A[1,1]的的下标为1,四个选项中仅有A选项能确定的值为1,故选A

(12)数组A[0..4,-1..-3,5..7]中含有元素的个数(  )。

A.55            B45            C.36            D.16

答案:B

解释:共有5*3*3=45个元素。

(13)广义表A=(a,b,(c,d),(e,(f,g))),则Head(Tail(Head(Tail(Tail(A)))))的值为(  )。

A.(g)            B.(d)             C.c            Dd

答案:D

解释:Tail(A)=(b,(c,d),(e,(f,g)))Tail(Tail(A))=( (c,d),(e,(f,g))) Head(Tail(Tail(A)))= (c,d)Tail(Head(Tail(Tail(A))))=(d)Head(Tail(Head(Tail(Tail(A)))))=d

(14)广义表((a,b,c,d))的表头是(  ),表尾是(  )。

A.a              B.( )             C(a,b,c,d)      D.(b,c,d)

答案:CB

解释:表头为非空广义表的第一个元素,可以是一个单原子,也可以是一个子表,((a,b,c,d))的表头为一个子表(a,b,c,d);表尾为除去表头之外,由其余元素构成的表,表为一定是个广义表,((a,b,c,d))的表尾为空表( )

(15)设广义表L=((a,b,c)),则L的长度和深度分别为(  )。

A.1和1          B.1和3         C12         D.2和3

答案:C

解释:广义表的深度是指广义表中展开后所含括号的层数,广义表的长度是指广义表中所含元素的个数。根据定义易知L的长度为1,深度为2

2.应用题

(1)已知模式串t=‘abcaabbabcab’写出用KMP法求得的每个字符对应的next和nextval函数值。

答案:

模式串t的next和nextval值如下:

j

1  2  3  4  5  6  7  8  9  10 11 12

t

a  b  c  a  a  b  b  a  b   c  a  b

next[j]

0  1  1  1  2  2  3  1  2  3  4  5

nextval[j]

0  1  1  0  2  1  3  0  1  1  0  5

(2)设目标为t=“abcaabbabcabaacbacba”,模式为p=“abcabaa”

① 计算模式p的naxtval函数值;

② 不写出算法,只画出利用KMP算法进行模式匹配时每一趟的匹配过程。

答案:

p的nextval函数值为0110132。(p的next函数值为0111232)。

利用KMP(改进的nextval)算法,每趟匹配过程如下:

 第一趟匹配: abcaabbabcabaacbacba

              abcab(i=5,j=5)

 第二趟匹配: abcaabbabcabaacbacba

                  abc(i=7,j=3)

 第三趟匹配: abcaabbabcabaacbacba

                    a(i=7,j=1)

 第四趟匹配: abcaabbabcabaac bacba

  (成功)             abcabaa(i=15,j=8)

(3)数组A中,每个元素A[i,j]的长度均为32个二进位,行下标从-1到9,列下标从1到11,从首地址S开始连续存放主存储器中,主存储器字长为16位。求:

① 存放该数组所需多少单元?

② 存放数组第4列所有元素至少需多少单元?

③ 数组按行存放时,元素A[7,4]的起始地址是多少?

④ 数组按列存放时,元素A[4,7]的起始地址是多少?

答案:

每个元素32个二进制位,主存字长16位,故每个元素占2个字长,行下标可平移至1到11。

(1)242   (2)22   (3)s+182   (4)s+142

(4)请将香蕉banana用工具 H( )—Head( ),T( )—Tail( )从L中取出。

L=(apple,(orange,(strawberry,(banana)),peach),pear)

答案:H(H(T(H(T(H(T(L)))))))

3.算法设计题

(1)写一个算法统计在输入字符串中各个不同字符出现的频度并将结果存入文件(字符串中的合法字符为A-Z这26个字母和0-9这10个数字)。

[题目分析]由于字母共26个,加上数字符号10个共36个,所以设一长36的整型数组,前10个分量存放数字字符出现的次数,余下存放字母出现的次数。从字符串中读出数字字符时,字符的ASCII代码值减去数字字符 ‘0’的ASCII代码值,得出其数值(0..9),字母的ASCII代码值减去字符‘A’的ASCII代码值加上10,存入其数组的对应下标分量中。遇其它符号不作处理,直至输入字符串结束。

[算法描述]

void Count()

//统计输入字符串中数字字符和字母字符的个数。

{int i,num[36];

char ch

 for(i=0;i<36;i++)num[i]=0;// 初始化

 while((ch=getchar())!=‘#’)  //‘#’表示输入字符串结束。

   if(‘0’<=ch<=‘9’){i=ch-48;num[i]++;}        // 数字字符

    else if(‘A’<=ch<=‘Z’){i=ch-65+10;num[i]++;}// 字母字符

 for(i=0;i<10;i++)  // 输出数字字符的个数

   cout<<“数字”<<i<< “的个数=”<<num[i]<<endl;

 for(i=10;i<36;i++)// 求出字母字符的个数

   cout<<“字母字符”<<i+55<< “的个数=”<<num[i]<<endl;

(2)写一个递归算法来实现字符串逆序存储,要求不另设串存储空间。

[题目分析]实现字符串的逆置并不难,但本题“要求不另设串存储空间”来实现字符串逆序存储,即第一个输入的字符最后存储,最后输入的字符先存储,使用递归可容易做到。

[算法描述]

void InvertStore(char A[])

//字符串逆序存储的递归算法。

{char ch;

static int i = 0;//需要使用静态变量

cin>>ch;

if (ch!= '.')    //规定'.'是字符串输入结束标志

  {InvertStore(A);

   A[i++] = ch;//字符串逆序存储

  }

A[i] = '\0';  //字符串结尾标记

}

(3)编写算法,实现下面函数的功能。函数void insert(char*s,char*t,int pos)将字符串t插入到字符串s中,插入位置为pos。假设分配给字符串s的空间足够让字符串t插入。(说明:不得使用任何库函数)

[题目分析]本题是字符串的插入问题,要求在字符串s的pos位置,插入字符串t。首先应查找字符串s的pos位置,将第pos个字符到字符串s尾的子串向后移动字符串t的长度,然后将字符串t复制到字符串s的第pos位置后。

对插入位置pos要验证其合法性,小于1或大于串s的长度均为非法,因题目假设给字符串s的空间足够大,故对插入不必判溢出。

[算法描述]

void  insert(char *s,char *t,int pos)

//将字符串t插入字符串s的第pos个位置。

{int i=1,x=0;  char *p=s,*q=t;  //p,q分别为字符串s和t的工作指针

if(pos<1) {cout<<“pos参数位置非法”<<endl;exit(0);}

while(*p!=’\0’&&i<pos) {p++;i++;} //查pos位置

//若pos小于串s长度,则查到pos位置时,i=pos。

if(*p == '/0') { cout<<pos<<"位置大于字符串s的长度";exit(0);}

else      //查找字符串的尾

  while(*p!= '/0') {p++; i++;}  //查到尾时,i为字符‘\0’的下标,p也指向‘\0’。

while(*q!= '\0') {q++; x++; }   //查找字符串t的长度x,循环结束时q指向'\0'。

for(j=i;j>=pos ;j--){*(p+x)=*p; p--;}//串s的pos后的子串右移,空出串t的位置。

q--;  //指针q回退到串t的最后一个字符

for(j=1;j<=x;j++) *p--=*q--;  //将t串插入到s的pos位置上

[算法讨论] 串s的结束标记('\0')也后移了,而串t的结尾标记不应插入到s中。

(4)已知字符串S1中存放一段英文,写出算法format(s1,s2,s3,n),将其按给定的长度n格式化成两端对齐的字符串S2, 其多余的字符送S3。

[题目分析]本题要求字符串s1拆分成字符串s2和字符串s3,要求字符串s2“按给定长度n格式化成两端对齐的字符串”,即长度为n且首尾字符不得为空格字符。算法从左到右扫描字符串s1,找到第一个非空格字符,计数到n,第n个拷入字符串s2的字符不得为空格,然后将余下字符复制到字符串s3中。

[算法描述]

void format (char *s1,*s2,*s3)

//将字符串s1拆分成字符串s2和字符串s3,要求字符串s2是长n且两端对齐

{char *p=s1, *q=s2;

int i=0;

  while(*p!= '\0' && *p== ' ') p++;//滤掉s1左端空格

  if(*p== '\0') {cout<<"字符串s1为空串或空格串"<<endl;exit(0);  }

  while( *p!='\0' && i<n){*q=*p; q++; p++; i++;}

//字符串s1向字符串s2中复制

  if(*p =='\0'){cout<<"字符串s1没有"<<n<<"个有效字符"<<endl; exit(0);}

  if(*(--q)==' ' ) //若最后一个字符为空格,则需向后找到第一个非空格字符

   {p-- ;          //p指针也后退

    while(*p==' '&&*p!='\0') p++;//往后查找一个非空格字符作串s2的尾字符

    if(*p=='\0')

{cout<<"s1串没有"<<n<<"个两端对齐的字符串"<<endl; exit(0);}

       *q=*p;         //字符串s2最后一个非空字符

    *(++q)='\0';   //置s2字符串结束标记

    }

  *q=s3;p++;      //将s1串其余部分送字符串s3。

  while (*p!= '\0') {*q=*p; q++; p++;}

  *q='\0';        //置串s3结束标记

}

(5)设二维数组a[1..m, 1..n] 含有m*n 个整数。

① 写一个算法判断a中所有元素是否互不相同?输出相关信息(yes/no);

② 试分析算法的时间复杂度。

[题目分析]判断二维数组中元素是否互不相同,只有逐个比较,找到一对相等的元素,就可结论为不是互不相同。如何达到每个元素同其它元素比较一次且只一次?在当前行,每个元素要同本行后面的元素比较一次(下面第一个循环控制变量p的for循环),然后同第i+1行及以后各行元素比较一次,这就是循环控制变量k和p的二层for循环。

[算法描述]

int JudgEqual(ing a[m][n],int m,n)

//判断二维数组中所有元素是否互不相同,如是,返回1;否则,返回0。

{for(i=0;i<m;i++)

 for(j=0;j<n-1;j++)

  {for(p=j+1;p<n;p++) //和同行其它元素比较

    if(a[i][j]==a[i][p]) {cout<<“no”; return(0); }

    //只要有一个相同的,就结论不是互不相同

    for(k=i+1;k<m;k++)  //和第i+1行及以后元素比较

     for(p=0;p<n;p++)

      if(a[i][j]==a[k][p]) { cout<<“no”; return(0); }            

}// for(j=0;j<n-1;j++)

cout<<“yes”; return(1);   //元素互不相同

}//算法JudgEqual结束

二维数组中的每一个元素同其它元素都比较一次,数组中共m*n个元素,第1个元素同其它m*n-1个元素比较,第2个元素同其它m*n-2 个元素比较,……,第m*n-1个元素同最后一个元素(m*n)比较一次,所以在元素互不相等时总的比较次数为 (m*n-1)+(m*n-2)+…+2+1=(m*n)(m*n-1)/2。在有相同元素时,可能第一次比较就相同,也可能最后一次比较时相同,设在(m*n-1)个位置上均可能相同,这时的平均比较次数约为(m*n)(m*n-1)/4,总的时间复杂度是O(n4)

(6)设任意n个整数存放于数组A(1:n)中,试编写算法,将所有正数排在所有负数前面(要求算法复杂度为0(n))。

[题目分析]本题属于排序问题,只是排出正负,不排出大小。可在数组首尾设两个指针i和j,i自小至大搜索到负数停止,j自大至小搜索到正数停止。然后i和j所指数据交换,继续以上过程,直到 i=j为止。

[算法描述]

void Arrange(int A[],int n)

//n个整数存于数组A中,本算法将数组中所有正数排在所有负数的前面

{int i=0,j=n-1,x;  //用类C编写,数组下标从0开始

 while(i<j)

{while(i<j && A[i]>0)  i++;

while(i<j && A[j]<0)  j--;

  if(i<j) {x=A[i]; A[i++]=A[j]; A[j--]=x; }//交换A[i] 与A[j]

}// while(i<j)

}//算法Arrange结束.

[算法讨论]对数组中元素各比较一次,比较次数为n。最佳情况(已排好,正数在前,负数在后)不发生交换,最差情况(负数均在正数前面)发生n/2次交换。用类c编写,数组界偶是0..n-1。空间复杂度为O(1).

目录
相关文章
|
1月前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
142 77
|
1月前
|
存储 C++
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
【数据结构——树】哈夫曼树(头歌实践教学平台习题)【合集】目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果:任务描述 本关任务:编写一个程序构建哈夫曼树和生成哈夫曼编码。 相关知识 为了完成本关任务,你需要掌握: 1.如何构建哈夫曼树, 2.如何生成哈夫曼编码。 测试说明 平台会对你编写的代码进行测试: 测试输入: 1192677541518462450242195190181174157138124123 (用户分别输入所列单词的频度) 预
61 14
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
|
1月前
|
存储 C++ 索引
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
【数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】初始化队列、销毁队列、判断队列是否为空、进队列、出队列等。本关任务:编写一个程序实现环形队列的基本运算。(6)出队列序列:yzopq2*(5)依次进队列元素:opq2*(6)出队列序列:bcdef。(2)依次进队列元素:abc。(5)依次进队列元素:def。(2)依次进队列元素:xyz。开始你的任务吧,祝你成功!(4)出队一个元素a。(4)出队一个元素x。
44 13
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
|
1月前
|
算法 C++
【C++数据结构——查找】二叉排序树(头歌实践教学平台习题)【合集】
【数据结构——查找】二叉排序树(头歌实践教学平台习题)【合集】 目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果: 任务描述 本关任务:实现二叉排序树的基本算法。 相关知识 为了完成本关任务,你需要掌握:二叉树的创建、查找和删除算法。具体如下: (1)由关键字序列(4,9,0,1,8,6,3,5,2,7)创建一棵二叉排序树bt并以括号表示法输出。 (2)判断bt是否为一棵二叉排序树。 (3)采用递归方法查找关键字为6的结点,并输出其查找路径。 (4)分别删除bt中关键
53 11
【C++数据结构——查找】二叉排序树(头歌实践教学平台习题)【合集】
|
1月前
|
存储 人工智能 算法
【C++数据结构——图】最短路径(头歌教学实验平台习题) 【合集】
任务描述 本关任务:编写一个程序,利用Dijkstra算法,实现带权有向图的最短路径。 相关知识 为了完成本关任务,你需要掌握:Dijkst本关任务:编写一个程序,利用Dijkstra算法,实现带权有向图的最短路径。为了完成本关任务,你需要掌握:Dijkstra算法。带权有向图:该图对应的二维数组如下所示:Dijkstra算法:Dijkstra算法是指给定一个带权有向图G与源点v,求从v到G中其他顶点的最短路径。Dijkstra算法的具体步骤如下:(1)初始时,S只包含源点,即S={v},v的距离为0。
61 15
|
1月前
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
48 12
|
1月前
|
C++
【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
46 10
|
1月前
|
算法 C++
【C++数据结构——图】最小生成树(头歌实践教学平台习题) 【合集】
【数据结构——图】最小生成树(头歌实践教学平台习题)目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果:【合集】任务描述 本关任务:编写一个程序求图的最小生成树。相关知识 为了完成本关任务,你需要掌握:1.建立邻接矩阵,2.Prim算法。建立邻接矩阵 上述带权无向图对应的二维数组,根据它建立邻接矩阵,如图1建立下列邻接矩阵。注意:INF表示无穷大,表示整数:32767 intA[MAXV][MAXV];Prim算法 普里姆(Prim)算法是一种构造性算法,从候选边中挑
44 10
|
1月前
|
存储 算法 C++
【C++数据结构——图】图的邻接矩阵和邻接表的存储(头歌实践教学平台习题)【合集】
本任务要求编写程序实现图的邻接矩阵和邻接表的存储。需掌握带权有向图、图的邻接矩阵及邻接表的概念。邻接矩阵用于表示顶点间的连接关系,邻接表则通过链表结构存储图信息。测试输入为图的顶点数、边数及邻接矩阵,预期输出为Prim算法求解结果。通关代码提供了完整的C++实现,包括输入、构建和打印邻接矩阵与邻接表的功能。
49 10
|
1月前
|
C++
【C++数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】
【数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】(1)遇到左括号:进栈Push()(2)遇到右括号:若栈顶元素为左括号,则出栈Pop();否则返回false。(3)当遍历表达式结束,且栈为空时,则返回true,否则返回false。本关任务:编写一个程序利用栈判断左、右圆括号是否配对。为了完成本关任务,你需要掌握:栈对括号的处理。(1)遇到左括号:进栈Push()开始你的任务吧,祝你成功!测试输入:(()))
38 7

热门文章

最新文章