数据结构(C语言版)课后习题答案 下载本文

(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++) // 输出数字字符的个数

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

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

[算法描述]

void InvertStore(char A[]) //字符串逆序存储的递归算法。 {char ch;

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

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

XXIX

cout<<“数字”<

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

}

{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参数位置非法”<

if(*p == '/0') { cout<

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中。

[算法描述]

XXX

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

//将字符串s1拆分成字符串s2和字符串s3,要求字符串s2是长n且两端对齐 {char *p=s1, *q=s2; int i=0;

}

(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

{for(p=j+1;p

if(a[i][j]==a[i][p]) {cout<<“no”; return(0); } //只要有一个相同的,就结论不是互不相同

XXXI

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

if(*p== '\\0') {cout<<\字符串s1为空串或空格串\} while( *p!='\\0' && i

if(*p =='\\0'){cout<<\字符串s1没有\个有效字符\if(*(--q)==' ' ) //若最后一个字符为空格,则需向后找到第一个非空格字符 {p-- ; //p指针也后退

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

{cout<<\串没有\个两端对齐的字符串\ *q=*p; //字符串s2最后一个非空字符 *(++q)='\\0'; //置s2字符串结束标记 }

*q=s3;p++; //将s1串其余部分送字符串s3。 while (*p!= '\\0') {*q=*p; q++; p++;} *q='\\0'; //置串s3结束标记

for(k=i+1;k

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

}// for(j=0;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(n)。

(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

{while(i0) i++; while(i

if(i

}// while(i

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

XXXII

4