본문 바로가기
C/알고리즘

원형 연결 리스트

by 덤더리덤떰 2023. 9. 20.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>

typedef struct _listNode_ {
	int data;
	struct _listNode_* link;
}listNode;

typedef struct _linkedList_h_ {
	listNode* head;
}linkedList_h;

linkedList_h* createLinkedList_h() {
	linkedList_h* CL = (linkedList_h*)calloc(1, sizeof(linkedList_h));
	assert(CL != NULL);

	return CL;
}

void orderedInsert(linkedList_h* CL, int item) {
	listNode* newNode = (listNode*)calloc(1, sizeof(listNode));
	assert(newNode != NULL);
	newNode->data = item;
	newNode->link = NULL;

	//1. 첫번째로 삽입되는 경우
	if (CL->head == NULL) {
		CL->head = newNode;
		newNode->link = newNode;
		return;
	}
	//2. 가장 작은 값 삽입
	listNode* curNode = CL->head;
	if (curNode->data > item) {
		while (curNode->link != CL->head) {
			curNode = curNode->link;
		}
		newNode->link = CL->head;
		CL->head = newNode;
		curNode->link = newNode;
		return;
	}
	else {
		//3. 일반적인 경우
		listNode* preNode = CL->head;
		curNode = curNode->link;
		while (curNode != CL->head) {
			if (curNode->data > item) {
				newNode->link = preNode->link;
				preNode->link = newNode;
				return;
			}
			else {
				preNode = curNode;
				curNode = curNode->link;
			}
		}
		//4. 가장 큰 값을 삽입하는 경우
		if (curNode == CL->head) {
			preNode->link = newNode;
			newNode->link = CL->head;
			return;
		}
	}
}

void printList(linkedList_h* CL) {
	if (CL->head == NULL) {
		printf("공백 리스트입니다\n");
		return;
	}
	else {
		listNode* curNode = CL->head;
		printf("\n연결리스트 출력 : ");
		while (curNode->link != CL->head) {
			printf("%d ", curNode->data);
			curNode = curNode->link;
		}
		printf("\n");
	}
}

void insertFirstNode(linkedList_h* CL, int item) {
	listNode* newNode = (listNode*)calloc(1, sizeof(listNode));
	assert(newNode != NULL);
	newNode->data = item;
	newNode->link = NULL;
	listNode* curNode = CL->head;
	if (CL->head == NULL) {
		CL->head = newNode;
	}
	else {
		while (curNode->link != CL->head) {
			curNode = curNode->link;
		}

		newNode->link = CL->head;
		CL->head = newNode;
		curNode->link = newNode;
	}
}

listNode* searchNode(linkedList_h* CL, int item) {
	if (CL->head == NULL) {
		printf("공백리스트입니다\n");
		return;
	}
	else {
		int i = 0;
		listNode* curNode = CL->head;
		while (curNode->link != CL->head) {
			printf("Search try: %d\n", i++);
			if (curNode->data == item) {
				return curNode;
			}
			else {
				curNode = curNode->link;
			}
		}
	}
}

listNode* searchNode2(listNode * p, int item) {
	if (p == NULL) {
		return;
	}
	else {
		int i = 0;
		listNode* curNode = p;
		while (curNode->link!= p) {
			if (curNode->data == item) {
				printf("Search try: %d\n", i++);
				return curNode;
			}
			else {
				curNode = curNode->link;
			}
		}

		return;
	}
}

void insertMiddleNode(linkedList_h* CL, listNode* pre, int item) {
	if (pre == NULL) {
		return;
	}
	else {
		listNode* newNode = (listNode*)calloc(1, sizeof(listNode));
		assert(newNode != NULL);
		newNode->data = item;
		newNode->link = NULL;
		if (CL->head == NULL) {
			CL->head = newNode;
			newNode->link = newNode;
			return;
		}
		else {
			newNode->link = pre->link;
			pre->link = newNode;
		}
	}
}

void deleteNode(linkedList_h* CL, listNode* p) {
	if (CL->head == NULL) {
		printf("공백 리스트입니다\n");
		return;
	}
	else {
		if (p == NULL) {
			printf("삭제할 노드가 존재하지 않습니다\n");
			return;
		}
		else {
			listNode* pre = CL->head;
			if (p == CL->head) {
				//첫번째 노드를 삭제하는 경우
				while (pre->link != CL->head) {
					pre = pre->link;
				}

				//pre는 맨마지막 노드를 가리킴 
				pre->link = CL->head->link;
				CL->head = CL->head->link;
				free(p);
				p = NULL;
			}
			else {
				while (pre->link != p) {
					pre = pre->link;
				}
				pre->link = p->link;

				free(p);
				p = NULL;
			}
			
		}
	}
}

void freeLinkedList_h(linkedList_h * CL) {
	listNode* curNode = CL->head;
	listNode* preNode = curNode;
	while (preNode != NULL) {
		free(preNode);
		preNode = NULL;
		
		curNode = curNode->link;
		preNode = curNode;
	}
}

int main() {
	int i;
	int data;

	linkedList_h* CL;
	listNode* p;

	srand(time(NULL));

	CL = createLinkedList_h();
	printf("(1) 원형 연결 리스트 생성하기 ! \n");

	printf("(2) orderedInsert()를 이용하여 원형 연결 리스트에 데이터 노드 삽입\n");

	for (i = 0; i < 10; i++) {
		orderedInsert(CL, rand() % 100);
		printList(CL);
	}

	printf("\n(3) insertFirstNode를 이용하여 원형 연결 리스트에 데이터 노드 삽입\n");

	for (i = 1; i < 11; i++) {
		insertFirstNode(CL, i);
	}

	printList(CL);
	

	printf("(4) 5 탐색\n");
	p = searchNode(CL, 5);
	
	printf("(5) 4 재탐색\n");
	p = searchNode2(p, 4);
	
	printf("(6) 4 이후에 100넣기\n");
	insertMiddleNode(CL, p, 100);
	printList(CL);

	printf("(7) 10,100,9 순서대로 삭제\n");
	p = searchNode(CL, 10);
	deleteNode(CL, p);
	printList(CL);

	p = searchNode(CL, 100);
	deleteNode(CL, p);
	printList(CL);

	p = searchNode(CL, 9);
	deleteNode(CL, p);
	printList(CL);

	freeLinkedList_h(CL);
	if (CL != NULL) {
		free(CL);
	}

	printf("Done\n");
	return 0;
}