【十字链表为存储结构实现矩阵相加】
**
用十字链表为存储结构实现矩阵相加 B = B + A
#include <stdio.h>
#include <stdlib.h>
#include<malloc.h>
typedef struct OLNode //十字链表存储单元
{
int row, col;
int data;
struct OLNode *right, *down;
} OLNode, *OLink;
typedef struct CrossList //十字链表
{
OLink *row_head, *col_head;
int m, n, len;
} CrossList;
void CreatCrossList(CrossList* M, int m, int n, int len)
//创建以十字链表为存储结构的稀疏矩阵
{
M->m = m, M->n = n, M->len = len; //读入行列数和非零元素个数
M->row_head = (OLink*)malloc(sizeof(OLink) * (m + 1)); //给头指针向量分配空间
if(M->row_head == NULL) return; //判断是否为空指针
M->col_head = (OLink*)malloc(sizeof(OLink) * (n + 1));
if(M->col_head == NULL) return;
for(int i = 0; i <= m; i++) //初始化头指针向量为空
M->row_head[i] = NULL;
for(int i = 0; i <= n; i++)
M->col_head[i] = NULL;
int i, j, e; //开始读入数据
for(int k = 0; k < M->len; k++)
{
scanf("%d %d %d", &i, &j, &e);
OLink p = (OLink)malloc(sizeof(OLNode)); //创建一个结点
if(p == NULL) return;
p->row = i, p->col = j, p->data = e; //将数据赋给创建的结点
p->right = p->down =NULL; //初始化指针
//横向分配存储位置
OLink q;
if(M->row_head[i] == NULL) //该行头指针为空
M->row_head[i] = p;
else if(M->row_head[i]->col > j) //该行第一个结点列数大于该结点
{
p->right = M->row_head[i];
M->row_head[i] = p;
}
else //该行第一个结点列数小于该结点
{
for(q = M->row_head[i]; q->right && q->right->col < j; q = q->right);//空循环
p->right = q->right;
q->right = p;
}
//列向分配存储位置(思想同上)
if(M->col_head[j] == NULL)
M->col_head[j] = p;
else if(M->col_head[j]->row > i)
{
p->down = M->col_head[j]->down;
M->col_head[j] = p;
}
else
{
for(q = M->col_head[j]; q->down && q->down->row < i; q = q->down);
p->down = q->down;
q->down = p;
}
}
}
void Insert(CrossList *M, OLink q)
//单个非零元素插入十字链表矩阵中
//借用创建十字链表矩阵的思想,只是多了可能会在相同位置的情况,且若相加后为零,还可能删除结点
{
int i = q->row, j = q->col; //i,j存放非零元素的行列数
OLink p;
if(M->row_head[i] == NULL) //该行没有元素,直接插入
M->row_head[i] = q;
else if(M->row_head[i]->col > j) //该行第一个元素列坐标大于该元素列坐标
{
q->right = M->row_head[i];
M->row_head[i] = q;
}
else if(M->row_head[i]->col == j) //该行第一个元素和该元素在同一个位置
{
M->row_head[i]->data = M->row_head[i]->data + q->data;
if(M->row_head[i]->data == 0) //相加后等于零,删除结点
M->row_head[i] = M->row_head[i]->right;
}
else //该行第一个元素列坐标小于该元素列坐标
{
for(p = M->row_head[i]; p->right && p->right->col < j; p = p->right);//空循环
if(p->right == NULL) //该行所有元素列坐标都小于该元素
p->right = q;
else if(p->right->col > j) //该元素列坐标大小介于该行两个元素之间
{
q->right = p->right;
p->right = q;
}
else //该元素列坐标大小等于该行某个个元素(不为第一个元素)
{
p->right->data = p->right->data + q->data;
if(p->right->data == 0) //相加等于零,删除结点
p->right = p->right->right;
}
}
}
void AddCrossList(CrossList* A, CrossList* B)
{
OLink p = (OLNode*)malloc(sizeof(OLNode));
for(int k = 1; k <= A->m; k++)
{
p = A->row_head[k];
while(p)
{
OLink q =(OLNode*)malloc(sizeof(OLNode));
//重新分配结点,目的是不改变原来的A十字链表矩阵
q->data = p->data;
q->row = p->row;
q->col = p->col;
q->right = q->down = NULL;
Insert(B, q); //一行一行逐个逐个插入到B十字链表矩阵中去
p = p->right;
}
}
}
void Print(CrossList *M) //打印B的稀疏矩阵(三元组形式)
{
OLink p = (OLNode*)malloc(sizeof(OLNode));
for(int k = 1; k <= M->len; k++) //一行一行地扫描打印
{
p = M->row_head[k];
while(p)
{
printf("%d %d %d\n", p->row, p->col, p->data);
p = p->right;
}
}
}
int main()
{
int m, n, len1, len2;
scanf("%d %d %d %d", &m, &n, &len1, &len2); //读入矩阵行列数,非零元个数
CrossList *A, *B;
A = (CrossList*)malloc(sizeof(CrossList)); //创建十字链表矩阵
B = (CrossList*)malloc(sizeof(CrossList));
CreatCrossList(A, m, n, len1);
CreatCrossList(B, m, n, len2);
AddCrossList(A, B); //矩阵相加
Print(B); //输出相加后的矩阵
return 0;
}
[题目介绍](https://img-blog.csdnimg.cn/d84c53b2607a4926ade0c2c925659223.png#pic_center)
测试数据:
3 4 3 2
1 1 1
1 3 1
2 2 2
1 2 1
2 2 3
正确输出:
1 1 1
1 2 1
1 3 1
2 2 5
## 西北工业大学数据结构noj