5.18⑤ 試設計一個算法,將數組A中的元素
A[0..n-1]循環右移k位,並要求只用一個元素
大小的附加存儲,元素移動或交換次數為O(n)。
要求實現以下函數:
void Rotate(Array1D &a, int n, int k);
一維數組類型Array1D的定義:
typedef ElemType Array1D[MAXLEN];
void Rotate(Array1D &a, int n, int k) /* a[n] contains the elements, */ /* rotate them right circlely by k sits */ { ElemType *p=a,temp; int i,j; if(0!=k%n){//k不是n的倍數時 for(i=1;i<=k;++i){ temp=a[n-1]; for(j=n-2;j>=0;--j){ a[j+1]=a[j]; } a[0]=temp; } } }
5.21④ 假設稀疏矩陣A和B均以三元組表作為存儲結構。
試寫出矩陣相加的算法,另設三元組表C存放結果矩陣。
要求實現以下函數:
Status AddTSM(TSMatrix A,TSMatrix B,TSMatrix &C);
/* 三元組表示的稀疏矩陣加法: C=A+B */
稀疏矩陣的三元組順序表類型TSMatrix的定義:
#define MAXSIZE 20 // 非零元個數的最大值
typedef struct {
int i,j; // 行下標,列下標
ElemType e; // 非零元素值
}Triple;
typedef struct {
Triple data[MAXSIZE+1]; // 非零元三元組表,data[0]未用
int mu,nu,tu; // 矩陣的行數、列數和非零元個數
}TSMatrix;
Status AddTSM(TSMatrix A,TSMatrix B,TSMatrix &C) /* 三元組表示的稀疏矩陣加法: C=A+B */ { int ai,bi,ci,aj,bj,cj,apos,bpos,cpos; apos=bpos=cpos=1; if(A.mu!=B.mu||A.nu!=B.nu){ return ERROR; } C.mu=A.mu; C.nu=A.nu; while(apos<=A.tu&&bpos<=B.tu){ ai=A.data[apos].i; bi=B.data[bpos].i; if(ai>bi){ ci=bi; while(ci==B.data[bpos].i){ C.data[cpos].i=ci; C.data[cpos].j=B.data[bpos].j; C.data[cpos].e=B.data[bpos].e; ++bpos; ++cpos; } } else if(ai<bi){ ci=ai; while(ci==A.data[apos].i){ C.data[cpos].i=ci; C.data[cpos].j=A.data[apos].j; C.data[cpos].e=A.data[apos].e; ++apos; ++cpos; } } else{ ci=ai; aj=A.data[apos].j; bj=B.data[bpos].j; if(aj>bj){ C.data[cpos].i=ci; C.data[cpos].j=bj; C.data[cpos].e=B.data[bpos].e; ++cpos; ++bpos; } else if(aj<bj){ C.data[cpos].i=ci; C.data[cpos].j=aj; C.data[cpos].e=A.data[apos].e; ++cpos; ++apos; } else{ cj=ai; C.data[cpos].e=A.data[apos].e+B.data[bpos].e; if(0!=C.data[cpos].e){ C.data[cpos].i=ci; C.data[cpos].j=aj; ++cpos; } ++apos; ++bpos; } } }//A稀疏矩陣完或者B稀疏矩陣完。 while(apos<=A.tu){//如果A矩陣中仍有元素 C.data[cpos].i=A.data[apos].i; C.data[cpos].j=A.data[apos].j; C.data[cpos].e=A.data[apos].e; ++cpos; ++apos; } while(bpos<=B.tu){//如果B矩陣中仍有元素 C.data[cpos].i=B.data[bpos].i; C.data[cpos].j=B.data[bpos].j; C.data[cpos].e=B.data[bpos].e; ++cpos; ++bpos; } C.tu=--cpos; return OK; }
5.23② 三元組表的一種變型是,從三元組表中去掉
行下標域得到二元組表,另設一個行起始向量,其每
個分量是二元組表的一個下標值,指示該行中第一個
非零元素在二元組表中的起始位置。試編寫一個算法,
由矩陣元素的下標值i,j求矩陣元素。試討論這種方
法和三元組表相比有什么優缺點。
要求實現以下函數:
Status GetElem(T2SMatrix M, int i, int j, ElemType &e);
/* 求二元組矩陣的元素A[i][j]的值e */
稀疏矩陣的二元組順序表+行起始向量的類型T2SMatrix的定義:
typedef struct{
int j;
ElemType e;
}TwoTuples;
typedef struct{
TwoTuples data[MAXSIZE];
int cpot[MAXROW]; // 這個向量存儲每一行在二元組中的起始位置
int mu,nu,tu;
} T2SMatrix; // 二元組矩陣類型
Status GetElem(T2SMatrix M, int i, int j, ElemType &e) /* 求二元組矩陣的元素A[i][j]的值e */ { //竟然忘了這個是稀疏矩陣,e如果不是非零元素就是零元素 //還要判斷i j的合法性!! int cur,last; cur=M.cpot[i]; last=M.cpot[i+1]; e=0; if(i>M.mu||j>M.nu||i<=0||j<=0){ return ERROR; } while(cur<last){ if(M.data[cur].j==j){ e=M.data[cur].e; return OK; } ++cur; } return OK; }
5.26③ 試編寫一個以三元組形式輸出用十字鏈表
表示的稀疏矩陣中非零元素及其下標的算法。
要求實現以下函數:
void OutCSM(CrossList M, void(*Out3)(int, int, int));
/* 用函數Out3,依次以三元組格式輸出十字鏈表表示的矩陣 */
稀疏矩陣的十字鏈表存儲表示:
typedef struct OLNode {
int i,j; // 該非零元的行和列下標
ElemType e; // 非零元素值
OLNode *right,*down; // 該非零元所在行表和列表的后繼鏈域
}OLNode, *OLink;
typedef struct {
OLink *rhead,*chead; // 行和列鏈表頭指針向量基址
int mu,nu,tu; // 稀疏矩陣的行數、列數和非零元個數
}CrossList;
void OutCSM(CrossList M, void(*Out3)(int, int, int)) /* 用函數Out3,依次以三元組格式輸出十字鏈表表示的矩陣 */ { int i=1,row,col,e; OLink p,q; for(i=1;i<=M.mu;++i){ p=M.rhead[i]; while(p){ Out3(p->i,p->j,p->e); p=p->right; } } }
5.30③ 試按表頭、表尾的分析方法重寫求廣義表
的深度的遞歸算法。
要求實現以下函數:
int GListDepth(GList ls);
/* Return the depth of list */
廣義表類型GList的定義:
typedef enum {ATOM,LIST} ElemTag;
typedef struct GLNode{
ElemTag tag;
union {
char atom;
struct {
GLNode *hp, *tp;
} ptr;
}un;
} *GList;
int GListDepth(GList ls) /* Return the depth of list */ { int max=0,len=0; GList p; if(!ls){ return 1; } if(ls->tag==ATOM){ return 0; } for(max=0,p=ls;p;p=p->un.ptr.tp){ len=GListDepth(p->un.ptr.hp); if(max<len){ max=len; } } return max+1; }
5.32④ 試編寫判別兩個廣義表是否相等的遞歸算法。
要求實現以下函數:
Status Equal(GList A, GList B);
/* 判斷廣義表A和B是否相等,是則返回TRUE,否則返回FALSE */
廣義表類型GList的定義:
typedef enum {ATOM,LIST} ElemTag;
typedef struct GLNode{
ElemTag tag;
union {
char atom;
struct {
GLNode *hp, *tp;
} ptr;
}un;
} *GList;
Status Equal(GList A, GList B) /* 判斷廣義表A和B是否相等,是則返回TRUE,否則返回FALSE */ { //基本思想:分三種情況1、若果都為原子節點,則判斷是否相等 2、如果都為廣義表,則遞歸返回兩個廣義表比較結果 //3、其它情況直接返回FALSE; if(ATOM==A->tag&&ATOM==B->tag){//情況1 if(A->un.atom==B->un.atom){ return TRUE; } else{ return FALSE; } } else if(LIST==A->tag&&LIST==B->tag){//情況2 return Equal(A->un.ptr.hp,B->un.ptr.hp)&&Equal(A->un.ptr.tp,B->un.ptr.tp); } else{//情況3 return FALSE; } }
5.33④ 試編寫遞歸算法,輸出廣義表中所有原子項
及其所在層次。
要求實現以下函數:
void OutAtom(GList A, int layer, void(*Out2)(char, int));
/* 遞歸地用函數Out2輸出廣義表的原子及其所在層次,layer表示當前層次 */
廣義表類型GList的定義:
typedef enum {ATOM,LIST} ElemTag;
typedef struct GLNode{
ElemTag tag;
union {
char atom;
struct {
GLNode *hp, *tp;
} ptr;
}un;
} *GList;
void OutAtom(GList A, int layer, void(*Out2)(char, int)) /* 遞歸地用函數Out2輸出廣義表的原子及其所在層次,layer表示當前層次 */ { if(A){ GList p; if(ATOM==A->tag){ Out2(A->un.atom,layer); } else{ p=A->un.ptr.hp; OutAtom(p,layer+1,Out2); p=A->un.ptr.tp; OutAtom(p,layer,Out2);//表尾所在層是當前層,所以此處不能為layer+1 } } }