两个以正交链表表示的稀疏矩阵的加法算法:
//自己写的亲测有效,经过严格测试:
#include<stdio.h>
#include<stdlib.h>
#define MaxSize 100
typedef enum {
H, E } TagField;
typedef struct term {
int row, col, value;
}Term;
typedef struct mnode {
struct mnode* Right, * Down;
TagField Tag;
union {
struct mnode* Next;
Term Element;
}U;
}MNode;
typedef struct linkedmatrix {
MNode* Head;
MNode* HD[MaxSize];
}LinkedMatrix;
MNode* NewNode() {
MNode* temp = (MNode*)malloc(sizeof(MNode));
temp->Down = NULL;
temp->Right = NULL;
return temp;
}
//该算法的时间复杂度为O(heads+nozeros)
LinkedMatrix MRead(void) {
int rows, cols, nozeros, heads;
int row, col, value, i;
MNode* ptemp, * prow_last, *pcol_last, * pnode, * Temp;
LinkedMatrix A;
printf("Enter the number of rows, columns and number of nozero terms: ");
scanf_s("%d%d%d", &rows, &cols, &nozeros);
//建立正交链表的表头结点
heads = (cols > rows) ? cols : rows;
pnode = NewNode();
pnode->Tag = E;
pnode->U.Element.row = rows;
pnode->U.Element.col = cols;
pnode->U.Element.value = nozeros;
pnode->Down = NULL;
A.Head = pnode;
Temp = A.Head; //把A的表头结点赋给一个临时变量
if (!heads) {
pnode->Right=pnode;
}
else {
//建立heads 个行/列表头结点, 形成一个包含有Heads个元素的包含有表头节点的空循环链表,
for (i = 0; i < heads; i++) {
A.HD[i] = NewNode();
A.HD[i]->Tag = H;
A.HD[i]->Right = A.HD[i];
A.HD[i]->Down = A.HD[i];
if (i==0) {
Temp->Right = A.HD[i];
}
else {
Temp->U.Next = A.HD[i];
}
Temp = A.HD[i];
}
Temp->U.Next = A.Head;
//包含有Heads个元素的包含有表头节点的空循环链表创建完成
//从第0行起,按行插入非0元素
for (i = 0; i < nozeros;i++) {
printf("Enter row , col and value: ");
scanf_s("%d%d%d", &row, &col, &value);
ptemp = NewNode();
ptemp->Tag = E;
ptemp->U.Element.row = row;
ptemp->U.Element.col = col;
ptemp->U.Element.value = value;
ptemp->Right = A.HD[row];
ptemp->Down = A.HD[col];
prow_last = A.HD[row];
for (; prow_last->Right != A.HD[row]; prow_last = prow_last->Right);
prow_last->Right = ptemp;
prow_last = ptemp;
pcol_last=A.HD[col];
for (; pcol_last->Down != A.HD[col]; pcol_last = pcol_last->Down);
pcol_last->Down=ptemp;
pcol_last=ptemp;
}
}
return A;
}
LinkedMatrix Add2LinkedMatrix(LinkedMatrix a, LinkedMatrix b) {
MNode* p_head_temp, * prow_temp, *p_a_row_temp, * p_a_col_temp, * ptemp, * p_a_row_temp1;
int equalFlag = 0, lastrowFlag=0,lastcolFlag=0;
LinkedMatrix result;
if (a.Head==NULL || b.Head==NULL) {
printf("can not be null\n");
return;
}
if (a.Head->U.Element.row != a.Head->U.Element.row || a.Head->U.Element.col != a.Head->U.Element.col) {
printf("the shape of two Matrix must be itentical\n");
return;
}
p_head_temp = b.Head->Right;
for (; p_head_temp != b.Head; p_head_temp = p_head_temp->U.Next) {
prow_temp = p_head_temp->Right;//b中新的一行
for (; prow_temp != p_head_temp; prow_temp = prow_temp->Right) {
//prow_temp按行扫描b,prow_temp指代当前b矩阵中非零结点
//printf("%d %d %d\n", prow_temp->U.Element.row, prow_temp->U.Element.col, prow_temp->U.Element.value);
//在这里开始逐一将b中的元素与a中的元素进行对比。如果相同位置中,a有b的同样的元素,就直接将值相加。如果没有,就将b中的元素插入到a的这个位置上。
equalFlag = 0;
p_a_row_temp = a.HD[prow_temp->U.Element.row];
for (; p_a_row_temp->Right != a.HD[prow_temp->U.Element.row]; p_a_row_temp = p_a_row_temp->Right) {
if (p_a_row_temp->U.Element.row == prow_temp->U.Element.row && p_a_row_temp->U.Element.col == prow_temp->U.Element.col) {
//如果找到了这个元素, 行列一样的话
p_a_row_temp->U.Element.value += prow_temp->U.Element.value;
equalFlag = 1;
break;
}
}
if (equalFlag ==0 && p_a_row_temp->U.Element.row == prow_temp->U.Element.row && p_a_row_temp->U.Element.col == prow_temp->U.Element.col) {
//如果找到了这个元素, 行列一样的话
p_a_row_temp->U.Element.value += prow_temp->U.Element.value;
continue;
}
if (equalFlag==0) {
//如果这个元素a中没有的话,那就将此元素插入到a中
lastrowFlag = 0;
lastcolFlag = 0;
a.Head->U.Element.value++;
ptemp = NewNode();
ptemp->Tag = E;
ptemp->U.Element.row = prow_temp->U.Element.row;
ptemp->U.Element.col = prow_temp->U.Element.col;
ptemp->U.Element.value = prow_temp->U.Element.value;
ptemp->Right = NULL;
ptemp->Down = NULL;
//先把行搞定
p_a_row_temp1 = a.HD[prow_temp->U.Element.row]; //刷新 p_a_row_temp 为 a的行表头
for (; p_a_row_temp1->Right != a.HD[prow_temp->U.Element.row]; p_a_row_temp1 = p_a_row_temp1->Right) {
if (p_a_row_temp1->Right->U.Element.col > ptemp->U.Element.col) {
ptemp->Right = p_a_row_temp1->Right;
p_a_row_temp1->Right=ptemp;
lastrowFlag = 1;
break;
}
}
if (lastrowFlag==0) {
ptemp->Right= a.HD[prow_temp->U.Element.row];
p_a_row_temp1->Right = ptemp; // 这时 p_a_row_temp1 指代 a中当前行的最后一个结点
}
//再把列搞定
p_a_col_temp = a.HD[prow_temp->U.Element.col];
for (; p_a_col_temp->Down != a.HD[prow_temp->U.Element.col]; p_a_col_temp = p_a_col_temp->Down) {
if (p_a_col_temp->Down->U.Element.row > ptemp->U.Element.row) {
ptemp->Down = p_a_col_temp->Down;
p_a_col_temp->Down = ptemp;
lastcolFlag = 1;
break;
}
}
if (lastcolFlag == 0) {
ptemp->Down = a.HD[prow_temp->U.Element.col];
p_a_col_temp->Down = ptemp; // 这时 p_a_row_temp1 指代 a中当前行的最后一个结点
}
}
}
}
result = a;
return result;
}
void PrintLinkedMatrix(LinkedMatrix A) {
MNode* ptemp, * prow_temp;
ptemp = A.Head->Right;
for (; ptemp != A.Head; ptemp= ptemp->U.Next) {
prow_temp = ptemp->Right;
for (; prow_temp != ptemp; prow_temp = prow_temp->Right) {
printf("%d %d %d\n", prow_temp->U.Element.row, prow_temp->U.Element.col, prow_temp->U.Element.value);
}
}
}
void main() {
LinkedMatrix A, B,addRes;
A = MRead();
PrintLinkedMatrix(A);
printf("**********************\n");
B = MRead();
PrintLinkedMatrix(B);
printf("**********************\n");
addRes = Add2LinkedMatrix(A, B);
PrintLinkedMatrix(addRes);
system("pause");
}
UP主是一名程序员,再次考研复习中,需要讨论问题一起复习的请联系我。