一、矩阵的压缩存储
- 对称矩阵:对有n^2个元素的对称矩阵,可用长度为 [n(n+1)/2] 的一维矩阵存储。以行序为主序,存储下三角中的元: 当i >= j时, k = i(i-1)/2+j-1; 当i < j时,k = j(j-1)/2+i-1;
- 稀疏矩阵
(1)三元组顺序表
#define MAXSIZE 12500
typedef struct
{
int i, j; //行号、列号
Elemtype e;
} Triple;
typedef struct
{
Triple data[MAXSIZE + 1]; //非零元三元组表,data[0]未用
int mu, nu, tu; //行数、列数、非零元数
};
!!三元组矩阵转置算法!!
a. 普通转置
void TransposeSMatrix(TSMatrix M,TSMatrix &T)
{
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++;
}
}
}
}
}
b. 快速转置
增加num和cpot两个向量,num[col] 表示矩阵M中第col列中非零元的个数,cpot[col] 表示M中第col列的第一个非 零元在b.data中的恰当位置,有下列公式:
cpot[1] = 1; cpot[col] = cpot[col-1] + num[col-1]; 2 <= col <= a.nu
void FataTransposeSMatrix(TSMatric M,TSMtrix &T)
{
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++)
num[M.data[t].j]; //求M中每一列的非零元个数
cpot[1] = 1;
for (col = 2; col <= M.tu;col++)
cpot[col] = cpot[col - 1] + num[col - 1];//求第col列中第一个非零元在b.data中的序号
for (p = 1; p <= M.tu;p++)
{
col = M.data[p].j;
q = cpot[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;
cpot[col]++;
}
}
}
(2)行逻辑链接的顺序表
typedef struct
{
int i, j; //行号、列号
Elemtype e;
} Triple;
typedef struct
{
Triple data[MAXSIZE + 1]; //非零元三元组表,data[0]未用
int rpos[MAXSIZE+1]; //各行第一个非零元的位置表
int mu, nu, tu; //行数、列数、非零元数
};
(3)十字链表
typedef struct OLNode
{
int i, j;
Elemtype e;
struct OLNode *right, *down;
} OLNode, *OLink;
typedef struct
{
OLink *rhead, *chead;
int mu, nu, tu;
} CrossList;
二、广义表
1. 当广义表非空时,称第一个元素为表头,其余元素组成的表是表尾;
2. 存储结构
(1)头尾链表存储表示
typedef enum
{
ATOM,
LIST
} ElemTag;
typedef struct GLNode
{
ElemTag tag; //用于区分是原子结点还是表结点
union{
AtomType atom;
struct
{
struct GLNode *hp, *tp;
} ptr; //表结点指针域,分别指向表头和表尾
};
} * GList;
(2)扩展线性链表存储表示
typedef enum
{
ATOM,
LIST
} ElemTag;
typedef struct GLNode
{
ElemTag tag; //用于区分是原子结点还是表结点
union{
AtomType atom;
struct GLNode *hp;
};
struct GLNode *tp; //表结点指针域,分别指向表头和表尾
} * GList;
3.m元多项式的表示:将 m 元多项式先分解成主变元的多项式,则可将其看作一元多项式,而每个系数则是 m-1 元多项式;利用此法可将m-1 元多项式进一步分解,直至每个系数为常数。
4.广义表的递归算法
(1)采用头尾链表存储结构,求广义表L的深度
int GListDepth(GList L)
{
if(!L)
return 1;
if(L->tag==ATOM)
return 0;
for (max = 0, pp = L; pp;pp=pp->ptr.hp)
{
dep = GListDepth(pp->ptr.hp); //求以pp->ptr.hp为头指针的子表深度
if(dep>max)
max = dep;
}
return max + 1; //子表深度最大值+1
}
(2)采用头尾链表存储结构,有广义表L复制得到广义表T
void CopyGList(GList &T,GList L)
{
if(!L)
T = NULL;//复制空表
else
{
if(!(T=(GList)malloc(sizeof(GLNode))))
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);
}
}
}
(3)采用头尾链表存储结构,由广义表的书写形式串S创建广义表L,设emp = "()".
void CreateGlist(Glist &L,SString S)
{
if(StrCompre(S,emp))
L = NULL;
else
{
if(!(L=(GList)malloc(sizeof(GLNode))))
exit(OVERFLOW);
if(StrLength(S)==1)
{
L->tag = ATOM;
L->atom = S;
}
else
{
L->tag = LIST;
p = L;
SubString(sub, S, 2, StrLength(S) - 2); //脱外层括号
do
{
sever(sub, hsub); //从sub中分离出表头串hsub
CreateGList(p->ptr.hp, hsub);
if(!StrEmpty(sub))
{
if(!(p=(GLNode*)malloc(sizeof(GLNode))))
exit(OVERFLOW);
p->tag = LIST;
q->ptr.hp = p;
}
} while (!StrEmpty(sub));
q->ptr.tp = NULL;
}
}
}
void sever(SString &str,SString &hstr)
{
//将非空串str分割成两部分,hsub为第一个','之前的子串,str为之后的子串
n = StrLength(str);
i = 0;
k = 0;
do
{
i++;
SubString(ch, str, i, 1);
if(ch=='(')
k++;
else if(ch==')')
k--;
} while (i<n&&(ch!=','||k!=0));
if(i<n)
{
SubString(hstr, str, 1, i - 1);
SubString(str, str, i + 1, n - i);
}
else
{
StrCopy(hstr, str);
ClearString(str);
}
}