#단순 연결리스트
이번시간은 연결리스트에 대해서 알아보겠습니다. 먼저 리스트란, 자료구조의 한 종류로써 순차적으로 data를 저장하고 순차적으로 data를 처리하는데 유리합니다. 연결리스트에도 종류는 다양합니다. (단순,원형,이중) 하지만, 저는 연결리스트를 단순 연결리스트로 생각하고 설명하겠습니다.
<c언어로 만드는 자료구주와 적용알고리즘 해설서 출처>
리스트에는 배열리스트, 연결리스트가 있는데, 배열리스트는 얼마나 리스트가 생기고 줄어드는지 미리 파악할 수 없기에 단순히 미리 크기 값을 할당합니다. 따라서 메모리 누수가 발생할 가능성이 있습니다. 너무 큰 크기로 배열을 잡았다가, 실제 다 사용하지 않는다면 메모리가 낭비되기 때문이죠. 하지만 연결리스트는 필요시에만 메모리를 동적으로 할당하기 때문에 메모리 누수가 발생되지 않고 유연합니다.
또한, 배열리스트는 물리적으로 data가 순차적으로 되어있는 반면 연결리스트는 data가 물리적으로 순차적이지 않을 수 있습니다. 즉 각각 data의 값들이 저장되는 메모리 조각들이 포인트로 인해 논리적으로 순차적이게 보일 뿐 사실상 물리적으로는 순차적이지 않는 특징이 있습니다.
또 연결리스트는 단순 data가 아닌 노드라는 것으로 저장합니다. 노드 안에는 data와 link를 할 수 있는 포인터로 구성되어 있습니다. 또한, 자주 변경되는 상황에서는 배열리스트보단 연결리스트가 비용적인 측면에서 효율적입니다.
끝으로 탐색에서 연결리스트는 노드의 개수가 n개 일 경우 시간 복잡도가 O(n)인데 비해 배열리스트는 O(1)을 가집니다.
요약을 하자면, 연결리스트가 배열리스트와 비교했을 때 가지는 장단점은 다음과 같습니다.
장점
- 추가 원소 이동 연산 불필요
- 최대 원소 개수 지정 불필요
단점
- 구현의 어려움(포인터 연산, 동적 메모리 할당, 메모리 관리 등)
- 탐색 연산의 비용이 높음
이제 실제로 구현해보겠습니다. 저는 오랜만에 공부도 할겸 C언어로 구현해보겠습니다. 한 가지 알아둘 점은, 배열리스트는 배열을 이용해 구현하고, 리스트는 구조체와 포인터를 이용해 구현한다는 점입니다. 따라서 구조체와 포인터에 대한 이해는 필수입니다. ㅎㅎ
저는 단순하게 처음에 노드를 추가/삭제하는 함수, 원하는 위치에 노드를 삽입하는 함수, 노드 전부를 출력하는 함수, 메모리 반납을 하는 함수, 원하는 data값이 어디에 위치하는지 탐색하는 함수 정도로 구현해봤습니다.
// CProject.cpp: 콘솔 응용 프로그램의 진입점을 정의합니다. // #include <stdio.h> #include <stdlib.h> //malloc을 위함 struct NODE { struct NODE *next; int data; }; void init(struct NODE* head) { head->data = NULL; head->next = NULL; } void addFrist(struct NODE* target, int data) { struct NODE* newNode = (NODE*)malloc(sizeof(NODE)); newNode->next = target->next; newNode->data = data; target->next = newNode; } void removeFrist(struct NODE* target) { struct NODE *removeNode = target->next; target->next = removeNode->next; free(removeNode); } void insertNode(struct NODE* head, int object, int data) { struct NODE* curr = head; struct NODE* newNode = (NODE*)malloc(sizeof(NODE)); for (int i = 0; i < object-1; i++) { struct NODE *next = curr->next; curr = next; } //printf("%d\n", curr->data); newNode->next = curr->next; newNode->data = data; curr->next = newNode; } void searchNode(struct NODE* head, int data) { struct NODE* curr = head->next; int n = 1; while (curr != NULL) { struct NODE *next = curr->next; if (data == (int)(curr->data)) { printf("%d 번째에 있습니다.\n",n); } n++; curr = next; } } void printNode(struct NODE* head) { struct NODE *curr = head->next; while (curr != NULL) { printf("%d ->", curr->data); curr = curr->next; } printf("\n"); } void freeNode(struct NODE* head) { struct NODE *curr = head->next; curr = head->next; while (curr != NULL) { struct NODE *next = curr->next; free(curr); curr = next; } free(head); } struct NODE *head; int main() { struct NODE *head = (NODE*)malloc(sizeof(NODE)); init(head); addFrist(head, 10); addFrist(head, 20); addFrist(head, 30); addFrist(head, 40); removeFrist(head); printNode(head); insertNode(head,1,50); printNode(head); searchNode(head,50); freeNode(head); return 0; }
결과 콘솔창
'전공지식 > Data structure / Algorithm' 카테고리의 다른 글
[Algorithm] 이진탐색(Binary Search) (0) | 2017.11.19 |
---|---|
[Data structure] 이진트리 (Binary Tree) (2) | 2017.11.10 |
[Sort] 버블정렬 (Bubble Sort) (0) | 2017.10.25 |
[Sort] 선택정렬 (Select Sort) (0) | 2017.10.24 |
[Sort] 삽입정렬 (Insert Sort) (0) | 2017.10.24 |
댓글