- // 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);
- }
- }