严蔚敏数据结构矩阵

这篇博客详细介绍了稀疏矩阵的几种存储方式,包括数组的一般存储、三元组存储和十字链表存储,并提供了相应的操作函数,如创建、转置、乘法等。此外,还给出了C语言实现的代码示例,展示了如何读取文件中的矩阵数据并进行运算。
摘要由CSDN通过智能技术生成

头文件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;
}

文件中的数组:

 

结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值