Data Structure – Linked list & Sparse Matrix (transpose)

연결리스트를 통한 희소행렬 표현

희소행렬(Sparse matrix)이 다음 그림과 같이 연결리스트를 이용하여 표현되어 있다.
각 노드는 row,col,val 필드를 가지는데 각각 행 번호, 열 번호, 원소의 값을 나타낸다. 또한 이 노드의 Rlink와 Dlink는 각각 같은 행과 열에서 0이 아닌 다음 원소를 나타내는 노드의 주소를 가지는 필드이다. rowHead[i]는 i번째 행의 해드 노드를 나타내고, colHead[j]는 j번째 열의 해드 노드를 나타낸다.

아래에 연결리스트를 통한 희소 행렬 및 전치 행렬(transpose)을 C언어로 구현해보았다.

Linked List & Sparse Matrix.c

#pragma warning(disable:4996)
#include <stdio.h>
#include <stdlib.h>

typedef struct element {
	int row;
	int col;
	int val;
	struct element* Dlink;
	struct element* Rlink;
}element;

typedef struct Head {
	element* ptr;
}Head;

// 헤드 만들기 
Head* make_head(int num) {
	int i;
	Head* head = (Head*)malloc(sizeof(Head)*num);

	for (i = 0; i < num; i++)
		head[i].ptr = 0;
	return head;
}

// 리스트 삽입 
void insert(Head* rowHead, Head* colHead, int row, int col, int val) {
	element* e = (element*)malloc(sizeof(element));
	e->row = row;
	e->col = col;
	e->val = val;
	e->Rlink = e->Dlink = 0;

	// insert_first
	if (rowHead[row].ptr == 0)
		rowHead[row].ptr = e;
	// insert_last
	else {
		element* ptr = rowHead[row].ptr;
		while (ptr->Rlink != NULL) {
			ptr=ptr->Rlink;
		}
		ptr->Rlink = e;
	}

	// insert_first
	if (colHead[col].ptr == 0)
		colHead[col].ptr = e;
	// insert_last
	else {
		element* ptr = colHead[col].ptr;
		while (ptr->Dlink != NULL) {
			ptr = ptr->Dlink;
		}
		ptr->Dlink = e;
	}
}

// 리스트 출력 
void print_list(Head* rowHead, Head* colHead,int rows, int cols) {
	int i;
	// print rowHead list 
	for (i = 0; i < rows; i++) {
		printf("\nrowHead[%d]에 해당하는 리스트 출력:",i);
		element* ptr = rowHead[i].ptr;
		if (ptr == NULL)
			printf(" x");
		while (ptr != NULL) {
			printf("[%d %d %d] ", ptr->row, ptr->col, ptr->val);
			ptr = ptr->Rlink;
		}
	}
	printf("\n");

	// print colHead list 
	for (i = 0; i < cols; i++) {
		printf("\ncolHead[%d]에 해당하는 리스트 출력:", i);
		element* ptr = colHead[i].ptr;
		if (ptr == NULL)
			printf(" x");
		while (ptr != NULL) {
			printf("[%d %d %d] ", ptr->row, ptr->col, ptr->val);
			ptr = ptr->Dlink;
		}
	}
	printf("\n");

}

// 전치행렬 만들기 
void transpose(Head** rowHead_ptr, Head** colHead_ptr,int* rows,int* cols) {
	// element 노드의 위치가 전치행렬된 상태가 되도록 
	Head* tmp = *rowHead_ptr;
	*rowHead_ptr = *colHead_ptr;
	*colHead_ptr = tmp;

	// 행의 개수와 열의 개수를 교환 
	int temp = *rows;
	*rows = *cols;
	*cols = temp;

	// 기존에 Rlink였던 것을 Dlink로 변경, Dlink였던 것을 Rlink로 변경 
	int i;
	element* ptr;
	tmp = *rowHead_ptr; // 바뀐 위치를 기준으로 판단함 
	for (i = 0; i < *rows; i++) {
		ptr = tmp[i].ptr;
		while (ptr != NULL) {
			if ((ptr->Rlink != NULL) || (ptr->Dlink != NULL)) {
				element* t = ptr->Rlink;
				ptr->Rlink = ptr->Dlink;
				ptr->Dlink = t;
			}
			ptr = ptr->Rlink;
		}
	}

	// element정보(행,열)도 교환 
	for (i = 0; i < *rows; i++) {
		ptr = tmp[i].ptr;
		while (ptr != NULL) {
			int t = ptr->row;
			ptr->row = ptr->col;
			ptr->col = t;
			ptr = ptr->Rlink;
		}
	}
}

int main() {
	int rows, cols;
	rows = cols = 0;

	printf("행과 열의 개수를 입력하세요:");
	scanf("%d %d",&rows,&cols);

	Head* rowHead = make_head(rows); // rowHead 동적 배열
	Head* colHead = make_head(cols); // colHead 동적 배열
	
	int terms = 0;
	printf("0이 아닌 항의 개수를 입력하세요:");
	scanf("%d", &terms);

	int i;
	for (i = 0; i < terms; i++) {
		printf("%d번째 항의 (행,열,값)을 입력하세요:",i); // 희소행렬 항 입력받기 
		int row, col, val;
		row = col = val = 0;
		scanf("%d %d %d", &row, &col, &val);
		insert(rowHead, colHead, row, col, val); // 입력된 값으로 리스트 삽입 
	}

	print_list(rowHead,colHead,rows,cols); // 리스트 출력 

	printf("\n전치행렬 결과:");
	transpose(&rowHead, &colHead,&rows,&cols); // 전치행렬 만들기 
	print_list(rowHead, colHead, rows, cols); // 리스트 출력 
}

Other Example

One thought on “Data Structure – Linked list & Sparse Matrix (transpose)

Leave a Reply

Your email address will not be published. Required fields are marked *