稀疏矩阵-正交链表-加法

两个以正交链表表示的稀疏矩阵的加法算法:

//自己写的亲测有效,经过严格测试:
#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主是一名程序员,再次考研复习中,需要讨论问题一起复习的请联系我。

Guess you like

Origin blog.csdn.net/m0_47472749/article/details/121525611