- 배열 : 동일한 타입의 변수가 연속된 공간에 존재하는 자료구조
- 연결 리스트 : 서로 다른 위치에 존재하는 데이터를 포인터를 이용해 연결한 자료구조
연결리스트 정의
자료구조는 탐색/삽입/삭제 모두 빠르게 수행될 수 있도록 개발되어져 왔다.
배열과 연결리스트는 모두 선형 자료구조에 속한다. (순서가 존재한다는 의미이다)
하지만 배열은 동일한 타입의 변수가 연속된 메모리에 저장되는 자료구조인 반면,
연결리스트(linked list)는 node로 구성되어 있고, 각 node는 pointer로 연결되어 있다.
여기서 pointer로 연결되어 있다는 것이 매우 중요한데, 이 의미는 node들이 아무 곳이나 존재할 수 있다는 의미이다.
노드는 데이터와 포인터로 구성되어 있다.
- 데이터 : 데이터를 저장하기 위한 공간
- 포인터 : 주소를 저장하는 변수 (singly linked list에서는 다음 node의 주소를 저장하고 있다)
- 다음 노드의 "주소"를 저장하기 때문에 배열과 달리 노드가 연속된 공간에 존재할 필요가 없다.
- 하지만 다음 node의 주소만을 저장하고 있기 때문에 "순차접근"만 가능하다
- 배열:
- 탐색 : O(1) - index를 통해 접근이 가능하므로 (임의 접근 가능)
- 삽입 : O(n)
- 삭제 : O(n)
- 연결리스트:
- sorted
- 탐색 : O(n) (비정렬되어 있는 것에 비해 평균적으로 2배 빠르다)
- 삽입 : Search(O(n)) + O(1)
- 삭제 : search(O(n)) + O(1)
- unsorted
- 탐색 : O(n)
- 삽입 : Search(O(n)) + O(1) or O(1)
- 삭제 : search(O(n)) + O(1)
- sorted
연결리스트 삽입, 삭제, 조회
linked list를 구현할 때 일반적으로 삽입, 삭제, 조회가 가능하도록 코드를 작성해야 한다.
- 1. 삽입
- 첫 번째 위치에 삽입하고자 하는 경우
- 삽입하고자 하는 노드 생성
- 삽입하고자 하는 노드의 다음 노드가 이전의 head가 되도록
- 마지막 위치에 삽입하고자 하는 경우
- 삽입하고자 하는 노드 생성
- 이전 tail노드가 자신을 가리키도록 설정
- 처음도 마지막도 아닌, 중간에 삽입하고자 하는 경우
- 삽입하고자 하는 노드(E) 생성
- 삽입하고자 하는 이전 위치의 노드(B)가 가리키는 노드(C)를 E도 가리키도록 설정
- 삽입하고자 하는 이전 위치의 노드(B)가 나(E)를 가리키도록 설정
- 삽입 끝!
- 첫 번째 위치에 삽입하고자 하는 경우
- 2. 삭제
- 만약 linked list에서 삭제를 한다면, (위의 예시에서 B-C-D 노드가 연결되어 있고, C를 삭제한다고 가정)
- 처음 노드를 삭제하고자 하는 경우
- 첫 번째 노드 따로 변수에 저장
- head가 두 번째 노드를 가리키도록 하면 된다
- 첫 번째 노드 메모리 해제
- 마지막 노드를 삭제하고자 하는 경우
- 마지막 노드 따로 변수에 저장
- 마지막 이전 노드가 NULL이 되도록 하면 된다
- 마지막 노드 메모리 해제
- 처음도 아닌, 마지막도 아닌 중간 노드 삭제하고자 하는 경우
- (B - C - D 에서 C 노드를 삭제하고자 하는 경우)
- B의 next 노드(C)를 따로 저장
- B의 next가 D 노드가 되도록 설정
- C 노드의 메모리 해제
- 3. 조회
- 1) linked list가 value 순서대로 정렬이 되어있는 경우
- 노드를 순차적으로 접근하며 내가 찾고자 하는 값과 비교하는데, 만약 어떤 node의 value가 내가 찾고자 하는 값보다 크다면 search 실패한 것이다.
- 이렇게 정렬이 되어있는 경우, 중간에 끊을 수 있다.
- 2) linked list가 value 순서대로 정렬이 되어있지 않은 경우
- 처음부터 끝까지 노드를 순차적으로 접근해가며 찾고자 하는 value를 탐색해야 하낟.
- 정렬이 되어있지 않은 경우, 중간에 끊을 수 없다.
- 1) linked list가 value 순서대로 정렬이 되어있는 경우
linked list 응용
- duumy node
- head와 tail 사용하여 예외처리를 보다 쉽게 할 수 있다.
- circular list
- 마지막의 노드가 첫 노드를 다시 가리키는 구조
- doubly linked list
- 양방향의 link가 존재
- 내 앞의 노드의 주소
- 내 뒤의 노드의 주소
- 양방향의 link가 존재
- linked list의 사용
- linked list의 search 성능은 좋지 않으므로 search가 거의 없고,
데이터를 순서대로 읽은 작업을 수행하는 경우에 linked list가 사용된다고 한다. - +) 배열과 같은 경우 삽입/삭제 성능이 좋지 않으므로
데이터가 잘 바뀌지 않고, 탐색이 자주 일어나는 경우에 사용된다- 예를 들어 사전과 같은 데이터
- linked list의 search 성능은 좋지 않으므로 search가 거의 없고,
#13. 팰린드롬 연결리스트
<fast runner, slow runner>
linked list의 경우 순차접근만 가능하기 때문에 따로 길이를 저장하지 않으면, 어디가 중간인 지 알 수 없다.
따라서 fast runner, slow runner 개념을 도입하였다.
slow runner는 1 step씩, fast runner는 2 step씩 이동하기 때문에 fast runner가 linked list의 끝 지점에 도달한 경우 slow runner는 중간 지점에 도달한다. 따라서 linked list의 중간 지점에 도달한 순간을 알 수 있게 되는 것이다.
#14. 두 정렬 리스트의 병합
재귀나 다른 코드에서 return할 때 return x or y, return x and y 과 같은 표현을 사용하는 것을 보고
이것이 의미하는 바에 대해 알아보았다.
return x or y : x가 false이면 y를 그렇지 않으면 x를 return
- x가 false -> false or y = y -> 따라서 y를 return
- x가 true -> true or y = true -> 따라서 x를 return
return x and y : x가 false이면 x를 그렇지 않으면 y를 return
- x가 false -> false and y = false -> 따라서 x를 return
- x가 true -> true and y = y -> 따라서 y를 return
(참고 : stackoverflow.com/questions/4477850/and-or-operators-return-value)
'다전공_컴퓨터공학 > 자료구조, 알고리즘' 카테고리의 다른 글
[자료구조] 우선순위 큐 (priority queue) (0) | 2020.12.20 |
---|---|
[자료구조] 데크 (double ended queue) (0) | 2020.12.20 |
[자료구조] 스택(Stack), 큐(Queue) (0) | 2020.11.25 |
[자료구조] 배열 (array) (0) | 2020.11.13 |
[자료구조] 파이썬 리스트, 딕셔너리 (0) | 2020.11.02 |