稀疏矩阵-正交链表-加法
两个以正交链表表示的稀疏矩阵的加法算法:
//自己写的亲测有效,经过严格测试: #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主是一名程序员,再次考研复习中,需要讨论问题一起复习的请联系我。