稀疏矩阵——三元组十字链表的C语言实现
粗浅学习稀疏矩阵——三元组十字链表。
代码实现了新建矩阵、矩阵相加、矩阵逆置和矩阵打印在屏幕上。
惭愧于命名规范和编程水平,不足的地方请大牛们多多指教:
直接上代码
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;上纠结了许久,在写转置的过程中指针的乱指、眼瞎让我花了很多时间在调试上,下一次再写需理清思路,考虑周全再下手也不迟。