- // func5-1.cpp 广义表的书写形式串为SString类型,包括算法5.8。bo5-5.cpp和bo5-6.cpp调用
- #include"c4-1.h" // 定义SString类型
- #include"bo4-1.cpp" // SString类型的基本操作
- void sever(SString str,SString hstr) // 算法5.8改。SString是数组,不需引用类型
- { // 将非空串str分割成两部分:hstr为第一个','之前的子串,str为之后的子串
- int n,k,i; // k记尚未配对的左括号个数
- SString ch,c1,c2,c3;
- n=StrLength(str); // n为串str的长度
- StrAssign(c1,","); // c1=','
- StrAssign(c2,"("); // c2='('
- StrAssign(c3,")"); // c3=')'
- SubString(ch,str,1,1); // ch为串str的第1个字符
- for(i=1,k=0;i<=n&&StrCompare(ch,c1)||k!=0;++i) // i小于串长且ch不是','
- { // 搜索最外层的第一个逗号
- SubString(ch,str,i,1); // ch为串str的第i个字符
- if(!StrCompare(ch,c2)) // ch='('
- ++k; // 左括号个数+1
- else if(!StrCompare(ch,c3)) // ch=')'
- --k; // 左括号个数-1
- }
- if(i<=n) // 串str中存在',',它是第i-1个字符
- {
- SubString(hstr,str,1,i-2); // hstr返回串str','前的字符
- SubString(str,str,i,n-i+1); // str返回串str','后的字符
- }
- else // 串str中不存在','
- {
- StrCopy(hstr,str); // 串hstr就是串str
- ClearString(str); // ','后面是空串
- }
- }
- // bo5-1.cpp 顺序存储数组(存储结构由c5-1.h定义)的基本操作(5个)
- Status InitArray(Array &A,int dim,...)
- { // 若维数dim和各维长度合法,则构造相应的数组A,并返回OK
- int elemtotal=1,i; // elemtotal是数组元素总数,初值为1(累乘器)
- va_list ap;
- if(dim<1||dim>MAX_ARRAY_DIM)
- return ERROR;
- A.dim=dim;
- A.bounds=(int *)malloc(dim*sizeof(int));
- if(!A.bounds)
- exit(OVERFLOW);
- va_start(ap,dim);
- for(i=0;i<dim;++i)
- {
- A.bounds[i]=va_arg(ap,int);
- if(A.bounds[i]<0)
- return UNDERFLOW; // 在math.h中定义为4
- elemtotal*=A.bounds[i];
- }
- va_end(ap);
- A.base=(ElemType *)malloc(elemtotal*sizeof(ElemType));
- if(!A.base)
- exit(OVERFLOW);
- A.constants=(int *)malloc(dim*sizeof(int));
- if(!A.constants)
- exit(OVERFLOW);
- A.constants[dim-1]=1;
- for(i=dim-2;i>=0;--i)
- A.constants[i]=A.bounds[i+1]*A.constants[i+1];
- return OK;
- }
- void DestroyArray(Array &A)
- { // 销毁数组A
- if(A.base)
- free(A.base);
- if(A.bounds)
- free(A.bounds);
- if(A.constants)
- free(A.constants);
- A.base= A.bounds=A.constants=NULL;
- A.dim=0;
- }
- Status Locate(Array A,va_list ap,int &off) // Value()、Assign()调用此函数
- { // 若ap指示的各下标值合法,则求出该元素在A中的相对地址off
- int i,ind;
- off=0;
- for(i=0;i<A.dim;i++)
- {
- ind=va_arg(ap,int);
- if(ind<0||ind>=A.bounds[i])
- return OVERFLOW;
- off+=A.constants[i]*ind;
- }
- return OK;
- }
- Status Value(ElemType &e,Array A,...) // 在VC++中,...之前的形参不能是引用类型
- { // ...依次为各维的下标值,若各下标合法,则e被赋值为A的相应的元素值
- va_list ap;
- int off;
- va_start(ap,A);
- if(Locate(A,ap,off)==OVERFLOW) // 调用Locate()
- return ERROR;
- e=*(A.base+off);
- return OK;
- }
- Status Assign(Array A,ElemType e,...) // 变量A的值不变,故不需要&
- { // ...依次为各维的下标值,若各下标合法,则将e的值赋给A的指定的元素
- va_list ap;
- int off;
- va_start(ap,e);
- if(Locate(A,ap,off)==OVERFLOW) // 调用Locate()
- return ERROR;
- *(A.base+off)=e;
- return OK;
- }
- // bo5-2.cpp 三元组稀疏矩阵的基本操作(8个),包括算法5.1
- Status CreateSMatrix(TSMatrix &M)
- { // 创建稀疏矩阵M
- int i,m,n;
- ElemType e;
- Status k;
- printf("请输入矩阵的行数,列数,非零元素数:");
- scanf("%d,%d,%d",&M.mu,&M.nu,&M.tu);
- if(M.tu>MAX_SIZE)
- return ERROR;
- M.data[0].i=0; // 为以下比较顺序做准备
- for(i=1;i<=M.tu;i++)
- {
- do
- {
- printf("请按行序顺序输入第%d个非零元素所在的行(1~%d),列(1~%d),元素值:",i,M.mu,M.nu);
- scanf("%d,%d,%d",&m,&n,&e);
- k=0;
- if(m<1||m>M.mu||n<1||n>M.nu) // 行或列超出范围
- k=1;
- if(m<M.data[i-1].i||m==M.data[i-1].i&&n<=M.data[i-1].j) // 行或列的顺序有错
- k=1;
- }while(k);
- M.data[i].i=m;
- M.data[i].j=n;
- M.data[i].e=e;
- }
- return OK;
- }
- void DestroySMatrix(TSMatrix &M)
- { // 销毁稀疏矩阵M
- M.mu=M.nu=M.tu=0;
- }
- void PrintSMatrix(TSMatrix M)
- { // 输出稀疏矩阵M
- int i;
- printf("%d行%d列%d个非零元素。/n",M.mu,M.nu,M.tu);
- printf("行 列 元素值/n");
- for(i=1;i<=M.tu;i++)
- printf("%2d%4d%8d/n",M.data[i].i,M.data[i].j,M.data[i].e);
- }
- void PrintSMatrix1(TSMatrix M)
- { // 按矩阵形式输出M
- int i,j,k=1;
- Triple *p=M.data;
- p++; // p指向第1个非零元素
- for(i=1;i<=M.mu;i++)
- {
- for(j=1;j<=M.nu;j++)
- if(k<=M.tu&&p->i==i&&p->j==j) // p指向非零元,且p所指元素为当前处理元素
- {
- printf("%3d",p->e); // 输出p所指元素的值
- p++; // p指向下一个元素
- k++; // 计数器+1
- }
- else // p所指元素不是当前处理元素
- printf("%3d",0); // 输出0
- printf("/n");
- }
- }
- void CopySMatrix(TSMatrix M,TSMatrix &T)
- { // 由稀疏矩阵M复制得到T
- T=M;
- }
- int comp(int c1,int c2)
- { // AddSMatrix函数要用到,另加
- if(c1<c2)
- return -1;
- if(c1==c2)
- return 0;
- return 1;
- }
- Status AddSMatrix(TSMatrix M,TSMatrix N,TSMatrix &Q)
- { // 求稀疏矩阵的和Q=M+N
- int m=1,n=1,q=0;
- if(M.mu!=N.mu||M.nu!=N.nu) // M、N两稀疏矩阵行或列数不同
- return ERROR;
- Q.mu=M.mu;
- Q.nu=M.nu;
- while(m<=M.tu&&n<=N.tu) // 矩阵M和N的元素都没处理完
- {
- switch(comp(M.data[m].i,N.data[n].i))
- {
- case -1: Q.data[++q]=M.data[m++]; // 将矩阵M的当前元素值赋给矩阵Q
- break;
- case 0: switch(comp(M.data[m].j,N.data[n].j)) // M、N矩阵当前元素的行相等,继续比较列
- {
- case -1: Q.data[++q]=M.data[m++];
- break;
- case 0: Q.data[++q]=M.data[m++]; // M、N矩阵当前非零元素的行列均相等
- Q.data[q].e+=N.data[n++].e; // 矩阵M、N的当前元素值求和并赋给矩阵Q
- if(Q.data[q].e==0) // 元素值为0,不存入压缩矩阵
- q--;
- break;
- case 1: Q.data[++q]=N.data[n++];
- }
- break;
- case 1: Q.data[++q]=N.data[n++]; // 将矩阵N的当前元素值赋给矩阵Q
- }
- }
- while(m<=M.tu) // 矩阵N的元素全部处理完毕
- Q.data[++q]=M.data[m++];
- while(n<=N.tu) // 矩阵M的元素全部处理完毕
- Q.data[++q]=N.data[n++];
- Q.tu=q; // 矩阵Q的非零元素个数
- if(q>MAX_SIZE) // 非零元素个数太多
- return ERROR;
- return OK;
- }
- Status SubtSMatrix(TSMatrix M,TSMatrix N,TSMatrix &Q)
- { // 求稀疏矩阵的差Q=M-N
- int i;
- for(i=1;i<=N.tu;i++)
- N.data[i].e*=-1;
- return AddSMatrix(M,N,Q);
- }
- void TransposeSMatrix(TSMatrix M,TSMatrix &T)
- { // 求稀疏矩阵M的转置矩阵T。算法5.1改
- int p,q,col;
- T.mu=M.nu;
- T.nu=M.mu;
- T.tu=M.tu;
- if(T.tu)
- {
- q=1;
- for(col=1;col<=M.nu;++col)
- for(p=1;p<=M.tu;++p)
- if(M.data[p].j==col)
- {
- T.data[q].i=M.data[p].j;
- T.data[q].j=M.data[p].i;
- T.data[q].e=M.data[p].e;
- ++q;
- }
- }
- }
- Status MultSMatrix(TSMatrix M,TSMatrix N,TSMatrix &Q)
- { // 求稀疏矩阵的乘积Q=M×N
- int i,j;
- ElemType *Nc,*Tc;
- TSMatrix T; // 临时矩阵
- if(M.nu!=N.mu)
- return ERROR;
- T.nu=M.mu; // 临时矩阵T是Q的转秩矩阵
- T.mu=N.nu;
- T.tu=0;
- Nc=(ElemType*)malloc((N.mu+1)*sizeof(ElemType)); // Nc为矩阵N一列的临时数组(非压缩,[0]不用)
- Tc=(ElemType*)malloc((M.nu+1)*sizeof(ElemType)); // Tc为矩阵T一行的临时数组(非压缩,[0]不用)
- if(!Nc||!Tc) // 创建临时数组不成功
- exit(ERROR);
- for(i=1;i<=N.nu;i++) // 对于N的每一列
- {
- for(j=1;j<=N.mu;j++)
- Nc[j]=0; // 矩阵Nc的初值为0
- for(j=1;j<=M.mu;j++)
- Tc[j]=0; // 临时数组Tc的初值为0,[0]不用
- for(j=1;j<=N.tu;j++) // 对于N的每一个非零元素
- if(N.data[j].j==i) // 属于第i列
- Nc[N.data[j].i]=N.data[j].e; // 根据其所在行将其元素值赋给相应的Nc
- for(j=1;j<=M.tu;j++) // 对于M的每一个值
- Tc[M.data[j].i]+=M.data[j].e*Nc[M.data[j].j]; // Tc中存N的第i列与M相乘的结果
- for(j=1;j<=M.mu;j++)
- if(Tc[j]!=0)
- {
- T.data[++T.tu].e=Tc[j];
- T.data[T.tu].i=i;
- T.data[T.tu].j=j;
- }
- }
- if(T.tu>MAX_SIZE) // 非零元素个数太多
- return ERROR;
- TransposeSMatrix(T,Q); // 将T的转秩赋给Q
- DestroySMatrix(T); // 销毁临时矩阵T
- free(Tc); // 释放动态数组Tc和Nc
- free(Nc);
- return OK;
- }
- // bo5-3.cpp 行逻辑链接稀疏矩阵(存储结构由c5-3.h定义)的基本操作(8个),包括算法5.3
- Status CreateSMatrix(RLSMatrix &M)
- { // 创建稀疏矩阵M
- int i,j;
- Triple T;
- Status k;
- printf("请输入矩阵的行数,列数,非零元素数:");
- scanf("%d,%d,%d",&M.mu,&M.nu,&M.tu);
- if(M.tu>MAX_SIZE||M.mu>MAX_RC)
- return ERROR;
- M.data[0].i=0; // 为以下比较做准备
- for(i=1;i<=M.tu;i++)
- {
- do
- {
- printf("请按行序顺序输入第%d个非零元素所在的行(1~%d),列(1~%d),元素值:",i,M.mu,M.nu);
- scanf("%d,%d,%d",&T.i,&T.j,&T.e);
- k=0;
- if(T.i<1||T.i>M.mu||T.j<1||T.j>M.nu) // 行、列超出范围
- k=1;
- if(T.i<M.data[i-1].i||T.i==M.data[i-1].i&&T.j<=M.data[i-1].j) // 没有按顺序输入非零元素
- k=1;
- }while(k); // 当输入有误,重新输入
- M.data[i]=T;
- }
- for(i=1;i<=M.mu;i++) // 给rpos[]赋初值0
- M.rpos[i]=0;
- for(i=1;i<=M.tu;i++) // 计算每行非零元素数并赋给rpos[]
- M.rpos[M.data[i].i]++;
- for(i=M.mu;i>=1;i--) // 计算rpos[]
- {
- M.rpos[i]=1; // 赋初值1
- for(j=i-1;j>=1;j--)
- M.rpos[i]+=M.rpos[j];
- }
- return OK;
- }
- void DestroySMatrix(RLSMatrix &M)
- { // 销毁稀疏矩阵M(使M为0行0列0个非零元素的矩阵)
- M.mu=M.nu=M.tu=0;
- }
- void PrintSMatrix(RLSMatrix M)
- { // 输出稀疏矩阵M
- int i;
- printf("%d行%d列%d个非零元素。/n",M.mu,M.nu,M.tu);
- printf("行 列 元素值/n");
- for(i=1;i<=M.tu;i++)
- printf("%2d%4d%8d/n",M.data[i].i,M.data[i].j,M.data[i].e);
- for(i=1;i<=M.mu;i++)
- printf("第%d行的第一个非零元素是本矩阵第%d个元素/n",i,M.rpos[i]);
- }
- void PrintSMatrix1(RLSMatrix M)
- { // 按矩阵形式输出M
- int i,j,k=1;
- Triple *p=M.data;
- p++; // p指向第1个非零元素
- for(i=1;i<=M.mu;i++)
- {
- for(j=1;j<=M.nu;j++)
- if(k<=M.tu&&p->i==i&&p->j==j) // p指向非零元,且p所指元素为当前处理元素
- {
- printf("%3d",p->e); // 输出p所指元素的值
- p++; // p指向下一个元素
- k++; // 计数器+1
- }
- else // p所指元素不是当前处理元素
- printf("%3d",0); // 输出0
- printf("/n");
- }
- }
- void CopySMatrix(RLSMatrix M,RLSMatrix &T)
- { // 由稀疏矩阵M复制得到T
- T=M;
- }
- Status AddSMatrix(RLSMatrix M,RLSMatrix N,RLSMatrix &Q)
- { // 求稀疏矩阵的和Q=M+N
- int k,p,q,tm,tn;
- if(M.mu!=N.mu||M.nu!=N.nu)
- return ERROR;
- Q.mu=M.mu; // Q矩阵行数
- Q.nu=M.nu; // Q矩阵列数
- Q.tu=0; // Q矩阵非零元素数初值
- for(k=1;k<=M.mu;++k) // 对于每一行,k指示行号
- {
- Q.rpos[k]=Q.tu+1; // Q矩阵第k行的第1个元素的位置
- p=M.rpos[k]; // p指示M矩阵第k行当前元素的序号
- q=N.rpos[k]; // q指示N矩阵第k行当前元素的序号
- if(k==M.mu) // 是最后一行
- {
- tm=M.tu+1; // tm,tn分别是p,q的上界
- tn=N.tu+1;
- }
- else
- {
- tm=M.rpos[k+1];
- tn=N.rpos[k+1];
- }
- while(p<tm&&q<tn) // M,N矩阵均有第k行元素未处理
- if(M.data[p].j==N.data[q].j) // M矩阵当前元素的列=N矩阵当前元素的列
- {
- if(M.data[p].e+N.data[q].e!=0) // 和不为0,存入Q
- {
- Q.data[++Q.tu]=M.data[p];
- Q.data[Q.tu].e+=N.data[q].e;
- }
- p++;
- q++;
- }
- else if(M.data[p].j<N.data[q].j) // M矩阵当前元素的列<N矩阵当前元素的列
- Q.data[++Q.tu]=M.data[p++]; // 将M的当前值赋给Q
- else // M矩阵当前元素的列>N矩阵当前元素的列
- Q.data[++Q.tu]=N.data[q++]; // 将N的当前值赋给Q
- while(p<tm) // M矩阵还有第k行的元素未处理
- Q.data[++Q.tu]=M.data[p++]; // 将M的当前值赋给Q
- while(q<tn) // N矩阵还有k行的元素未处理
- Q.data[++Q.tu]=N.data[q++]; // 将N的当前值赋给Q
- }
- if(Q.tu>MAX_SIZE)
- return ERROR;
- else
- return OK;
- }
- Status SubtSMatrix(RLSMatrix M,RLSMatrix N,RLSMatrix &Q)
- { // 求稀疏矩阵的差Q=M-N
- int i;
- if(M.mu!=N.mu||M.nu!=N.nu)
- return ERROR;
- for(i=1;i<=N.tu;++i) // 对于N的每一元素,其值乘以-1
- N.data[i].e*=-1;
- AddSMatrix(M,N,Q); // Q=M+(-N)
- return OK;
- }
- Status MultSMatrix(RLSMatrix M,RLSMatrix N,RLSMatrix &Q)
- { // 求稀疏矩阵乘积Q=M×N。算法5.3改
- int arow,brow,p,q,ccol,ctemp[MAX_RC+1],t,tp;
- if(M.nu!=N.mu) // 矩阵M的列数应和矩阵N的行数相等
- return ERROR;
- Q.mu=M.mu; // Q初始化
- Q.nu=N.nu;
- Q.tu=0;
- if(M.tu*N.tu==0) // M和N至少有一个是零矩阵
- return ERROR;
- for(arow=1;arow<=M.mu;++arow)
- { // 从M的第一行开始,到最后一行,arow是M的当前行
- for(ccol=1;ccol<=Q.nu;++ccol)
- ctemp[ccol]=0; // Q的当前行的各列元素累加器清零
- Q.rpos[arow]=Q.tu+1; // Q当前行的第1个元素位于上1行最后1个元素之后
- if(arow<M.mu)
- tp=M.rpos[arow+1];
- else
- tp=M.tu+1; // 给最后1行设界
- for(p=M.rpos[arow];p<tp;++p)
- { // 对M当前行中每一个非零元
- brow=M.data[p].j; // 找到对应元在N中的行号(M当前元的列号)
- if(brow<N.mu)
- t=N.rpos[brow+1];
- else
- t=N.tu+1; // 给最后1行设界
- for(q=N.rpos[brow];q<t;++q)
- {
- ccol=N.data[q].j; // 乘积元素在Q中列号
- ctemp[ccol]+=M.data[p].e*N.data[q].e;
- }
- } // 求得Q中第arow行的非零元
- for(ccol=1;ccol<=Q.nu;++ccol) // 压缩存储该行非零元
- if(ctemp[ccol]!=0)
- {
- if(++Q.tu>MAX_SIZE)
- return ERROR;
- Q.data[Q.tu].i=arow;
- Q.data[Q.tu].j=ccol;
- Q.data[Q.tu].e=ctemp[ccol];
- }
- }
- return OK;
- }
- void TransposeSMatrix(RLSMatrix M,RLSMatrix &T)
- { // 求稀疏矩阵M的转置矩阵T
- int p,q,t,col,*num;
- num=(int *)malloc((M.nu+1)*sizeof(int));
- T.mu=M.nu;
- T.nu=M.mu;
- T.tu=M.tu;
- if(T.tu)
- {
- for(col=1;col<=M.nu;++col)
- num[col]=0; // 设初值
- for(t=1;t<=M.tu;++t) // 求M中每一列非零元个数
- ++num[M.data[t].j];
- T.rpos[1]=1;
- for(col=2;col<=M.nu;++col) // 求M中第col中第一个非零元在T.data中的序号
- T.rpos[col]=T.rpos[col-1]+num[col-1];
- for(col=1;col<=M.nu;++col)
- num[col]=T.rpos[col];
- for(p=1;p<=M.tu;++p)
- {
- col=M.data[p].j;
- q=num[col];
- T.data[q].i=M.data[p].j;
- T.data[q].j=M.data[p].i;
- T.data[q].e=M.data[p].e;
- ++num[col];
- }
- }
- free(num);
- }
- // bo5-4.cpp 稀疏矩阵的十字链表存储(存储结构由c5-4.h定义)的基本操作(9个),包括算法5.4
- void InitSMatrix(CrossList &M)
- { // 初始化M(CrossList类型的变量必须初始化,否则创建、复制矩阵将出错)。加
- M.rhead=M.chead=NULL;
- M.mu=M.nu=M.tu=0;
- }
- void InitSMatrixList(CrossList &M)
- { // 初始化十字链表表头指针向量。加
- int i;
- if(!(M.rhead=(OLink*)malloc((M.mu+1)*sizeof(OLink)))) // 生成行表头指针向量
- exit(OVERFLOW);
- if(!(M.chead=(OLink*)malloc((M.nu+1)*sizeof(OLink)))) // 生成列表头指针向量
- exit(OVERFLOW);
- for(i=1;i<=M.mu;i++) // 初始化矩阵T的行表头指针向量,各行链表为空
- M.rhead[i]=NULL;
- for(i=1;i<=M.nu;i++) // 初始化矩阵T的列表头指针向量,各列链表为空
- M.chead[i]=NULL;
- }
- void InsertAscend(CrossList &M,OLink p)
- { // 初始条件:稀疏矩阵M存在,p指向的结点存在。操作结果:按行列升序将p所指结点插入M
- OLink q=M.rhead[p->i]; // q指向待插行表
- if(!q||p->j<q->j) // 待插的行表空或p所指结点的列值小于首结点的列值
- {
- p->right=M.rhead[p->i]; // 插在表头
- M.rhead[p->i]=p;
- }
- else
- {
- while(q->right&&q->right->j<p->j) // q所指不是尾结点且q的下一结点的列值小于p所指结点的列值
- q=q->right; // q向后移
- p->right=q->right; // 将p插在q所指结点之后
- q->right=p;
- }
- q=M.chead[p->j]; // q指向待插列表
- if(!q||p->i<q->i) // 待插的列表空或p所指结点的行值小于首结点的行值
- {
- p->down=M.chead[p->j]; // 插在表头
- M.chead[p->j]=p;
- }
- else
- {
- while(q->down&&q->down->i<p->i) // q所指不是尾结点且q的下一结点的行值小于p所指结点的行值
- q=q->down; // q向下移
- p->down=q->down; // 将p插在q所指结点之下
- q->down=p;
- }
- M.tu++;
- }
- void DestroySMatrix(CrossList &M)
- { // 初始条件:稀疏矩阵M存在。操作结果:销毁稀疏矩阵M
- int i;
- OLink p,q;
- for(i=1;i<=M.mu;i++) // 按行释放结点
- {
- p=*(M.rhead+i);
- while(p)
- {
- q=p;
- p=p->right;
- free(q);
- }
- }
- free(M.rhead);
- free(M.chead);
- InitSMatrix(M);
- }
- void CreateSMatrix(CrossList &M)
- { // 创建稀疏矩阵M,采用十字链表存储表示。算法5.4改
- int i,k;
- OLink p;
- if(M.rhead)
- DestroySMatrix(M);
- printf("请输入稀疏矩阵的行数 列数 非零元个数: ");
- scanf("%d%d%d",&M.mu,&M.nu,&i);
- InitSMatrixList(M); // 初始化M的表头指针向量
- printf("请按任意次序输入%d个非零元的行 列 元素值:/n",M.tu);
- for(k=0;k<i;k++)
- {
- p=(OLink)malloc(sizeof(OLNode)); // 生成结点
- if(!p)
- exit(OVERFLOW);
- scanf("%d%d%d",&p->i,&p->j,&p->e); // 给结点的3个成员赋值
- InsertAscend(M,p); // 将结点p按行列值升序插到矩阵M中
- }
- }
- void PrintSMatrix(CrossList M)
- { // 初始条件:稀疏矩阵M存在。操作结果:按行或按列输出稀疏矩阵M
- int i,j;
- OLink p;
- printf("%d行%d列%d个非零元素/n",M.mu,M.nu,M.tu);
- printf("请输入选择(1.按行输出 2.按列输出): ");
- scanf("%d",&i);
- switch(i)
- {
- case 1: for(j=1;j<=M.mu;j++)
- {
- p=M.rhead[j];
- while(p)
- {
- cout<<p->i<<"行"<<p->j<<"列值为"<<p->e<<endl;
- p=p->right;
- }
- }
- break;
- case 2: for(j=1;j<=M.nu;j++)
- {
- p=M.chead[j];
- while(p)
- {
- cout<<p->i<<"行"<<p->j<<"列值为"<<p->e<<endl;
- p=p->down;
- }
- }
- }
- }
- void PrintSMatrix1(CrossList M)
- { // 按矩阵形式输出M
- int i,j;
- OLink p;
- for(i=1;i<=M.mu;i++)
- { // 从第1行到最后1行
- p=M.rhead[i]; // p指向该行的第1个非零元素
- for(j=1;j<=M.nu;j++) // 从第1列到最后1列
- if(!p||p->j!=j) // 已到该行表尾或当前结点的列值不等于当前列值
- printf("%-3d",0); // 输出0
- else
- {
- printf("%-3d",p->e);
- p=p->right;
- }
- printf("/n");
- }
- }
- void CopySMatrix(CrossList M,CrossList &T)
- { // 初始条件:稀疏矩阵M存在。操作结果:由稀疏矩阵M复制得到T
- int i;
- OLink p,q;
- if(T.rhead) // 矩阵T存在
- DestroySMatrix(T);
- T.mu=M.mu;
- T.nu=M.nu;
- InitSMatrixList(T); // 初始化T的表头指针向量
- for(i=1;i<=M.mu;i++) // 按行复制
- {
- p=M.rhead[i]; // p指向i行链表头
- while(p) // 没到行尾
- {
- if(!(q=(OLNode*)malloc(sizeof(OLNode)))) // 生成结点q
- exit(OVERFLOW);
- *q=*p; // 给结点q赋值
- InsertAscend(T,q); // 将结点q按行列值升序插到矩阵T中
- p=p->right;
- }
- }
- }
- int comp(int c1,int c2)
- { // AddSMatrix函数要用到,另加
- if(c1<c2)
- return -1;
- if(c1==c2)
- return 0;
- return 1;
- }
- void AddSMatrix(CrossList M,CrossList N,CrossList &Q)
- { // 初始条件:稀疏矩阵M与N的行数和列数对应相等。操作结果:求稀疏矩阵的和Q=M+N
- int i;
- OLink pq,pm,pn;
- if(M.mu!=N.mu||M.nu!=N.nu)
- {
- printf("两个矩阵不是同类型的,不能相加/n");
- exit(OVERFLOW);
- }
- Q.mu=M.mu; // 初始化Q矩阵
- Q.nu=M.nu;
- Q.tu=0; // Q矩阵元素个数的初值为0
- InitSMatrixList(Q); // 初始化Q的表头指针向量
- for(i=1;i<=M.mu;i++) // 按行的顺序相加
- {
- pm=M.rhead[i]; // pm指向矩阵M的第i行的第1个结点
- pn=N.rhead[i]; // pn指向矩阵N的第i行的第1个结点
- while(pm&&pn) // pm和pn均不空
- {
- pq=(OLink)malloc(sizeof(OLNode)); // 生成矩阵Q的结点
- switch(comp(pm->j,pn->j))
- {
- case -1: *pq=*pm; // M的列<N的列,将矩阵M的当前元素值赋给pq
- InsertAscend(Q,pq); // 将结点pq按行列值升序插到矩阵Q中
- pm=pm->right; // 指针向后移
- break;
- case 0: *pq=*pm; // M、N矩阵的列相等,元素值相加
- pq->e+=pn->e;
- if(pq->e!=0) // 和为非零元素
- InsertAscend(Q,pq); // 将结点pq按行列值升序插到矩阵Q中
- else
- free(pq); // 释放结点
- pm=pm->right; // 指针向后移
- pn=pn->right;
- break;
- case 1: *pq=*pn; // M的列>N的列,将矩阵N的当前元素值赋给pq
- InsertAscend(Q,pq); // 将结点pq按行列值升序插到矩阵Q中
- pn=pn->right; // 指针向后移
- }
- }
- while(pm) // pn=NULL
- {
- pq=(OLink)malloc(sizeof(OLNode)); // 生成矩阵Q的结点
- *pq=*pm; // M的列<N的列,将矩阵M的当前元素值赋给pq
- InsertAscend(Q,pq); // 将结点pq按行列值升序插到矩阵Q中
- pm=pm->right; // 指针向后移
- }
- while(pn) // pm=NULL
- {
- pq=(OLink)malloc(sizeof(OLNode)); // 生成矩阵Q的结点
- *pq=*pn; // M的列>N的列,将矩阵N的当前元素值赋给pq
- InsertAscend(Q,pq); // 将结点pq按行列值升序插到矩阵Q中
- pn=pn->right; // 指针向后移
- }
- }
- if(Q.tu==0) // Q矩阵元素个数为0
- DestroySMatrix(Q); // 销毁矩阵Q
- }
- void SubtSMatrix(CrossList M,CrossList N,CrossList &Q)
- { // 初始条件:稀疏矩阵M与N的行数和列数对应相等。操作结果:求稀疏矩阵的差Q=M-N
- int i;
- OLink pq,pm,pn;
- if(M.mu!=N.mu||M.nu!=N.nu)
- {
- printf("两个矩阵不是同类型的,不能相减/n");
- exit(OVERFLOW);
- }
- Q.mu=M.mu; // 初始化Q矩阵
- Q.nu=M.nu;
- Q.tu=0; // Q矩阵元素个数的初值为0
- InitSMatrixList(Q); // 初始化Q的表头指针向量
- for(i=1;i<=M.mu;i++) // 按行的顺序相减
- {
- pm=M.rhead[i]; // pm指向矩阵M的第i行的第1个结点
- pn=N.rhead[i]; // pn指向矩阵N的第i行的第1个结点
- while(pm&&pn) // pm和pn均不空
- {
- pq=(OLink)malloc(sizeof(OLNode)); // 生成矩阵Q的结点
- switch(comp(pm->j,pn->j))
- {
- case -1: *pq=*pm; // M的列<N的列,将矩阵M的当前元素值赋给pq
- InsertAscend(Q,pq); // 将结点pq按行列值升序插到矩阵Q中
- pm=pm->right; // 指针向后移
- break;
- case 0: *pq=*pm; // M、N矩阵的列相等,元素值相减
- pq->e-=pn->e;
- if(pq->e!=0) // 差为非零元素
- InsertAscend(Q,pq); // 将结点pq按行列值升序插到矩阵Q中
- else
- free(pq); // 释放结点
- pm=pm->right; // 指针向后移
- pn=pn->right;
- break;
- case 1: *pq=*pn; // M的列>N的列,将矩阵N的当前元素值赋给pq
- pq->e*=-1; // 求反
- InsertAscend(Q,pq); // 将结点pq按行列值升序插到矩阵Q中
- pn=pn->right; // 指针向后移
- }
- }
- while(pm) // pn=NULL
- {
- pq=(OLink)malloc(sizeof(OLNode)); // 生成矩阵Q的结点
- *pq=*pm; // M的列<N的列,将矩阵M的当前元素值赋给pq
- InsertAscend(Q,pq); // 将结点pq按行列值升序插到矩阵Q中
- pm=pm->right; // 指针向后移
- }
- while(pn) // pm=NULL
- {
- pq=(OLink)malloc(sizeof(OLNode)); // 生成矩阵Q的结点
- *pq=*pn; // M的列>N的列,将矩阵N的当前元素值赋给pq
- pq->e*=-1; // 求反
- InsertAscend(Q,pq); // 将结点pq按行列值升序插到矩阵Q中
- pn=pn->right; // 指针向后移
- }
- }
- if(Q.tu==0) // Q矩阵元素个数为0
- DestroySMatrix(Q); // 销毁矩阵Q
- }
- void MultSMatrix(CrossList M,CrossList N,CrossList &Q)
- { // 初始条件:稀疏矩阵M的列数等于N的行数。操作结果:求稀疏矩阵乘积Q=M×N
- int i,j,e;
- OLink pq,pm,pn;
- InitSMatrix(Q);
- Q.mu=M.mu;
- Q.nu=N.nu;
- Q.tu=0;
- InitSMatrixList(Q); // 初始化Q的表头指针向量
- for(i=1;i<=Q.mu;i++)
- for(j=1;j<=Q.nu;j++)
- {
- pm=M.rhead[i];
- pn=N.chead[j];
- e=0;
- while(pm&&pn)
- switch(comp(pn->i,pm->j))
- {
- case -1: pn=pn->down; // 列指针后移
- break;
- case 0: e+=pm->e*pn->e; // 乘积累加
- pn=pn->down; // 行列指针均后移
- pm=pm->right;
- break;
- case 1: pm=pm->right; // 行指针后移
- }
- if(e) // 值不为0
- {
- pq=(OLink)malloc(sizeof(OLNode)); // 生成结点
- if(!pq) // 生成结点失败
- exit(OVERFLOW);
- pq->i=i; // 给结点赋值
- pq->j=j;
- pq->e=e;
- InsertAscend(Q,pq); // 将结点pq按行列值升序插到矩阵Q中
- }
- }
- if(Q.tu==0) // Q矩阵元素个数为0
- DestroySMatrix(Q); // 销毁矩阵Q
- }
- void TransposeSMatrix(CrossList M,CrossList &T)
- { // 初始条件:稀疏矩阵M存在。操作结果:求稀疏矩阵M的转置矩阵T
- int u,i;
- OLink *head,p,q,r;
- CopySMatrix(M,T); // T=M
- u=T.mu; // 交换T.mu和T.nu
- T.mu=T.nu;
- T.nu=u;
- head=T.rhead; // 交换T.rhead和T.chead
- T.rhead=T.chead;
- T.chead=head;
- for(u=1;u<=T.mu;u++) // 对T的每一行
- {
- p=T.rhead[u]; // p为行表头
- while(p) // 没到表尾,对T的每一结点
- {
- q=p->down; // q指向下一个结点
- i=p->i; // 交换.i和.j
- p->i=p->j;
- p->j=i;
- r=p->down; // 交换.down和.right
- p->down=p->right;
- p->right=r;
- p=q; // p指向下一个结点
- }
- }
- }
- // bo5-5.cpp 广义表的头尾链表存储(存储结构由c5-5.h定义)的基本操作(11个),包括算法5.5,5.6,5.7
- #include"func5-1.cpp" // 算法5.8
- void InitGList(GList &L)
- { // 创建空的广义表L
- L=NULL;
- }
- void CreateGList(GList &L,SString S) // 算法5.7
- { // 采用头尾链表存储结构,由广义表的书写形式串S创建广义表L。设emp="()"
- SString sub,hsub,emp;
- GList p,q;
- StrAssign(emp,"()"); // 空串emp="()"
- if(!StrCompare(S,emp)) // S="()"
- L=NULL; // 创建空表
- else // S不是空串
- {
- if(!(L=(GList)malloc(sizeof(GLNode)))) // 建表结点
- exit(OVERFLOW);
- if(StrLength(S)==1) // S为单原子,只会出现在递归调用中
- {
- L->tag=ATOM;
- L->atom=S[1]; // 创建单原子广义表
- }
- else // S为表
- {
- L->tag=LIST;
- p=L;
- SubString(sub,S,2,StrLength(S)-2); // 脱外层括号(去掉第1个字符和最后1个字符)给串sub
- do
- { // 重复建n个子表
- sever(sub,hsub); // 从sub中分离出表头串hsub
- CreateGList(p->ptr.hp,hsub);
- q=p;
- if(!StrEmpty(sub)) // 表尾不空
- {
- if(!(p=(GLNode *)malloc(sizeof(GLNode))))
- exit(OVERFLOW);
- p->tag=LIST;
- q->ptr.tp=p;
- }
- }while(!StrEmpty(sub));
- q->ptr.tp=NULL;
- }
- }
- }
- void DestroyGList(GList &L)
- { // 销毁广义表L
- GList q1,q2;
- if(L)
- {
- if(L->tag==LIST) // 删除表结点
- {
- q1=L->ptr.hp; // q1指向表头
- q2=L->ptr.tp; // q2指向表尾
- DestroyGList(q1); // 销毁表头
- DestroyGList(q2); // 销毁表尾
- }
- free(L);
- L=NULL;
- }
- }
- void CopyGList(GList &T,GList L)
- { // 采用头尾链表存储结构,由广义表L复制得到广义表T。算法5.6
- if(!L) // 复制空表
- T=NULL;
- else
- {
- T=(GList)malloc(sizeof(GLNode)); // 建表结点
- if(!T)
- exit(OVERFLOW);
- T->tag=L->tag;
- if(L->tag==ATOM)
- T->atom=L->atom; // 复制单原子
- else
- {
- CopyGList(T->ptr.hp,L->ptr.hp); // 递归复制子表
- CopyGList(T->ptr.tp,L->ptr.tp);
- }
- }
- }
- int GListLength(GList L)
- { // 返回广义表的长度,即元素个数
- int len=0;
- while(L)
- {
- L=L->ptr.tp;
- len++;
- }
- return len;
- }
- int GListDepth(GList L)
- { // 采用头尾链表存储结构,求广义表L的深度。算法5.5
- int max,dep;
- GList pp;
- if(!L)
- return 1; // 空表深度为1
- if(L->tag==ATOM)
- return 0; // 原子深度为0,只会出现在递归调用中
- for(max=0,pp=L;pp;pp=pp->ptr.tp)
- {
- dep=GListDepth(pp->ptr.hp); // 递归求以pp->ptr.hp为头指针的子表深度
- if(dep>max)
- max=dep;
- }
- return max+1; // 非空表的深度是各元素的深度的最大值加1
- }
- Status GListEmpty(GList L)
- { // 判定广义表是否为空
- if(!L)
- return TRUE;
- else
- return FALSE;
- }
- GList GetHead(GList L)
- { // 生成广义表L的表头元素,返回指向这个元素的指针
- GList h,p;
- if(!L) // 空表无表头
- return NULL;
- p=L->ptr.hp; // p指向L的表头元素
- CopyGList(h,p); // 将表头元素复制给h
- return h;
- }
- GList GetTail(GList L)
- { // 将广义表L的表尾生成为广义表,返回指向这个新广义表的指针
- GList t;
- if(!L) // 空表无表尾
- return NULL;
- CopyGList(t,L->ptr.tp); // 将L的表尾拷给t
- return t;
- }
- void InsertFirst_GL(GList &L,GList e)
- { // 初始条件:广义表存在。操作结果:插入元素e(也可能是子表)作为广义表L的第1元素(表头)
- GList p=(GList)malloc(sizeof(GLNode)); // 生成新结点
- if(!p)
- exit(OVERFLOW);
- p->tag=LIST; // 结点的类型是表
- p->ptr.hp=e; // 表头指向e
- p->ptr.tp=L; // 表尾指向原表L
- L=p; // L指向新结点
- }
- void DeleteFirst_GL(GList &L,GList &e)
- { // 初始条件:广义表L存在。操作结果:删除广义表L的第一元素,并用e返回其值
- GList p=L; // p指向第1个结点
- e=L->ptr.hp; // e指向L的表头
- L=L->ptr.tp; // L指向原L的表尾
- free(p); // 释放第1个结点
- }
- void Traverse_GL(GList L,void(*v)(AtomType))
- { // 利用递归算法遍历广义表L
- if(L) // L不空
- if(L->tag==ATOM) // L为单原子
- v(L->atom);
- else // L为广义表
- {
- Traverse_GL(L->ptr.hp,v); // 递归遍历L的表头
- Traverse_GL(L->ptr.tp,v); // 递归遍历L的表尾
- }
- }
- // bo5-6.cpp 广义表的扩展线性链表存储(存储结构由c5-6.h定义)的基本操作(13个)
- #include"func5-1.cpp" // 算法5.8
- void InitGList(GList1 &L)
- { // 创建空的广义表L
- L=NULL;
- }
- void CreateGList(GList1 &L,SString S) // 算法5.7改
- { // 采用扩展线性链表存储结构,由广义表的书写形式串S创建广义表L。设emp="()"
- SString emp,sub,hsub;
- GList1 p;
- StrAssign(emp,"()"); // 设emp="()"
- if(!(L=(GList1)malloc(sizeof(GLNode1)))) // 建表结点不成功
- exit(OVERFLOW);
- if(!StrCompare(S,emp)) // 创建空表
- {
- L->tag=LIST;
- L->hp=L->tp=NULL;
- }
- else if(StrLength(S)==1) // 创建单原子广义表
- {
- L->tag=ATOM;
- L->atom=S[1];
- L->tp=NULL;
- }
- else // 创建一般表
- {
- L->tag=LIST;
- L->tp=NULL;
- SubString(sub,S,2,StrLength(S)-2); // 脱外层括号(去掉第1个字符和最后1个字符)给串sub
- sever(sub,hsub); // 从sub中分离出表头串hsub
- CreateGList(L->hp,hsub);
- p=L->hp;
- while(!StrEmpty(sub)) // 表尾不空,则重复建n个子表
- {
- sever(sub,hsub); // 从sub中分离出表头串hsub
- CreateGList(p->tp,hsub);
- p=p->tp;
- };
- }
- }
- void DestroyGList(GList1 &L)
- { // 初始条件:广义表L存在。操作结果:销毁广义表L
- GList1 ph,pt;
- if(L) // L不为空表
- { // 由ph和pt接替L的两个指针
- if(L->tag) // 是子表
- ph=L->hp;
- else // 是原子
- ph=NULL;
- pt=L->tp;
- DestroyGList(ph); // 递归销毁表ph
- DestroyGList(pt); // 递归销毁表pt
- free(L); // 释放L所指结点
- L=NULL; // 令L为空
- }
- }
- void CopyGList(GList1 &T,GList1 L)
- { // 初始条件:广义表L存在。操作结果:由广义表L复制得到广义表T
- T=NULL;
- if(L) // L不空
- {
- T=(GList1)malloc(sizeof(GLNode1));
- if(!T)
- exit(OVERFLOW);
- T->tag=L->tag; // 复制枚举变量
- if(L->tag==ATOM) // 复制共用体部分
- T->atom=L->atom; // 复制单原子
- else
- CopyGList(T->hp,L->hp); // 复制子表
- if(L->tp==NULL) // 到表尾
- T->tp=L->tp;
- else
- CopyGList(T->tp,L->tp); // 复制子表
- }
- }
- int GListLength(GList1 L)
- { // 初始条件:广义表L存在。操作结果:求广义表L的长度,即元素个数
- int len=0;
- GList1 p=L->hp; // p指向第1个元素
- while(p)
- {
- len++;
- p=p->tp;
- };
- return len;
- }
- int GListDepth(GList1 L)
- { // 初始条件:广义表L存在。操作结果:求广义表L的深度
- int max,dep;
- GList1 pp;
- if(L==NULL||L->tag==LIST&&!L->hp)
- return 1; // 空表深度为1
- else if(L->tag==ATOM)
- return 0; // 单原子表深度为0,只会出现在递归调用中
- else // 求一般表的深度
- for(max=0,pp=L->hp;pp;pp=pp->tp)
- {
- dep=GListDepth(pp); // 求以pp为头指针的子表深度
- if(dep>max)
- max=dep;
- }
- return max+1; // 非空表的深度是各元素的深度的最大值加1
- }
- Status GListEmpty(GList1 L)
- { // 初始条件:广义表L存在。操作结果:判定广义表L是否为空
- if(!L||L->tag==LIST&&!L->hp)
- return OK;
- else
- return ERROR;
- }
- GList1 GetHead(GList1 L)
- { // 生成广义表L的表头元素,返回指向这个元素的指针
- GList1 h,p;
- if(!L||L->tag==LIST&&!L->hp) // 空表无表头
- return NULL;
- p=L->hp->tp; // p指向L的表尾
- L->hp->tp=NULL; // 截去L的表尾部分
- CopyGList(h,L->hp); // 将表头元素复制给h
- L->hp->tp=p; // 恢复L的表尾(保持原L不变)
- return h;
- }
- GList1 GetTail(GList1 L)
- { // 将广义表L的表尾生成为广义表,返回指向这个新广义表的指针
- GList1 t,p;
- if(!L||L->tag==LIST&&!L->hp) // 空表无表尾
- return NULL;
- p=L->hp; // p指向表头
- L->hp=p->tp; // 在L中删去表头
- CopyGList(t,L); // 将L的表尾拷给t
- L->hp=p; // 恢复L的表头(保持原L不变)
- return t;
- }
- void InsertFirst_GL(GList1 &L,GList1 e)
- { // 初始条件:广义表存在。操作结果:插入元素e(也可能是子表)作为广义表L的第1元素(表头)
- GList1 p=L->hp;
- L->hp=e;
- e->tp=p;
- }
- void DeleteFirst_GL(GList1 &L,GList1 &e)
- { // 初始条件:广义表L存在。操作结果:删除广义表L的第一元素,并用e返回其值
- if(L&&L->hp)
- {
- e=L->hp;
- L->hp=e->tp;
- e->tp=NULL;
- }
- else
- e=L;
- }
- void Traverse_GL(GList1 L,void(*v)(AtomType))
- { // 利用递归算法遍历广义表L
- GList1 hp;
- if(L) // L不空
- {
- if(L->tag==ATOM) // L为单原子
- {
- v(L->atom);
- hp=NULL;
- }
- else // L为子表
- hp=L->hp;
- Traverse_GL(hp,v);
- Traverse_GL(L->tp,v);
- }
- }