第四章 字符串、数组和特殊矩阵

例题1:编写下列算法(假定下面所用的串均采用顺序存储方式,参数ch、ch1和ch2均为字符型):

  • 将串r中所有其值为ch1的字符换成ch2的字符。
  • 将串r中所有字符按照相反的次序仍存放在r中。
  • 从串r中删除其值等于ch的所有字符。
  • 从串r1中第index个字符起求出首次与字符r2相同的子串的起始位置。
  • 从串r中删除所有与串r3相同的子串(允许调用第(4)小题的函数和第(3)小题的删除子串的函数)。

解:(1)本小题的算法思想是:从头到尾扫描r串,对于值为ch1的元素直接替换成ch2即可。其函数如下:

orderstring *trans(r,ch1,ch2)

orderstring *r;

char ch1,ch2;

{

int i;

for(i=0;i<r->len; i++)

if(r->vec[ i ]==ch1)r->vec[ i ]=ch2;

return(r);

}

(2)本小题的算法思想是:将第一个元素与最后一个元素交换,第二个元素与倒数第二个元素交换,如此下去,便将该串的所有字符反序了。其函数如下:

orderstring *invert(r)

orderstring *r;

{

int i;

char x;

for(i=0;i< ( r->len / 2 ); i++)

{

x= r->vec[ i ];

r->vec[ i ]= r->vec[r->len-i-1];

r->vec[ r->len-i-1 ]=x;

}

return ( r );

}

(3)本小题的算法思想是:从头到尾扫描r串,对于其值为ch的元素采用移动的方式进行删除。其函数如下:

orderstring *delall(r,ch)

orderstring *r;

char ch;

{

int i,j;

for(i=0;i<r->len; i++)

if(r->vec[ i ]==ch)

{

for(j=i;j<r->len-1; j++)

r->vec[ j ]=r->vec[ j+1 ];

i--;

r->len--;

}

return(r);

}

(4)本小题的算法思想是:从第index个元素开始扫描r1,当其元素值与r2的第一个元素的值相同时,判定它们之后的元素值是否依次相同,直到r2结束为止,若都相同则返回,否则继续上述过程直到r1扫描完为止。其函数如下:

int partposition(r2,r1,index)

orderstring *r2,*r1;

int index;

{

int i,j,k;

for(i=index;i<r2->len; i++)

for(j=i,k=0;r2->vec[ j ]== r1->vec[ k ]; j++, k++)

if(!r1->vec[ k+1 ])

return(i);

return(-1);

}

(5)本小题的算法思想是:从位置1开始调用第(4)小题的函数partposition( ),若找到了一个相同子串,则调用delsubstring( )将其删除,再查找后面位置的相同子串,方法与以上相同。其函数如下:

orderstring *delstringall(r,r3)

orderstring *r,*r3;

{

int i=0,k;

while(i<r->len)/*当调用delsubstring( )进行删除操作时, r->len也减小了*/

{

if((k=partposition(r, r3, i)!=-1))

r=delsubstring(r,k+1,r3->len);

else

i++;

}

return r;

}

例题2:采用顺序存储方式存储串,编写一个函数将串s1中的第i个字符到第j个字符之间的字符(不包括第i个和第j个字符)用s2串替换,函数名为stuff(s1,i,j,s2)。例如:stuff(’abcd’, 1, 3, ’xyz’)返回’axyzcd’。

解:本题算法思想是:先提取s1的前i个字符str1,再取第j个字符及之后的所有字符str2,最后将str1,s2,str2连接起来便构成了结果串,其函数如下:

orderstring *stuff(s1,i,j,s2)

orderstring *s1,*s2;

int i,j;

{

orderstring *s;

int top,h;

s=(orderstring *)malloc(sizeof(orderstring));

if(i<=j && i<s1->len && j<s1->len)

{

for(h=0;h<i;h++)s->vec[h]=s1->vec[h];/*把s1的前i个字符赋给s*/

s->len=i;

h=0;

while(h<s2->len)

{

s->vec[s->len+h]=s2->vec[h];

h++;

}

s->len=s->len+s2->len;

s->vec[s->len]=’\0’;

top=s->len;

for(top=s->len, h=j-1; h<s1->len; h++, top++)

s->vec[top]=s1->vec[h];/*连接s1的第i个字符及之后的字符*/

s->len=top;

s->vec[s->len]=’\0’;

}

return(s);

}

例题3:建立三元组存储方法

解:输入一个稀疏矩阵A建立三元组存储方法的函数如下:

void crt_matrix(A,B)

int A[m][n];

smatrik B;/*A是一个稀疏矩阵,B是产生的相对应的三元组*/

{

int i,j,k=1;

for(i=0;i<n;i++)/*按行优先顺序扫描A的元素,不为0者存入B中*/

for(j=0;j<m;j++)

if(A[ i ][ j ]!=0)

{

B[k][0]= i;

B[k][1]= j;

B[k][2]= A[ i ][ j ];

k++;

}

B[0][0]= m;

B[0][1]= n;

B[0][2]= k-1;/*存入非0元素个数*/

}

例题4:假设稀疏矩阵A采用三元组表示,编写一个函数计算其转置矩阵B,要求B也采用三元组表示。

解:三元组表示中要求按行的顺序存放,所有转置过程不能直接将行下标和列下标转换,还必须使得列按顺序存放。因此在A中首先找出第一列中的所有元素,它们是转置矩阵第一行的非0元素,并把它们依次放在转置矩阵三元组数组B中;然后依次找出第二列中的所有元素,把它们依次放在数组B中;按照同样的方法逐列进行,直到找出第n列的所有元素,并把它们依次放在数组B中。实现本题功能的函数如下:

void transpose(A,B)

smatrik A,B; /*A是稀疏矩阵的三元组形式,B是存放A的转置矩阵的三元组数组*/

{

int m,n,p,q,t,col;

/*m为A中的行数; n为A中的列数; t为A中非0元素个数*/

/*q为B的下一项位置; p为A的当前项*/

m=A[0][0];n=A[0][1];t=A[0][2];

B[0][0]=n;B[0][1]=m;B[0][2]=t;/*产生第0行的结果*/

If(t>0)/*非0 矩阵才做转置*/

{

q=1;

for(col=0;col<n;col++)/*按列转置*/

for(p=1;p<=t;p++)

if(A[p][1]==col)

{

B[q][0]=A[p][1];

B[q][1]=A[p][0];

B[q][2]=A[p][2];

q++;

}

}

}

例题5:设二维数组A5*6的每个元素占4个字节,已知Loc(a00)=1000,A共占多少个字节?A的终端结点a45的起始地址为多少?按行和按列优先存储时,a25的起始地址分别为多少?

解:A共占的字节数为:5*6*4=120

a45的起始地址为:Loc(a00)+(4*6+5)*4 =1000+116=1116

按行优先存储时,a25的起始地址为:Loc(a00)+(2*6+5)*4=1000+68=1068

按列优先存储时,a25的起始地址为:Loc(a00)+(5*5+2)*4=1000+108=10108

版权所有:江西师范大学计算机信息工程学院  管理入口