연결리스트를 통한 희소행렬 표현
희소행렬(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)”
Great post.