Stack, Queue 에 이어서 Linked List.

사실 이걸 먼저 포스팅 했어야 되는데 ㅡ_ㅡ; 어쩌다보니 순서가 바꼈다.



<< Linked List >>


(1) 포인터를 이용하여 데이터를 저장한다.


(2) Array 와는 다르게 물리적 구조가 순차적이지 않다.

Array 의 경우, 메모리에 순차적으로 저장되지만 

Linked List 는 포인터를 이용하기 때문에 데이터가 메모리에 순차적으로 저장되어 있지 않다.


(3) Linked List 의 기본 단위는 Node 구조체로 이루어져 있다.

Node 구조체에 데이터와 Link 를 저장해놓는다.


(4) 각 Node 의 생성은 동적 할당으로 이루어지고, 

첫번째 Node 를 가르키는 노드인 Header Node 가 존재한다.

(5) Linked List 에는 3가지 종류가 있다.

- Single Linked List / Circular Linked List / Double Linked List

- 각 리스트 별로 삽입(Insert), 삭제(Remove) 연산이 있고, 

각 연산 별로 Header / Middle / Tail 에서 일어나는 경우를 살펴볼 것이다.

(이미지 출처 : http://blog.naver.com/zkd1750/90183988309)


연산 처리 과정을 그림으로 이해하기 쉽게 정리하면 좋겠지만

이미 다 배운 내용을 정리하는 차원이라 굳이 그리지는 않겠다. 귀찮다.



1. Single Linked List


(1) Insert

- Header

[Head] -> [A] -> [B] -> [C:Tail]  이런 상태에서

[Head] -> [?] -> [A] -> [B] -> [C:Tail] 로 [?] 라는 노드를 삽입할 것이다.


방법은 간단하다. 다음과 같은 순서로 노드의 삽입이 이루어진다.

① [?].next = [Head].next

② [Head].next = [?]


- Middle

[Head] -> [A] -> [B] -> [C:Tail]  이런 상태에서

[Head] -> [A] -> [B] -> [?] -> [C:Tail] 로 [?] 라는 노드를 삽입할 것이다.


① [?].next = [B].next

② [B].next = [?]


- Tail

[Head] -> [A] -> [B] -> [C:Tail]  이런 상태에서

[Head] -> [A] -> [B] -> [C] -> [?:Tail] 로 [?] 라는 노드를 삽입할 것이다.


① [C:Tail].next = [?]

② [?].next = NULL

(1번과 2번의 순서가 바뀌어도 상관은 없다.)

③ *tail = [?]


(2) Remove

- Header

[Head] -> [A] -> [B] -> [C:Tail]  이런 상태에서 [A] 를 삭제하면,

[Head] -> [B] -> [C:Tail]  이렇게 된다.


① [Head].next = [A].next    또는    [Head].next = [Head].next.next

② [A].next = NULL    // ① 연산으로 [A]를 가르키는 노드가 없으니 ① 연산 전에 [A]를 따로 저장

③ free([A])


- Middle

[Head] -> [A] -> [B] -> [C:Tail]  이런 상태에서 [B] 를 삭제하면,

[Head] -> [A] -> [C:Tail]  이렇게 된다.


① [A].next = [B].next    또는    [A].next = [A].next.next

② [B].next = NULL    // ① 연산으로 [B]를 가르키는 노드가 없으니 ① 연산 전에 [B]를 따로 저장

③ free([B])


- Tail

[Head] -> [A] -> [B] -> [C:Tail]  이런 상태에서 [C:Tail] 를 삭제하면,

[Head] -> [A] -> [B:Tail]  이렇게 된다.


① free([B].next)    // next 가 tail 인 녀석을 찾아서 메모리 해제

② [B].next = NULL

③ *tail = [B]




2. Circular Linked List


(1) Insert

- Header

[Head] -> [A] -> [B] -> [C:Tail] -> [A]  이런 상태에서

[Head] -> [?] -> [A] -> [B] -> [C:Tail] -> [?] 로 [?] 라는 노드를 삽입할 것이다.


① [?].next = [Head].next

② [Head].next = [?]

③ [C:Tail].next = [?]


- Middle

S.L.L 와 동일하다.


- Tail

[Head] -> [A] -> [B] -> [C:Tail] -> [A]  이런 상태에서

[Head] -> [A] -> [B] -> [C] -> [?:Tail] -> [A] 로 [?] 라는 노드를 삽입할 것이다.


① [?].next = [C:Tail].next    또는    [?].next = [Head].next

② [C:Tail].next = [?]

③ *tail = [?]


(2) Remove

- Header

[Head] -> [A] -> [B] -> [C:Tail] -> [A]  이런 상태에서 [A] 를 삭제하면,

[Head] -> [B] -> [C:Tail] -> [B]  이렇게 된다.


① [Head].next = [A].next    또는    [Head].next = [Head].next.next

② [C:Tail] = [Head].next

③ [A].next = NULL    // ① 연산으로 [A]를 가르키는 노드가 없으니 ① 연산 전에 [A]를 따로 저장

④ free([A])


- Middle

S.L.L 와 동일하다.


- Tail

[Head] -> [A] -> [B] -> [C:Tail] -> [A]  이런 상태에서 [C:Tail] 를 삭제하면,

[Head] -> [A] -> [B:Tail] -> [A]  이렇게 된다.


① [B].next.next = NULL    // next 가 Tail 인 녀석을 찾아보니 [B]. 즉, [B].next = Tail

연산 후 모습 : [Head] -> [A] -> [B] -> [C:Tail]

② free([B].next)

연산 후 모습 : [Head] -> [A] -> [B] -> [ ]

③ [B].next = [Head].next 

연산 후 모습 : [Head] -> [A] -> [B] -> [A]

④ *tail = [B]

[Head] -> [A] -> [B:Tail] -> [A]




3. Double Linked List

- previous, next 가 존재해서 조금 귀찮다.

- 어떤 책은 prev / next 로 하는 책도 있고, left /right 로 하는 책도 있는데 전자를 선택하겠다.

- 앞에 보았던 노드의 구조가 [Data, Next] 라면 지금은 [Prev, Data, Next] 정도 되겠다.


(1) Insert

- Header

[Head] ↔ [A]  [B]  [C:Tail]  이런 상태에서

[Head]  [?]  [A]  [B]  [C:Tail]  [?] 라는 노드를 삽입할 것이다.


① [?].prev = [Head] 

② [?].next = [Head].next

③ [Head].next = [?]

④ [?].next.prev = [?]


- Middle (Header 와 똑같다고 보면 된다)

[Head] ↔ [A]  [B]  [C:Tail]  이런 상태에서

[Head]  [A]  [?]  [B]  [C:Tail]  [?] 라는 노드를 삽입할 것이다.


① [?].prev = [A] 

② [?].next = [A].next

③ [A].next = [?]

④ [?].next.prev = [?]


- Tail

[Head] ↔ [A]  [B]  [C:Tail]  이런 상태에서

[Head]  [A]  [B]  [C]  [?:Tail]  [?] 라는 노드를 삽입할 것이다.


① [?].prev = [C:Tail] 

② [?].next = NULL

③ [C:Tail].next = [?]

④ *tail = [?]


(2) Remove

- Header

[Head]  [A]  [B]  [C:Tail이런 상태에서 [A] 를 삭제하면,

[Head]  [B]  [C:Tail] 이렇게 된다.


① [Head].next = [A].next    또는    [Head].next = [Head].next.next

② [Head].next.prev = [Head]

③ [A].prev = NULL    //  연산으로 [A]를 가르키는 노드가 없으니 ① 연산 전에 [A]를 따로 저장

④ [A].next = NULL

⑤ free([A])


- Middle (Header 와 똑같다고 보면 된다)

[Head]  [A]  [B]  [C:Tail이런 상태에서 [B] 를 삭제하면,

[Head]  [A [C:Tail] 이렇게 된다.


① [A].next = [B].next    또는    [A].next = [A].next.next

② [A].next.prev = [A]

③ [B].prev = NULL    // ①,  연산으로 [B]를 가르키는 노드가 없으니 ① 연산 전에 [B]를 따로 저장

④ [B].next = NULL

⑤ free([B])


Tail

[Head]  [A]  [B]  [C:Tail이런 상태에서 [C] 를 삭제하면,

[Head]  [A]  [B:Tail] 이렇게 된다.


① [B].next.prev = NULL    // next 가 Tail 인 녀석을 찾아보니 [B]. 즉, [B].next = Tail

② free([B].next)

③ [B].next = NULL

④ *tail = [B]



# Linked List 사용 사례 : 

- Stack, Queue, Tree 구현할 때 사용될 수 있다.

- 많이 쓰이기는 하는데 막상 사용 예제를 검색해보면 딱히 나오지는 않는 것 같다...



아, 드럽게 많네.

그림 별로 안 올려도 포스팅 하는데 겁나 오래걸린다ㅠㅠ


( + 이 포스팅에서 free 나 *tail 은 C언어로 쓰인 자료 참고하느라 추가했다.

원래 Java 로 코드를 한번 짜봤었는데 C 로는 안 해봐서 조금 지저분해도 써봤다. )


'Programming' 카테고리의 다른 글

[C]printf()에서 "%ul"와 "%lu"의 차이?  (0) 2015.07.05
언리얼엔진4 : DataTable 오브젝트 생성하기  (0) 2014.09.22
Delegate (대리자)  (1) 2013.12.20
[Python, C#]Lambda Form  (0) 2013.12.19
PHP vs. Ruby vs. Python  (0) 2013.12.19
by kelicia 2014. 4. 25. 02:36