1. 程式人生 > >稀疏矩陣——三元組十字連結串列的C語言實現

稀疏矩陣——三元組十字連結串列的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;上糾結了許久,在寫轉置的過程中指標的亂指、眼瞎讓我花了很多時間在除錯上,下一次再寫需理清思路,考慮周全再下手也不遲。