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 } } }