#include<stdio.h>#include<stdlib.h>#include<stdarg.h>//标准头文件,提供宏va_start、va_arg和va_end#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0#define INFEASIBLE -1#define OVERFLOW -2typedefint Status;typedefint ElemType;#define MAX_ARRAY_DIM 8typedefstruct{
ElemType* base;//数组元素基址int dim;//数组维数int* bounds;//数组维界基址int* constants;//数组映像函数常量基址}Array;
Status InitArray(Array& A,int dim,...);//若维数dim和随后的各维长度合法,则构造相应的数组A,并返回OK
Status DestroyArray(Array& A);//销毁数组A
Status Locate(Array A, va_list ap,int& off);//若ap指示的各下标值合法,则求出该元素在A中相对地址off
Status Value(Array A, ElemType* e,...);//A是n维数组,e是元素变量,随后是n个下标值//若下标不超界,则e赋值为所指定的A的元素值,并返回OK
Status Assign(Array& A, ElemType e,...);//A是n维数组,e是元素变量,随后是n个下标值//若下标不超界,则将e的值赋给所指定的A的元素,并返回OKvoidprint_Array(Array A);intmain(){
Array A;int dim =2;InitArray(A, dim,2,3);Assign(A,1,0,0);Assign(A,2,0,1);Assign(A,3,0,2);Assign(A,4,1,0);Assign(A,5,1,1);Assign(A,6,1,2);print_Array(A);
ElemType e;Value(A,&e,0,0);printf("e:%d", e);DestroyArray(A);system("pause");return0;}
Status InitArray(Array& A,int dim,...){if(dim<1|| dim>MAX_ARRAY_DIM)return ERROR;
A.dim = dim;
A.bounds =(int*)malloc(dim *sizeof(int));if(!A.bounds)exit(OVERFLOW);int elemtotal =1;
va_list ap;va_start(ap, dim);int i;for(i =0; i < dim; i++){
A.bounds[i]=va_arg(ap,int);if(A.bounds[i]<0)return ERROR;
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;}
Status DestroyArray(Array& A){if(!A.base)return ERROR;free(A.base); A.base =NULL;if(!A.bounds)return ERROR;free(A.bounds); A.bounds =NULL;if(!A.constants)return ERROR;free(A.constants); A.constants =NULL;return OK;}
Status Locate(Array A, va_list ap,int& off){
off =0;int i;int ind;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(Array A, ElemType* e,...){
va_list ap;int result;int off;va_start(ap, e);if((result =Locate(A, ap, off))<=0)return result;*e =*(A.base + off);va_end(ap);return OK;}
Status Assign(Array& A, ElemType e,...){
va_list ap;int result;int off;va_start(ap, e);if((result =Locate(A, ap, off))<=0)return result;*(A.base + off)= e;va_end(ap);return OK;}voidprint_Array(Array A){printf("Array:\n");if(!A.base){printf("NULL\n");}int i, elemtotal=1;for(i =0; i < A.dim; i++){
elemtotal *= A.bounds[i];}for(i =0; i < elemtotal; i++){printf("%d ", A.base[i]);if((i +1)% A.constants[0]==0){printf("\n");}}}
5.3 矩阵的压缩存储
压缩存储:为多个值相同的元只分配一个存储空间,对零元不分配空间
特殊矩阵:值相同的元素或零元素在矩阵中的分布有一定规律,反之称为稀疏矩阵
5.3.1 特殊矩阵
n阶对称矩阵 为每一对对称元分配一个存储空间,则可将
n
2
n^2
n2个元压缩存储到
n
(
n
+
1
)
2
\large\frac{n(n+1)}{2}
2n(n+1)个元的空间中
对角矩阵 除了主对角线上和直接在对角线上、下方若干条对角线上的元之外,所有的其他的元均为零
5.3.2 稀疏矩阵
稀疏因子 假设在
m
×
n
m×n
m×n的矩阵中,有
t
t
t个元素不为零,令
δ
=
t
m
×
n
\delta=\Large\frac{t}{m×n}
δ=m×nt,称
δ
\delta
δ为矩阵的稀疏因子
存储方式:除了存储非零元的值之外,还必须同时记下它所在行和列的位置
(
i
,
j
)
(i,j)
(i,j)。反之,一个三元组
(
i
,
j
,
a
)
(i,j,a)
(i,j,a)唯一确定了矩阵
A
A
A的一个非零元
算法5.1 采用三元组表存储表示,求稀疏矩阵M的转置矩阵T 时间复杂度
O
(
n
u
⋅
t
u
)
O(nu\cdot tu)
O(nu⋅tu),一般矩阵转置时间复杂度为
O
(
m
u
⋅
n
u
)
O(mu\cdot nu)
O(mu⋅nu),当
t
u
=
m
u
×
n
u
tu=mu\times nu
tu=mu×nu时,算法5.1的时间复杂度就为
O
(
m
u
⋅
n
u
2
)
O(mu\cdot nu^2)
O(mu⋅nu2)了,因此该算法仅使用于
t
u
≪
m
u
×
n
u
tu\ll mu\times nu
tu≪mu×nu的情况
按照
a
.
d
a
t
a
a.data
a.data中三元组的次序进行转置,并将转置后的三元组置入
b
b
b中恰当。的位置预先确定矩阵
M
M
M中每一列(即
T
T
T中每一行)的第一个非零元在
b
.
d
a
t
a
b.data
b.data中应有的位置
附设
n
u
m
num
num和
c
p
o
t
cpot
cpot两个向量。
n
u
m
[
c
o
l
]
num[col]
num[col]表示矩阵
M
M
M中第
c
o
l
col
col列中非零元个数,
c
p
o
t
[
c
o
l
]
cpot[col]
cpot[col]指示
M
M
M中第
c
o
l
col
col列的第一个非零元在
b
.
d
a
t
a
b.data
b.data中的恰当位置
时间复杂度
O
(
n
u
+
t
u
)
O(nu+tu)
O(nu+tu)
Status FastTransposeSMatrix(TSMatrix M, TSMatrix& T){
T.mu = M.nu; T.nu = M.mu; T.tu = M.tu;int col;int num[MAXCOL +1];int cpot[MAXCOL +1];if(T.tu){for(col =1; col <= M.nu; col++){
num[col]=0;}int t;for(t =1; t <= M.nu; t++){
num[M.data[t].j]++;}
cpot[1]=1;for(col =2; col <= M.nu; col++){
cpot[col]= cpot[col -1]+ num[col -1];}int p, q;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]++;}}return OK;}
算法5.3、算法5.4 未完待续…
完整代码
#include<stdio.h>#include<stdlib.h>#include<stdarg.h>//标准头文件,提供宏va_start、va_arg和va_end#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0#define INFEASIBLE -1#define OVERFLOW -2typedefint Status;typedefint ElemType;#define MAXSIZE 12500 //非零元最大个数#define MAXCOL 100typedefstruct{int i, j;
ElemType e;//非零元下标}Triple;typedefstruct{
Triple data[MAXSIZE +1];int mu, nu, tu;//矩阵的行数、列数和非零元个数}TSMatrix;
Status TransposeSMatrix(TSMatrix M, TSMatrix& T);//算法5.1 采用三元组表存储表示,求稀疏矩阵M的转置矩阵T
Status FastTransposeSMatrix(TSMatrix M, TSMatrix& T);//算法5.2 采用三元组顺序表存储表示,求稀疏矩阵M的转置矩阵Tintmain(){system("pause");return0;}
Status TransposeSMatrix(TSMatrix M, TSMatrix& T){
T.mu = M.nu; T.nu = M.mu; T.tu = M.tu;if(T.nu){int q =1;int col;for(col =1; col <= M.nu; col++){int p;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++;}}}}/*int ind;
for (ind = 1; ind <= M.tu; ind++)
{
T.data[ind].i = M.data[ind].j;
T.data[ind].j = M.data[ind].i;
T.data[ind].e = M.data[ind].e;
}*/return OK;}
Status FastTransposeSMatrix(TSMatrix M, TSMatrix& T){
T.mu = M.nu; T.nu = M.mu; T.tu = M.tu;int col;int num[MAXCOL +1];int cpot[MAXCOL +1];if(T.tu){for(col =1; col <= M.nu; col++){
num[col]=0;}int t;for(t =1; t <= M.nu; t++){
num[M.data[t].j]++;}
cpot[1]=1;for(col =2; col <= M.nu; col++){
cpot[col]= cpot[col -1]+ num[col -1];}int p, q;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]++;}}return OK;}