直接上代码。
最关键的是每次创建新结点之后插入十字链表的算法,也就是分析新结点指针指向的位置,这部分在最后InserttoChainTable函数里。虽然各种变量命名很奇怪,但是能标注的都尽量标注全了。
#include <stdio.h>
#include <stdlib.h>
#include "CrossList.h"
int main()
{
printf("验证十字链表矩阵的函数\n");
CrossList M,N;
{
FILE *fp = fopen("TestData.txt","r");
// if (!fp)
// exit (-1);
printf("从文件中创建两个矩阵\n");
CreateSMatrix_OL(fp,2,&M,&N);
fclose(fp);
printf("M = \n");
PrintSMatrix_OL(M);
printf("N = \n");
PrintSMatrix_OL(N);
printf("\n");
}
{
CrossList Tmp;
printf("将M拷贝到Tmp\n");
CopySMatrix_OL(&Tmp,M);
printf("Tmp = \n");
PrintSMatrix_OL(Tmp);
printf("\n");
}
{
CrossList T;
printf("T = M + N = \n");
AddSMatrix_OL(&T,M,N);
PrintSMatrix_OL(T);
printf("\n");
printf("T = M - N = \n");
SubSMatrix_OL(&T,M,N);
PrintSMatrix_OL(T);
printf("\n");
}
{
CrossList T;
printf("T = M * N = \n");
MultSMatrix_OL(&T,M,N);
PrintSMatrix_OL(T);
printf("\n");
}
{
CrossList T;
printf("T = M(T) = \n");
TransposeSMatrix_OL(&T,M);
PrintSMatrix_OL(T);
printf("\n");
}
{
printf("销毁M,N\n");
DestroySMatrix_OL(&M);
DestroySMatrix_OL(&N);
!M.mu && !M.nu && !M.tu && !N.mu && !N.tu && !N.nu? printf("M和N不存在\n"):printf("M和N存在\n");
printf("\n");
}
return 0;
}
/**********************************
* *
* 文件夹: ▲01 绪论 *
* *
* 文件名: Status.h *
* *
* 内 容: 相关状态码及宏函数列表 *
* *
**********************************/
#ifndef STATUS_H
#define STATUS_H
/* 状态码 */
#define TRUE 1 //真
#define FALSE 0 //假
#define YES 1 //是
#define NO 0 //否
#define OK 1 //通过
#define ERROR 0 //错误
#define SUCCESS 1 //成功
#define UNSUCCESS 0 //失败
#define INFEASIBLE -1 //不可行
#ifndef _MATH_H_ //系统中已有此状态码定义,要避免冲突
#define OVERFLOW -2 //堆栈上溢
#define UNDERFLOW -3 //堆栈下溢
#endif
#ifndef NULL
#define NULL ((void*)0)
#endif
/* 状态码识别类型 */
typedef int Status;
/*宏函数*/
//函数暂停一段时间
#define Wait(x)\
{\
double _Loop_Num_;\
for(_Loop_Num_=0.01; _Loop_Num_<=100000.0*x; _Loop_Num_+=0.01)\
;\
}//设立一个空循环
//摁Enter键继续
#define PressEnter\
{\
fflush(stdin);\
printf("Press Enter...");\
getchar();\
fflush(stdin);\
}
#endif
#ifndef CROSSLIST_H
#define CROSSLIST_H
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "Status.h"
#include "Scanf.h"
//十字链表类型定义
typedef int CElemType;
typedef struct OLNode
{
int i,j;
CElemType e;
struct OLNode *right;
struct OLNode *down;
} OLNode,*OLink;
typedef struct
{
OLink *rhead; //行链表头指针
OLink *chead; //列链表头指针
int mu,nu,tu;
} CrossList;
//函数表
Status CreateSMatrix_OL (FILE *fp,int n,...);
void DestroySMatrix_OL (CrossList *T);
void PrintSMatrix_OL (CrossList T);
void CopySMatrix_OL (CrossList *T, CrossList M);
Status AddSMatrix_OL (CrossList *T,CrossList M, CrossList N);
Status SubSMatrix_OL (CrossList *T, CrossList M, CrossList N);
Status MultSMatrix_OL (CrossList *T, CrossList M,CrossList N);
void TransposeSMatrix_OL (CrossList *T, CrossList M);
Status InserttoChainTable (OLink p, OLink *tmp, OLink tmpcol, CrossList *T);
Status InitMatrixandChain (CrossList *T);
#endif // CROSSLIST_H
#ifndef CROSSLIST_C
#define CROSSLIST_C
#include "CrossList.h"
十字链表类型定义
//typedef int CElemType;
//typedef struct OLNode
//{
// int i,j;
// CElemType e;
// struct OLNode *right;
// struct OLNode *down;
//} OLNode,*OLink;
//typedef struct
//{
// OLink *rhead; //行链表头指针
// OLink *chead; //列链表头指针
// int mu,nu,tu;
//} CrossList;
//函数表
Status CreateSMatrix_OL (FILE *fp,int n,...)
{
if (n<1)
return ERROR;
int count; //用来计算输入的矩阵个数
int k; //临时使用的变量
int number; //扫描时临时使用的变量
char *tmps;
OLink p; //用来代表新加入的结点
OLink q; //用来遍历每行的链表进而与p比较
CrossList *M; //指向输入的矩阵
va_list ap;
va_start (ap,n);
for (count=1;count<=n;count++){
M = va_arg(ap,CrossList *);
tmps = (char *)malloc(5*sizeof(char));
for (k=0;k<3;k++){
fscanf(fp,"%s %d",tmps,&number);
if (strcmpi(tmps,"row:")==0)
M->mu = number;
else if (strcmpi(tmps,"col:")==0)
M->nu = number;
else if (strcmpi(tmps,"num:")==0)
M->tu = number;
}
fscanf(fp,"%s",tmps);
if (strcmpi(tmps,"data:")==0){
//为chead,rhead动态申请空间,注意数组0号不放指针
InitMatrixandChain (M);
for (k=1;k<=M->tu;k++){
p = (OLink) malloc (sizeof(OLNode));
if (!p)
exit (OVERFLOW);
if (k==1){
fscanf(fp," (%d,%d,%d)",&(p->i),&(p->j),&(p->e));
// printf("(%d,%d,%d)",(p->i),(p->j),(p->e));
} else{
fscanf(fp,",(%d,%d,%d)",&(p->i),&(p->j),&(p->e));
// printf(",(%d,%d,%d)",(p->i),(p->j),(p->e));
}
// printf("%d%d%d",p->i,p->j,p->e);
p->right = p->down = NULL;
//定位插入行的哪个位置
if (M->rhead[p->i]==NULL || M->rhead[p->i]->j>p->j){
//如果需要插入链表第一位则
p->right = M->rhead[p->i];
M->rhead[p->i] = p;
} else {
//需要确保比较j的时候q所在结点一定是存在的,更加严谨
for (q = M->rhead[p->i];(q->right) && (q->right->j<p->j);q = q->right){}
//q指向应当插入的前一位Node;另外防止第一位重复
if (q->j==p->j || (q->right) && (q->right->j==p->j)){
printf("Repeated position.\n");
return ERROR;
}
p->right = q->right;
q->right = p;
}
//需要完成列插入
if(M->chead[p->j]==NULL || M->chead[p->j]->i>p->i){
p->down = M->chead[p->j];
M->chead[p->j] = p;
} else {
for (q = M->chead[p->j]; (q->down) && (q->down->i<p->i);q = q->down){}
if (q->i==p->i || (q->down) && (q->down->i==p->i)){
printf("Repeated position.\n");
return ERROR;
}
p->down = q->down;
q->down = p;
}
}
}
}
free(tmps);
va_end(ap);
return OK;
}
void DestroySMatrix_OL (CrossList *T)
{
//主要是处理行和列的链表
OLink row,tmp;
int i;
for (i=1;i<=T->mu;i++){
row = T->rhead[i];
while (row){
tmp = row;
row = row->right;
free(tmp);
}
}
free(T->rhead);
free(T->chead);
T->rhead = T->chead = NULL;
T->mu = T->nu = T->tu = 0;
}
void PrintSMatrix_OL (CrossList T)
{
OLink p;
int i,j;
for (i=1;i<=T.mu;i++){
p = T.rhead[i];
for (j=1;j<=T.mu;j++){
if (p && p->j==j){
printf("%d\t",p->e);
p = p->right;
} else
printf("0\t");
}
printf("\n");
}
}
void CopySMatrix_OL (CrossList *T, CrossList M)
{
T->mu = M.mu;
T->nu = M.nu;
T->tu = M.tu;
int k,i;
OLink p,q,tmp,tmpcol;
InitMatrixandChain (T);
for (i=1;i<=M.mu;i++){
q = M.rhead[i];
if (!q)
continue;
while (q){
p = (OLink)malloc(sizeof(OLNode));
if (!p)
exit(OVERFLOW);
p->i = q->i;
p->j = q->j;
p->e = q->e;
p->right = p->down = NULL;
InserttoChainTable (p,&tmp,tmpcol, T);
q = q->right;
}
}
}
Status AddSMatrix_OL (CrossList *T,CrossList M, CrossList N)
{
if(M.mu!=N.mu || M.nu!=N.nu){
printf("Cannot add these two matrix.\n");
return ERROR;
}
int k;
T->mu = M.mu;
T->nu = M.nu;
T->tu = 0;
InitMatrixandChain (T);
int row;
OLink pm,pn,p,tmp,tmpcol;
for (row=1;row<=M.mu;row++){
//从第一行遍历
pm = M.rhead[row];
pn = N.rhead[row];
while (pm && pn){
//当前行均有未扫描的单元
//区分是否需要创建结点
if (pm->j==pn->j && pm->e+pn->e==0){
pm = pm->right;
pn = pn->right;
continue;
}
p = (OLink)malloc (sizeof(OLNode));
if (!p)
exit (OVERFLOW);
if (pm->j<pn->j){
p->i = pm->i;
p->j = pm->j;
p->e = pm->e;
pm = pm->right;
} else if (pm->j>pn->j){
p->i = pn->i;
p->j = pn->j;
p->e = pn->e;
pn = pn->right;
} else {
p->i = pm->i;
p->j = pm->j;
p->e = pm->e + pn->e;
pm = pm->right;
pn = pn->right;
}
//创建完之后处理指针
p->down = p->right = NULL;
InserttoChainTable (p,&tmp,tmpcol, T);
}
while(pm){
p = (OLNode*)malloc(sizeof(OLNode));
if (!p)
exit (OVERFLOW);
p->i = pm->i;
p->j = pm->j;
p->e = pm->e;
p->down = p->right = NULL;
InserttoChainTable (p,&tmp,tmpcol, T);
pm = pm->right;
}
while(pn){
p = (OLNode*)malloc(sizeof(OLNode));
if (!p)
exit (OVERFLOW);
p->i = pn->i;
p->j = pn->j;
p->e = pn->e;
p->down = p->right = NULL;
InserttoChainTable (p,&tmp,tmpcol, T);
pn = pn->right;
}
}
return OK;
}
Status SubSMatrix_OL (CrossList *T, CrossList M, CrossList N)
{
if(M.mu!=N.mu || M.nu!=N.nu){
printf("Cannot sub these two matrix.\n");
return ERROR;
}
T->mu = M.mu;
T->nu = M.nu;
T->tu = 0;
InitMatrixandChain (T);
int row;
OLink pm,pn,p,tmp,tmpcol;
for (row=1;row<=M.mu;row++){
//从第一行遍历
pm = M.rhead[row];
pn = N.rhead[row];
while (pm && pn){
//当前行均有未扫描的单元
//区分是否需要创建结点
if (pm->j==pn->j && pm->e+pn->e==0){
pm = pm->right;
pn = pn->right;
continue;
}
p = (OLink)malloc (sizeof(OLNode));
if (!p)
exit (OVERFLOW);
if (pm->j<pn->j){
p->i = pm->i;
p->j = pm->j;
p->e = pm->e;
pm = pm->right;
} else if (pm->j>pn->j){
p->i = pn->i;
p->j = pn->j;
p->e = -pn->e;
pn = pn->right;
} else {
p->i = pm->i;
p->j = pm->j;
p->e = pm->e - pn->e;
pm = pm->right;
pn = pn->right;
}
//创建完之后处理指针
p->down = p->right = NULL;
InserttoChainTable (p,&tmp,tmpcol, T);
}
while(pm){
p = (OLNode*)malloc(sizeof(OLNode));
if (!p)
exit (OVERFLOW);
p->i = pm->i;
p->j = pm->j;
p->e = pm->e;
p->down = p->right = NULL;
InserttoChainTable (p,&tmp,tmpcol, T);
pm = pm->right;
}
while(pn){
p = (OLNode*)malloc(sizeof(OLNode));
if (!p)
exit (OVERFLOW);
p->i = pn->i;
p->j = pn->j;
p->e = -pn->e;
p->down = p->right = NULL;
InserttoChainTable (p,&tmp,tmpcol, T);
pn = pn->right;
}
}
return OK;
}
Status MultSMatrix_OL (CrossList *T, CrossList M,CrossList N)
{
if (M.nu!=N.mu){
printf("Unable to Multiply.\n");
return ERROR;
}
T->mu = M.mu;
T->nu = N.nu;
T->tu = 0;
InitMatrixandChain(T);
int mrow,ncol;
CElemType e;
OLink pm,pn,p,tmp,tmpcol;
if (M.tu*N.tu){
for (mrow=1;mrow<=M.mu;mrow++){
for (ncol=1;ncol<=N.nu;ncol++){
pm = M.rhead[mrow];
pn = N.chead[ncol];
e=0;
while (pm && pn){
if (pm->j<pn->i)
pm = pm->right;
else if (pm->j>pn->i)
pn = pn->down;
else{
e+=pm->e*pn->e;
pm = pm->right;
pn = pn->down;
}
}
if (e){
p = (OLink)malloc(sizeof(OLNode));
if (!p)
exit(OVERFLOW);
p->i = M.rhead[mrow]->i;
p->j = N.chead[ncol]->j;
p->e = e;
p->right = p->down = NULL;
InserttoChainTable (p, &tmp, tmpcol, T);
}
}
}
}
return OK;
}
void TransposeSMatrix_OL (CrossList *T, CrossList M)
{
T->mu = M.mu;
T->nu = M.nu;
T->tu = M.tu;
InitMatrixandChain(T);
int i;
OLink p,pm,tmp,tmpcol;
if (T->tu){
for (i=1;i<=M.nu;i++){
pm = M.chead[i];
if (!pm)
continue;
while (pm){
p = (OLink)malloc(sizeof(OLNode));
if (!p)
exit(OVERFLOW);
p->i = pm->j;
p->j = pm->i;
p->e = pm->e;
p->right = p->down = NULL;
InserttoChainTable (p, &tmp, tmpcol, T);
pm=pm->down;
}
}
}
}
Status InserttoChainTable (OLink p, OLink *tmp, OLink tmpcol, CrossList *T)
{
T->tu++;
if (T->rhead[p->i]==NULL)
T->rhead[p->i] = p;
else
(*tmp)->right = p;
*tmp = p;
if (T->chead[p->j]==NULL || T->chead[p->j]->i>p->i){
(*tmp)->down = T->chead[p->j];
T->chead[p->j] = *tmp;
} else {
for (tmpcol=T->chead[p->j];(tmpcol->down)&&(tmpcol->down->i<p->i);tmpcol = tmpcol->down){}
(*tmp)->down = tmpcol->down;
tmpcol->down = *tmp;
}
}
Status InitMatrixandChain (CrossList *T)
{
T->rhead = (OLink *)malloc((T->mu+1)*sizeof(OLink));
if (!T->rhead)
exit (OVERFLOW);
T->chead = (OLink *)malloc((T->nu+1)*sizeof(OLink));
int k;
if (!T->chead)
exit (OVERFLOW);
for (k=0;k<=T->mu;k++){
T->rhead[k] = NULL;
}
for (k=0;k<=T->nu;k++){
T->chead[k] = NULL;
}
return OK;
}
#endif // CROSSLIST_C
文档中的测试数据:
Row: 5
Col: 5
Num: 10
Data: (1,2,1),(1,4,5),(2,3,-3),(2,5,2),(3,1,2),(3,2,3),(3,3,4),(4,4,2),(5,1,3),(5,2,-1)
Row: 5
Col: 5
Num: 8
Data: (1,1,-3),(1,3,2),(2,4,-1),(3,2,4),(4,1,6),(4,5,5),(5,1,3),(5,3,2)