본문 바로가기
C, C++/과제창고

[C] 단일연결리스트 합병정렬 (singly linked list merge sort)

by 야호호코코 2018. 10. 14.
반응형

합병정렬에 관한 포스팅은 따로 알고리즘 창고에 하겠습니다.


보통 배열로 이루어진 정렬만 해서 애를 먹었습니다. 특히 분할하는 부분에서 힘들었는데, 그래도 깔끔한 방법을 찾아내 만들었습니다. 


구조체 및 함수설명


NODE : 단일연결리스트를 구성하는 노드 구조체

TMP : partition 함수를 위한 구조체. 두 개의 반환값을 받아내기 위함


NODE* addNode(int n) : 노드를 추가하는 함수. 단일연결리스트 끝부분에 계속 붙여나가므로 새 노드 값의 next는 항상 NULL이다.

void mergeSort(NODE **L, int k) : 합병정렬함수. 재귀방식으로 구성돼있다. L은 리스트의 시작 주소, k는 리스트의 크기이다.

NODE* merge(NODE *L1, NODE *L2) : 합병함수. 두 개의 리스트를 주소연결을 바꾸어 정렬된 하나의 리스트로 만들어 주소값으로 반환한다.

TMP partition(NODE *L, int k) : 분할함수. 하나의 리스트를 |L|-k 크기, k 크기의 부 리스트 두개로 만들어 반환한다. 따로 저장공간 할당 없이 주소값으로 반환한다.  


소스코드

#include <stdio.h>
#include <stdlib.h>


typedef struct node {

	int n;

	struct node *next;

}NODE;

typedef struct {

	NODE *L1;
	NODE *L2;

}TMP;

NODE* addNode(int n);
void mergeSort(NODE **, int);
NODE* merge(NODE *, NODE *);
TMP partition(NODE *, int);

void printAll(NODE *node);

int main() {

	NODE *head;

	int n;
	int i;
	NODE *tmp;
	int t;

	head = (NODE *)malloc(sizeof(NODE));
	head->next = NULL;

	scanf("%d", &n);

	for (i = 0, tmp = head; i < n; i++) {

		scanf("%d", &t);

		tmp->next = addNode(t);

		tmp = tmp->next;

	}

	mergeSort(&head->next, n);

	printAll(head->next);

}

NODE* addNode(int n) {

	NODE *new_node;

	new_node = (NODE *)malloc(sizeof(NODE));

	new_node->n = n;
	new_node->next = NULL;

	return new_node;

}

void mergeSort(NODE **L, int k) {

	NODE *L1 = NULL, *L2 = NULL;
	TMP tmp;

	NODE *i;

	if (k > 1 && *L != NULL) {

		tmp = partition(*L, k / 2);
		L1 = tmp.L1;
		L2 = tmp.L2;

		mergeSort(&L1, k / 2);
		mergeSort(&L2, (int)((k / 2.0) + 0.5));

		*L = merge(L1, L2);

	}

}

NODE* merge(NODE *L1, NODE *L2) {

	NODE *result = NULL;

	if (L1 == NULL) return L2;
	else if (L2 == NULL) return L1;

	if (L1->n < L2->n) {
		result = L1;
		result->next = merge(L1->next, L2);
	}
	else {
		result = L2;
		result->next = merge(L1, L2->next);
	}
	
	return result;

}

TMP partition(NODE *L, int k) {

	NODE *p;
	TMP result;
	NODE *L1, *L2;

	int i;

	p = L;
	L1 = L;

	for (i = 0; i < k - 1; i++) {
		p = p->next;
	}

	L2 = p->next;

	p->next = NULL;

	result.L1 = L1;
	result.L2 = L2;

	return result;

}

void printAll(NODE *node) {

	NODE *i = node;

	while (i != NULL) {
		printf(" %d", i->n);
		i = i->next;
	}

	printf("\n");

}


요즘 프로젝트 때문에 C 안하니까 어색해서 엄청 오래걸렸다. 틈틈이 연습해야겠다.

반응형

'C, C++ > 과제창고' 카테고리의 다른 글

[C] 학교과제_황제노드찾기  (0) 2018.07.01
[C] YesOrNo 아키네이터  (0) 2018.06.27