C语言实现稀疏矩阵的十字链表存储

前两天在看课外的数据结构的书预习新知识的时候看到了一个特别有意思的稀疏矩阵问题,于是就按照书上的用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; }

应该还是有很多可以优化的地方的,下次再碰到这样的问题的时候在回过头来看看吧

猜你喜欢

转载自www.cnblogs.com/RichieLeonhardt/p/10539116.html