前兩天在看課外的數據結構的書預習新知識的時候看到了一個特別有意思的稀疏矩陣問題,於是就按照書上的用C語言來實現之,剛學習數據結構的小白,請大佬們輕噴,下面上圖:
下面是代碼:
#include<stdio.h>
#include<stdlib.h> #define ElementType int typedef struct GNode *GList; struct GNode{ int row; //所在行數 int col; //所在列數 GList right; GList down; int Tag; /*Tag作為標志域,區分union中是什么數據:0表示節點是頭節點head,1表示節點是非零元素節點Term*/ ElementType value; //數據域 }; GList head; //制作空表並初始化行和列的頭結點,返回頭指針 GList MakeEmpty(int row_number,int col_number){ GList PtrL; PtrL = (GList)malloc(sizeof(struct GNode)); PtrL->row = row_number; //頭結點的row和col存儲稀疏矩陣的總行數和總列數 PtrL->col = col_number; PtrL->Tag = 0; GList temp_row = PtrL; GList temp_col = PtrL; for (int i = 0; i < row_number; ++i){ temp_row->down = (GList)malloc(sizeof(struct GNode)); temp_row = temp_row->down; temp_row->Tag = 0; temp_row->row = 0; temp_row->col = 0; temp_row->right = temp_row; } for (int i = 0; i < col_number; ++i){ temp_col->right = (GList)malloc(sizeof(struct GNode)); temp_col = temp_col->right; temp_col->Tag = 0; temp_col->row = 0; temp_col->col = 0; temp_col->down = temp_col; } temp_col->right = PtrL; //這邊跟書里面的不同,我直接將兩個尾端都指向頭結點了,也方便后面遍歷操作 temp_row->down = PtrL; return PtrL; } /*下面是用來找頭結點的兩個函數*/ GList find_col_head(int col){ GList head_col = head; for (int i = 0; i < col; ++i) { head_col = head_col->right; } return head_col; } GList find_row_head(int row){ GList head_row = head; for (int i = 0; i < row; ++i){ head_row = head_row->down; } return head_row; } /*下面是具體定位節點位置的兩個函數*/ GList find_row(int row){ GList r = find_row_head(row); while(r->right->row < row && r->right->Tag == 1){ r = r->right; } return r; } GList find_col(int col){ GList c = find_col_head(col); while(c->down->col < col && c->down->Tag == 1){ c = c->down; } return c; } //插入節點 void InsertNode(ElementType X,int row,int col){ GList p = (GList)malloc(sizeof(struct GNode)); p->row = row; p->col = col; p->Tag = 1; p->value = X; GList c = find_col(col); GList r = find_row(row); /*若節點已經存在,則直接覆蓋value值*/ if(c->down->col == col && r->right->row == row){ c->value = X; } else{ p->down = c->down; c->down = p; p->right = r->right; r->right = p; } } /*通過行列來刪除某個節點*/ void deleteNode(int row,int col){ GList r = find_row(row); GList c = find_col(col); GList temp; if(r->right->row == row && c->down->col == col){ temp = r->right; r->right = temp->right; temp = c->down; c->down = temp->right; free(temp); printf("刪除節點成功\n"); } else{ printf("刪除行為%d,列為%d的節點失敗:未找到節點\n",row,col ); } } /*逐行搜索遍歷輸出節點*/ void printAll(){ GList r = head->down; while(r->down != head){ GList temp_r = r; while(temp_r->right->Tag != 0){ printf("row:%d,col:%d,value:%d\n",temp_r->right->row,temp_r->right->col,temp_r->right->value); temp_r = temp_r->right; } r = r->down; } } /*輸出稀疏矩陣,可能會在行數和列數比較大的時候發生錯位,主要因為終端窗口不夠大而且不能橫向拉伸*/ void printMatrix(){ printf("-------------------------------------------------------------------------\n"); GList r = head->down; for(int i = 0;i <= head->col;++i){ printf("%d\t",i); } int count_row = 1; while(r != head){ printf("\n%d|\t",count_row); GList temp_r = r; int count = 0; while(temp_r->right->Tag != 0){ for (int i = 1; i < temp_r->right->col - count; ++i){ printf("\t"); } count = r->right->col; printf("%d\t",temp_r->right->value); temp_r = temp_r->right; } printf("\n"); r = r->down; count_row++; } printf("-------------------------------------------------------------------------\n"); } /*測試*/ int main(){ head = MakeEmpty(8,8); InsertNode(9,7,8); InsertNode(666,8,8); InsertNode(123,7,7); InsertNode(123111,2,6); InsertNode(1123,3,5); printMatrix(); InsertNode(12341,2,6); deleteNode(7,7); printAll(); printMatrix(); return 0; }
應該還是有很多可以優化的地方的,下次再碰到這樣的問題的時候在回過頭來看看吧