稀疏矩陣——三元組十字連結串列的C語言實現
阿新 • • 發佈:2018-12-19
粗淺學習稀疏矩陣——三元組十字連結串列。 程式碼實現了新建矩陣、矩陣相加、矩陣逆置和矩陣列印在螢幕上。 慚愧於命名規範和程式設計水平,不足的地方請大牛們多多指教: 直接上程式碼 crosslist.h
#ifndef _crosslist_h_ #define _crosslist_h_ #include "malloc.h" #include "stdio.h" typedef struct OLNode { int row, col; int value; struct OLNode *right; struct OLNode *down; }OLNode, *OLink; typedef struct { OLink *row_head; //行指標 OLink *col_head; //列指標 int row, column; //用於標識當前矩陣的行和列 }CrossList; //建立一個矩陣 int CreateCrossList(CrossList *M, int row, int column) { int i; if (row <= 0 || column <= 0) return 0; //採用十字連結串列儲存結構,建立稀疏矩陣 M->row = row; M->column = column; if (!(M->row_head = (OLink *)malloc((row + 1)*sizeof(OLink)))) return 0; if (!(M->col_head = (OLink *)malloc((column + 1)*sizeof(OLink)))) return 0; //對行表頭和列表頭賦值為空 for (i = 0; i <= row; i++) M->row_head[i] = NULL; for (i = 0; i <= column; i++) M->col_head[i] = NULL; return 1; } //新增一個元素 void addCrossList(CrossList *M, int row, int column, int value) { OLNode* head; OLNode* q; OLNode* pre; q = (OLNode *)malloc(sizeof(OLNode)); q->row = row; q->col = column; q->value = value; q->right = NULL; q->down = NULL; //先找行如果有標識出來,頭指標為空 if ((M->row_head)[row] == NULL) { head = (OLNode *)malloc(sizeof(OLNode)); (M->row_head[row]) = head; head->down = NULL; head->value = -1; head->right = q; q->right = NULL; } else { pre = M->row_head[row]; while (pre->right && pre->right->col <= column) pre = pre->right; //判斷是否已存在該點,若有則相加即可 if (pre->row == row && pre->col == column) { pre->value += value; return; } q->right = pre->right; pre->right = q; } //再插列如果有標識出來 if (M->col_head[column] == NULL) { M->col_head[column] = (OLNode *)malloc(sizeof(OLNode)); M->col_head[column]->down = NULL; M->col_head[column]->down = q; q->down = NULL; } else { for (pre = M->col_head[column]->down; pre->down &&pre->down->row < row; pre = pre->down); q->down = pre->down; pre->down = q; } } //按座標(x,y)將每個值打印出來 void printAll(CrossList M) { int i, row, col; row = M.row; col = M.column; OLNode* q = NULL; for (i = 0; i <= row; i++) { //天坑!若為空,也就不能得到->right if (M.row_head[i] == NULL) continue; for (q = M.row_head[i]->right; q != NULL; q = q->right) printf("(%d,%d)=%d ", q->row, q->col, q->value); printf("\n"); } printf("\n"); } //按座標(x,y)將每個值打印出來 void printAll2(CrossList M) { int i, row, col; row = M.row; col = M.column; OLNode* q = NULL; for (i = 0; i <= col; i++) { if (M.col_head[i] == NULL) continue; for (q = M.col_head[i]->down; q != NULL; q = q->down) printf("(%d,%d)=%d ", q->row, q->col, q->value); printf("\n"); } printf("\n"); } //N = N+M,矩陣相加,這裡程式碼要添上對同型矩陣的判斷,懶癌。。。 void add(CrossList *N, CrossList M) { int i; OLNode* q = NULL; for (i = 0; i < M.row; i++) { if (M.row_head[i] == NULL) continue; for (q = M.row_head[i]->right; q != NULL; q = q->right) addCrossList(N, q->row, q->col, q->value); } } //矩陣逆置 int transpose(CrossList *M) { OLink *trow, *tcol; OLNode *q, *x; int i, temp; if (!(trow = (OLink *)malloc((M->column + 1)*sizeof(OLink)))) return 0; if (!(tcol = (OLink *)malloc((M->row + 1)*sizeof(OLink)))) return 0; for (i = 0; i <= M->column; i++) { //對應行的空指標轉成列指標 if (M->col_head[i] == NULL) { trow[i] = NULL; continue; } //賦列表頭給新行表頭 trow[i] = M->col_head[i]; x = trow[i]->right; trow[i]->right = trow[i]->down; trow[i]->down = x; } for (i = 0; i <= M->row; i++) { //對應列的空指標轉成行指標 if (M->row_head[i] == NULL) { tcol[i] = NULL; continue; } //賦行表頭給新列表頭 tcol[i] = M->row_head[i]; x = tcol[i]->right; tcol[i]->right = tcol[i]->down; tcol[i]->down = x; } for (i = 0; i < M->row; i++) { if (M->row_head[i] == NULL) continue; for (q = M->row_head[i]->down; q != NULL; q = q->down) { //交換行列號 temp = q->row; q->row = q->col; q->col = temp; //交換行列指標 x = q->down; q->down = q->right; q->right = x; } } //釋放指標陣列 free(M->col_head); free(M->row_head); M->col_head = tcol; M->row_head = trow; return 1; } #endif
main.c
#include "stdio.h" #include "crosslist.h" int main(void) { CrossList cr1, cr2; printf("建立矩陣1\n"); CreateCrossList(&cr1, 15,15); addCrossList(&cr1, 4, 4, 22); addCrossList(&cr1, 3, 5, 24); addCrossList(&cr1, 4, 5, 23); addCrossList(&cr1, 2, 5, 2); addCrossList(&cr1, 4, 2, 32); printAll(cr1); printf("建立矩陣2\n"); CreateCrossList(&cr2, 15, 15); addCrossList(&cr2, 1, 4, 22); addCrossList(&cr2, 3, 5, 24); addCrossList(&cr2, 4, 5, 23); printAll(cr2); printf("矩陣2加到矩陣1\n"); add(&cr1, cr2); printAll(cr1); printf("矩陣1轉置\n"); transpose(&cr1); printAll(cr1); getchar(); return 0; }
感想:在二級指標上 typedef struct OLNode{}*OLink;與OLink *row_head;上糾結了許久,在寫轉置的過程中指標的亂指、眼瞎讓我花了很多時間在除錯上,下一次再寫需理清思路,考慮周全再下手也不遲。