头文件array.h
数组的一般存储:
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#define MAXARRAYDIM 8
#define ERROR 0
#define OVERFLOW -1
#define UNDERFLOW 0
#define OK 1
#define TRUE 1
#define FALSE 0
typedef int ElemType;
typedef int Status;
typedef struct
{
ElemType* base; //数组基地址
int dim; //数组维数
int* bounds; //数组维界基址(存储每个维度范围)
int* constants; //映像函数常量基址(P93 5-2式的ci)
}Array;
Status InitArray(Array* A, int dim, ...)
{
if (dim<1 || dim>MAXARRAYDIM) return ERROR;
A->dim = dim;
A->bounds = (int*)malloc(sizeof(int) * dim);
if (!A->bounds) exit(OVERFLOW);
int elemtotal = 1;
va_list ap; //va_list包含在库stdarg.h中,是可变长
va_start(ap, dim); //度表,从dim开始
for (int i = 0; i < dim; i++)
{
A->bounds[i] = va_arg(ap, int); //调用该函数后,ap指向下一个参数
if (A->bounds < 0) return UNDERFLOW;
elemtotal *= A->bounds[i];
}
va_end(ap); //va_start与va_end成对出现
A->base = (int*)malloc(sizeof(int) * elemtotal);
if (!A->base) exit(OVERFLOW);
A->constants = (int*)malloc(sizeof(int) * dim);
if (!A->constants) exit(OVERFLOW);
A->constants[dim - 1] = 1; //采用递推公式计算映像函数常量
for (int i = dim - 2; i >= 0; i--) //从后往前计算,最低维为1
A->constants[i] = A->constants[i + 1] * A->bounds[i + 1];
return OK;
}
Status DestroyArray(Array* A)
{
if (A->base)
free(A->base);
A->base = NULL;
if (A->bounds)
free(A->bounds);
A->bounds = NULL;
if (A->constants)
free(A->constants);
A->constants = NULL;
A->dim = 0;
return OK;
}
Status Locate(Array A, va_list ap, int* off)
{
*off = 0; //返回相对基址的地址
for (int i = 0; i < A.dim; i++)
{
int idx = va_arg(ap, int);
if (idx < 0 || idx >= A.bounds[i])
return OVERFLOW;
off += A.constants[i] * idx;
}
return OK;
}
Status Value(Array A, ElemType* e, ...)
{
va_list ap;
va_start(ap, e);
int off;
Locate(A, ap, &off);
va_end(ap);
*e = A.base[off];
return OK;
}
Status Assign(Array* A, ElemType e, ...)
{
va_list ap;
va_start(ap, e);
int off;
Locate(*A, ap, &off);
va_end(ap);
A->base[off] = e;
return OK;
}
系数矩阵的三元组存储:
#define MAXSIZE 12500
#define MAXRC 100
#define MAXLINELEN 100
#define STACK_INIT_SIZE 100
#define STACKINCREASMENT 10
//用到的栈的数据结构及函数
typedef struct
{
ElemType* base, * top;
int stacksize;
}SqStack;
Status InitStack(SqStack* S)
{
S->base = (ElemType*)malloc(sizeof(ElemType) * STACK_INIT_SIZE);
if (!S->base) exit(OVERFLOW);
S->top = S->base;
S->stacksize = STACK_INIT_SIZE;
return OK;
}
Status Push(SqStack* S, ElemType e)
{
if (S->top - S->base == STACK_INIT_SIZE)
S->base = (ElemType*)realloc(S->base, sizeof(ElemType) * STACKINCREASMENT);
S->stacksize += STACKINCREASMENT;
*(S->top) = e;
S->top++;
return OK;
}
Status Pop(SqStack* S, ElemType* e)
{
if (S->base == S->top)
return ERROR;
S->top--;
*e = *(S->top);
return OK;
}
Status StackEmpty(SqStack S)
{
if (S.base == S.top)
return TRUE;
else
return FALSE;
}
//三元组表示系数矩阵
typedef struct
{
int i, j;
ElemType e;
}Triple;
typedef struct
{
Triple data[MAXSIZE];
int mu, nu, tu;
}TSMatrix;
Status TransposeSMatrix(TSMatrix M, TSMatrix* T) //一般方法求稀疏矩阵的转置
{ //顺序扫描所有的元素
T->mu = M.nu; //由于要从T的第一行开始赋值,就要找到
T->nu = M.mu; //M中列号为1的元素,以此类推
T->tu = M.tu; //以此类推复杂度为O(M.nu*M.tu)
if (T->tu)
{
int q = 1;
for (int col = 1; col <= M.nu; col++)
for (int j = 1; j <= M.tu; j++)
if (M.data[j].j == col)
{
T->data[q].i = M.data[j].j;
T->data[q].j = M.data[j].i;
T->data[q].e = M.data[j].e;
q++;
}
}
return OK;
}
Status FastTransposeSMatrix(TSMatrix M, TSMatrix* T)
{ //快速转置矩阵的方法
T->mu = M.nu; //用num数组记录M中不同列中的非零元数量
T->nu = M.mu; //用cpot数组记录遇到M中列号为col的元素
T->tu = M.tu; //应该赋到T的什么位置
if (T->tu)
{
int* num, * cpot;
num = (int*)malloc(sizeof(int) * (M.nu + 1));
if (!num) exit(OVERFLOW);
cpot = (int*)malloc(sizeof(int) * (M.nu + 1));
if (!cpot) exit(OVERFLOW);
for (int i = 1; i <= M.mu; i++)
num[i] = 0;
for (int i = 1; i < M.tu; i++)
num[M.data[i].j]++;
cpot[1] = 1;
for (int i = 2; i < M.nu; i++)
cpot[i] = cpot[i - 1] + num[i - 1];
for (int i = 1; i <= T->tu; i++)
{
int col = M.data[i].j;
int j = cpot[col];
T->data[j].e = M.data[i].e;
T->data[j].i = M.data[i].j;
T->data[j].j = M.data[i].i;
cpot[i]++;
}
}
return OK;
}
//行逻辑稀疏矩阵(在三元组稀疏矩阵的基础上加入了每行第一个非零元的位置)
typedef struct
{
Triple data[MAXSIZE + 1];
int mu, nu, tu;
int rpos[MAXRC + 1];
}RLSMatrix;
Status MultSMatrix(RLSMatrix M, RLSMatrix N, RLSMatrix* Q)
{
if (M.nu != N.mu)
return ERROR;
Q->mu = M.mu;
Q->nu = N.nu;
int* temp;
temp = (int*)malloc(sizeof(int) * (N.nu + 1));
if (!temp) exit(OVERFLOW);
Q->tu = 0;
if (M.tu * N.tu != 0)
{
for (int mrow = 1; mrow <= M.mu; mrow++)
{
Q->rpos[mrow] = Q->tu + 1;
for (int i = 1; i <= N.nu; i++)
temp[i] = 0;
int mst, men;
mst = M.rpos[mrow];
if (mrow == M.mu)
men = M.tu;
else
men = M.rpos[mrow + 1] - 1;
for (int p = mst; p <= men; p++)
{
int nrow = M.data[p].j;
int nst = N.rpos[nrow], nen;
if (nrow == N.mu)
nen = N.tu;
else
nen = N.rpos[nrow + 1] - 1;
for (int q = nst; q <= nen; q++)
{
int col = N.data[q].j;
temp[col] += N.data[q].e * M.data[p].e;
}
}
Q->rpos[mrow] = Q->tu + 1;
for (int i = 1; i <= N.nu; i++)
{
if (temp[i])
{
if (++Q->tu > MAXSIZE) return ERROR;
Q->data[Q->tu].e = temp[i];
Q->data[Q->tu].i = mrow;
Q->data[Q->tu].j = i;
}
}
}
}
return OK;
}
void InitRLSMatrix(RLSMatrix* M)
{
printf("请输入数组的非零元个数\n");
scanf("%d", &M->tu);
printf("请输入数组的行数\n");
scanf("%d", &M->mu);
printf("请输入数组的列数\n");
scanf("%d", &M->nu);
int* rcount;
rcount = (int*)malloc(sizeof(int) * (M->mu + 1));
if (!rcount) exit(OVERFLOW);
for (int i = 1; i <= M->mu; i++)
rcount[i] = 0;
for (int i = 1; i <= M->tu; i++)
{
printf("请输入第%d个非零元的行号\n", i);
scanf("%d", &M->data[i].i);
rcount[M->data[i].i]++;
printf("请输入第%d个非零元的列号\n", i);
scanf("%d", &M->data[i].j);
printf("请输入第%d个非零元的值\n", i);
scanf("%d", &M->data[i].e);
}
M->rpos[1] = 1;
for (int i = 2; i <= M->mu; i++)
M->rpos[i] = M->rpos[i - 1] + rcount[i - 1];
}
void Convert_char_int(int* no, char* p)
{
int i;
switch (*p)
{
case '0':i = 0; break;
case '1':i = 1; break;
case '2':i = 2; break;
case '3':i = 3; break;
case '4':i = 4; break;
case '5':i = 5; break;
case '6':i = 6; break;
case '7':i = 7; break;
case '8':i = 8; break;
default:i = 9;
}
*no = i;
}
void FInitRLSMatrix(RLSMatrix* M, FILE* fp, char* buf)
{ //从文件中获取信息并建立矩阵
int row = 0, count = 0; //*buf为文件读取缓冲区指针
SqStack* S;
S = (SqStack*)malloc(sizeof(SqStack));
if (!S) exit(OVERFLOW);
InitStack(S);
while (!feof(fp))
{
M->rpos[row + 1] = count + 1;
fgets(buf, MAXLINELEN, fp);
char* ch = buf;
int col = 0;
int bit, ans;
while (*ch != '\n' && *ch != '\0')
{
int tag = 0;
ans = 0;
int power = 1;
while (*ch >= '0' && *ch <= '9')
{
Convert_char_int(&bit, ch);
Push(S, bit);
ch++;
tag = 1;
}
while (!StackEmpty(*S))
{
Pop(S, &bit);
ans += power * bit;
power *= 10;
} //将获取到的连续的数字字符转换为int
if (ans)
{
M->data[++count].i = row + 1;
M->data[count].j = col + 1;
M->data[count].e = ans;
}
if (tag)
col++;
ch++;
}
row++;
M->nu = col;
}
M->mu = row;
M->tu = count;
}
void PrintRLSMtrix(RLSMatrix M)
{
int count = 1;
for (int i = 1; i <= M.mu; i++)
{
for (int j = 1; j <= M.nu; j++)
{
if (M.data[count].i == i && M.data[count].j == j)
{
printf("%d\t", M.data[count].e);
count++;
}
else
printf("%d\t", 0);
}
printf("\n");
}
}
十字链表存储:
//十字链表(Orthogonal Link List)
typedef struct OLNode
{
int i, j;
ElemType e;
struct OLNode* right, * down;
}OLNode, * OLink;
typedef struct
{
OLink* rhead, * chead;
int mu, nu, tu;
}CrossList;
Status CreateSMatrix_OL(FILE* fp, CrossList* M)
{
int rowcount = 0, colcount = 0;
char* buf, * ch;
buf = (char*)malloc(sizeof(char) * MAXLINELEN);
if (!buf) exit(OVERFLOW);
while (!feof(fp))
{
rowcount++;
fgets(buf, MAXLINELEN, fp);
}
rewind(fp);
fgets(buf, MAXLINELEN, fp);
ch = buf;
while (*ch != '\0' && *ch != '\n')
{
int tag = 0;
while ((*ch >= '0' && *ch <= '9') || (*ch == '-'))
{
ch++;
tag = 1;
}
if (tag)
colcount++;
ch++;
}
rewind(fp);
M->mu = rowcount;
M->nu = colcount;
M->rhead = (OLink*)malloc(sizeof(OLink) * (M->mu + 1));
if (!M->rhead) exit(OVERFLOW);
M->chead = (OLink*)malloc(sizeof(OLink) * (M->nu + 1));
if (!M->rhead) exit(OVERFLOW);
for (int i = 1; i <= M->mu; i++)
M->rhead[i] = NULL;
for (int i = 1; i <= M->nu; i++)
M->chead[i] = NULL;
SqStack* S;
S = (SqStack*)malloc(sizeof(SqStack));
if (!S) exit(OVERFLOW);
InitStack(S);
int bit, ans, power;
OLink e;
int row = 0, col;
int count = 0;
int verse;
while (!feof(fp))
{
row++;
col = 0;
fgets(buf, MAXLINELEN, fp);
ch = buf;
while (*ch != '\0' && *ch != '\n')
{
verse = 0;
int tag = 0;
ans = 0;
power = 1;
while ((*ch >= '0' && *ch <= '9') || (*ch == '-'))
{
if (*ch == '-')
verse = 1;
else
{
Convert_char_int(&bit, ch);
Push(S, bit);
}
ch++;
tag = 1;
}
while (!StackEmpty(*S))
{
Pop(S, &bit);
ans += power * bit;
power *= 10;
if (verse == 1)
ans *= (-1);
}
ch++;
if (tag)
col++;
if (ans)
{
e = (OLink)malloc(sizeof(OLNode));
if (!e) exit(OVERFLOW);
e->e = ans;
e->i = row;
e->j = col;
e->right = NULL;
e->down = NULL;
OLink p = M->rhead[row];
if (!p)
M->rhead[row] = e;
else
{
while (p->right && p->right->j < e->j)
p = p->right;
e->right = p->right;
p->right = e;
}
p = M->chead[col];
if (!p)
M->chead[col] = e;
else
{
while (p->down && p->down->i < e->i)
p = p->down;
e->down = p->down;
p->down = e;
}
count++;
}
}
}
M->tu = count;
return OK;
}
void PrintSMatrix_OL(CrossList M)
{
for (int i = 1; i <= M.mu; i++)
{
OLNode* p = M.rhead[i];
int j = 1;
while (p && j <= M.nu)
{
if (j == p->j)
{
printf("%d\t", p->e);
p = p->right;
}
else
printf("0\t");
j++;
}
while (j <= M.nu)
{
printf("0\t");
j++;
}
printf("\n");
}
}
Status SumSMatrix_OL(CrossList* M, CrossList N)
{
if (M->mu != N.mu || M->nu != N.nu)
return ERROR;
OLNode* pa, * pre, * pb;
OLink* hl;
hl = (OLink*)malloc(sizeof(OLink) * (M->nu + 1));
if (!hl) exit(OVERFLOW);
for (int j = 1; j <= M->nu; j++)
hl[j] = M->chead[j];
int row = 1;
while (row <= M->mu)
{
pa = M->rhead[row];
pre = NULL;
pb = N.rhead[row];
OLNode* q;
while (pb)
{
if (pa == NULL || pa->j > pb->j)
{
q = (OLNode*)malloc(sizeof(OLNode));
if (!q) exit(OVERFLOW);
*q = *pb;
if (pre)
pre->right = q;
else
M->rhead[row] = q;
q->right = pa;
pre = q;
if (M->chead[q->j] && M->chead[q->j]->i < q->i)
{
while (hl[q->j]->down->i < q->i)
hl[q->j] = hl[q->j]->down;
q->down = hl[q->j]->down;
hl[q->j]->down = q;
hl[q->j] = q;
}
else
{
q->down = M->chead[q->j];
M->chead[q->j] = q;
}
pb = pb->right;
M->tu++;
}
else
{
if (pa->j < pb->j)
{
pre = pa;
pa = pa->right;
}
else
{
if (pa->e + pb->e != 0)
{
pa->e += pb->e;
pre = pa;
pa = pa->right;
pb = pb->right;
}
else
{
q = pa;
if (pre == NULL)
{
M->rhead[row] = pa->right;
pa = pa->right;
}
else
{
pa = pa->right;
pre->right = pa;
}
if (q->i == M->chead[q->j]->i)
{
M->chead[q->j] = q->down;
hl[q->j] = q->down;
}
else
hl[q->j]->down = q->down;
free(q);
pb = pb->right;
M->tu--;
}
}
}
}
row++;
}
}
c文件:(仅运行十字链表矩阵相加函数)
#include "array.h"
int main()
{
FILE* fp, * fq;
fp = fopen("C:\\Users\\14164\\Desktop\\arrayname1.txt", "r");
fq = fopen("C:\\Users\\14164\\Desktop\\arrayname2.txt", "r");
CrossList M;
CrossList N;
CreateSMatrix_OL(fp, &M);
printf("矩阵1:\n");
PrintSMatrix_OL(M);
CreateSMatrix_OL(fq, &N);
printf("矩阵2:\n");
PrintSMatrix_OL(N);
SumSMatrix_OL(&M, N);
printf("矩阵3:\n");
PrintSMatrix_OL(M);
return 0;
}
文件中的数组:
结果: