검색(Searching)
- 특정 노드를 추가하거나 삭제를 위해서는 검색이 우선되야 한다.
- 다양한 알고리즘을 활용하는 경우, 최적 알고리즘 경로를 측정하는데 쓰인다.
- 검색하는 컬렉션이 무작위이고 정렬되지 않은 경우, 선형검색이 기본적인 검색방법이다.
1 |
|
Recursion(재귀)
- 알고리즘과 방법론에서 자주 언급되고, 중요한 개념이므로 반복하여 익숙해진다.
- 재귀의 개념은 수학적 사고에 기반하고, 코드를 작성하기 전에 문제를 해결하는 재호출 로직을 발견해야한다.
- 재귀 호출은 스택의 개념이 적용되며, 함수의 내부는 스택처럼 관리된다.(LIFO, 후입선출)
- 단점: 재귀를 사용하면 함수를 반복적으로 호출하는 상황이 벌어지므로, 메모리를 더 많이 사용한다.
- 수학적으로 개념이 복잡한 경우, 시간과 공간(메모리)복잡도 측면에서 효율이 안 좋더라도 재귀를 사용하여 문제를 해결하는 것이 좋다.
- 하위 문제를 쉽게 해결할 수 있을 때까지 문제를 더 작은 하위 문제로 나누는 것을 의미한다.
- 재귀적으로 다양한 문제를 해결할 수 있는데, 하나의 문제를 분할하면서 해결하고 해결 후 하나로 다시 합치는 ‘분할정복법’이 대표적이다.
- 재귀는 해결을 위한 특정 기능을 재호출한다는 측면이고, 분할 정복은 문제를 분할하고 해결하는 구체적인 방법론이다.
- 분할정복법을 활용하기 위해 재귀개념(기능 재호출)이 필요하다.
- 재귀에서 중점적으로 생각해야될 부분은 조건에 따른 반복계산이다.
조건
1) 기본 케이스
- 알고리즘은 특성상 반복을 중지할 수 있다.
2) 추가 조건
- 추가 조건과 기본 케이스의 차이를 확인한다.
3) 자신 호출
- 알고리즘이 자신을 호출해야 한다.
예제
1부터 n까지의 합
1 |
|
최대공약수
1 |
|
트리(Tree)
- 루트(Root): 가장 위쪽에 있는 노드, 트리 별 하나만 있다.
- 루트는 부모와 다르다. 부모노드는 자식노드가 1개 이상 있는경우에만 존재할 수 있다.
- 서브트리: 자식노드이면서 부모노드역할을 하는 노드가 있는 트리이다.
- 차수: 노드가 갖고 있는 최대 자식노드 수이다.
- 위의 경우 차수는 2개이다.
- 10의 차수, 8의 차수, 9의 차수, 1의 차수
- 위의 경우 차수는 2개이다.
- 리프(Leaf): 레벨별로 가장 마지막에 있는 노드, 단말노드(terminal node), 외부노드(external node)라고도 한다. 리프는 트리별로 여러 개가 있을 수 있다.
- 레벨: 루트노드에서 얼마나 멀리 떨어져 있는지 각각 나타낸다. 루트노드의 레벨은 0이며, 아래로 내려갈 때마다 1씩 증가한다.
- 높이: 루트에서 가장 멀리 떨어진 리프노드까지의 거리이며, 리프 레벨의 최대값을 높이라고 한다.
- 형제(Sibling) 노드: 부모가 같은 두 개의 노드이다.
이진 트리(Binary Tree)
- 아래와 같이 각 노드별로, 최대 2개의 서브노드를 가질 수 있다.(left, right)
- 여러 트리종류 중 가장 기본이 되면서 많이 활용되는 트리이다.
- 두 가지 조건으로 구성되어 있다.
- 루틴 노드를 중심으로 두 개의 서브트리로 나눠진다.
- 나눠진 두 서브트리도 모두 두 개의 서브트리를 갖는다.
- 서브트리의 노드가 반드시 값을 갖고 있을 필요는 없다.
포화 이진 트리
- 모든 리프노드들이 동일한 레벨을 갖고 있는 경우이다.
완전 이진 트리
- 노드가 위에서 아래로 채워져있다.
- 노드가 왼쪽에서 오른쪽 순서대로 채워져있다.
BST(Binary Search Trees, 이진검색트리)
- 이진검색트리는 노드를 정확하게 정렬해야하는 특정 유형의 이진트리다.
- BST의 목적은 단순 이진트리보다 빠른 노드탐색이다. 때문에 insert node에서 중복을 처리해주는 것이 아닌, 아래 ‘값 크기 조건’에 맞도록 값을 넣어주는 경우가 이진탐색트리가 되는 것이다.
- 만약 아래 값 크기 조건을 지키지 않고 값을 삽입하는 경우 이진트리탐색의 로직이 아닌 단순이진트리의 로직으로 탐색되기 때문에 느린 탐색이 진행된다.
- 값 크기 조건: 오른쪽 서브노드의 값(right child) > 루트 노드의 값 > 왼쪽 서브노드의 값(left child)
- 중복값을 가진 노드가 없어야 한다.
- 왼쪽 서브트리노드들의 값은 루트노드 값보다 작아야한다.
- 오른쪽 서브트리노드들의 값은 루트노드 값보다 커야한다.
- 위에 대한 규칙이 정해진 이유는 왼쪽부터 오른쪽으로 검색을 하는 구조이기 때문이다.
- 왼 -> 오 개념이 적용되는 이유: 트리와 같은 자료구조는 기본이 되는 연결리스트를 참조해서 만들어진 개념이기 때문이다.
- 특징
- 위와 같은 규칙에 따라 구조가 단순하다.
- base node / 검색할 노드 / 자식노드 존재여부에 따라 검색되는 노드의 순서가 달라진다.
- 검색이 일반 이진트리보다 빠르기 때문에 노드를 삽입하기 쉽다.
- 값 크기 조건: 오른쪽 서브노드의 값(right child) > 루트 노드의 값 > 왼쪽 서브노드의 값(left child)
검색 성공 경우
- 위 그림처럼 6(루트)보다 작은 2(왼쪽 자식노드)를 검색한다.
- 다음으로 2를 기준으로 5(오른쪽 자식노드)가 크므로 검색된다.
- 5를 기준으로 4(왼쪽 자식노드)가 작으면서 검색도 완료된다.
검색 실패 경우
- 6(루트)보다 큰 7(오른족 자식노드)을 검색한다.
- 7보다 큰 오른쪽 자식노드는 존재하지 않기 때문에 검색에 실패한다.
파이썬 소스 코드
1 |
|
순회 탐색
1 |
|