추상적으로 필요한 기능을 나열한 일종의 로직
Linked-list : 리스트들을 연결해줌, 참조되는 노드의 위치바꾸기
.
로 지칭=
로 표현Stack : Last in First out, 뒤로가기 버튼, ctrl+z...
append
, pop
으로 stack 구현 가능 Queue : First in First Out, 임일 전달, 푸쉬 알랑 기능, 쇼핑몰에서 주문 처리(선착순), 전화 온 순서대로 업무 처리....
효율성
이 달라짐관리
하는 데 도움singly linked list
: 노드당 다음 노드를 알려주는 링크가 하나 뿐, 한방향으로 밖에 이동을 못함doubly linked list
: 노드당 링크가 2개, 이전 노드를 갈 수 있는 링크를 추가하게 되는 것, 양방향으로 움직일 수 있음Circular(환형) linked list
: 더블일 수도 있고 싱글일 수 있음, 마지막 노드가 첫번째 노드를 가르켜서 계속 회전할 수 있음push
: 스택에 데이터를 추가하는 기능pop
: 스택의 최상위 데이터를 꺼내는 기능top
, rear
front
알고리즘과 방법론에서 자주 언급
재귀 개념은 문재를 해결하는 재호출 로직을 발견해야 함
재귀 호출은 스택의 개념이 적용, 함수의 내부는 스택처럼 관리
재귀로 문제를 해결하는 방법
재귀는 해결을 위한 특정 기능을 재호출한다는 측면
분할정복은 문제를 분할하고 해결하는 구체적인 방법론
→ 분할정복법을 활용하기 위해서는 재귀개념(기능 재호출)이 필요
재귀의 조건
재귀 제한
파이썬에서는 재귀 깊이 1000으로 제한
재귀 함수의 호출이 1000에 도달하면 RecursionError
발생
→ setrecursionlimit()
함수 이용해 재귀 제한 늘릴 수 있음
재귀적인 문제 해결
한 단계 낮은 문제가 해결된다면 그것을 바탕으로 답을 얻을 수 있
재귀함수 작성 시
재귀호출 할 때 인자를 반드시 규모가 줄어들도록 설정
재귀호출 없이 해결할 수 있는 최소문제(base case)설정
트리 용어
루트(root) : 가장 위쪽에 있는 노드, 트리별 하나
서브트리 : 자식 노드이면서 부모노드 역할을 하는 트리
차수 : 노드가 갖고 있는 최대 자식노드 수
리프(leaf) : 레벨별로 가장 마지막에 있는 노드
= 단말 노드(terminal node), 외부노드(external node)
레벨 : 루트노드에서 얼마나 멀리 떨어져 있는 지, 루트노드의 레벨은 0이고 아래로 내려갈 때마다 1씩 증가
높이 : 루트에서 가장 멀리 떨어진 리프노트까지의 거리, 리프 레벨의 최대값
형제(sibling)노드 : 부모가 같은 두 개의 노드
이진트리는 각 노드별로 최대 2개의 서브노드를 가질 수 있음(left, right)
조건
루트 노드를 중심으로 두 개의 서브트리로 나눠짐
나눠진 두 서브트리도 모두 두 개의 서브트리를 가짐
Perfect
Complete
Binary Search Trees(BST, 이진검색(탐색)트리)
자식 노드가 최대 2개까지만 붙는 이진트리의 형태를 띔
노드를 정확하게 정렬하는 특정 유형의 이진 트리
조건
값 크기 조건 : 오른쪽 서브 노드 값 > 루트(부모)노드 값 > 왼쪽 서브 노드 값
→ 왼쪽부터 오른쪽으로 검색을 하는 구조이기 때문
특징
알고리즘이란?
프로그래밍
정렬 : 숫자 두개의 크기를 비교하고 바꿔주는 작업을 반복하여 조건에 맞게 순서를 맞춰주는 작업
선형검색(Linear search)
이진검색(Binary search)
# 처음과 마지막을 정해줘야 함
def binary_search(test_list):
low = 0 # 리스트 첫번째 항목
high = len(test_list) - 1 # 리스트 마지막 항목
Selection sort(선택정렬)
Insertion sort(삽입정렬)
아직 정렬되지 않은 특정 노드와 정렬된 노드들의 값을 비교하며 값이 더 큰 것의 인덱스보다 작은 인덱스에 삽입하며 정렬
소량의 데이터를 정렬하기 위한 효율적인 알고리즘
시간 복잡도 : O(n) - 최상(이미 정렬됨), O(n^2) - 최악(반대로 정렬된 경우)/평균
Bubble sort(버블정렬)
서로 이웃한 두 원소의 크기를 비교한 결과에 따라 교환을 반복하는 알고리즘, 단순 교환 정렬
가장 간단하지만 매우 비효율적
시간 복잡도 : O(n^2)
복잡하거나 큰 문제를 여러 개로 나눠서 푸는 방법
오버헤드
발생, 스택에 다양한 데이터를 보관하고 있어야 하기 때문에 스택 오버플로우
가 발생하거나 과도한 메모리 사용하게 됨
오버헤드
: 어떤 처리를 하기 위해 들어가는 간접적인 처리 시간/메모리 등
스택 오버플로우
: 스택 포인터가 스택의 경계를 넘어설 때 발생, 프로그램이 호출 스택에서 이용 가능한 공간 이상을 사용하려고 시도할 때 스택이오버플로우
된다고 함 → 프로그램 충돌 발생
재귀호출 vs 분할정복
재귀호출 : 같은 함수코드를 재호출하는 것(같은 함수코드 사용)
분할정복 : 비슷한 작업을 재진행하는 것(같은 함수코드는 아닐 수 있음)
비슷한 크기로 문제를 분할하고 해결된 문제를 제외하고 동일한 크기로 문제를 다시 분할 → Divide , Conquer, Merge
분할정복 과정
분할정복의 조건
처음에 전체 탐색을 할 때 좌우로 나눠서 재귀적으로 수행하기 때문에 병합정렬보다 빠름
분할
단계에서 정렬불안정 정렬의 대표적인 경우로 노드값이 중복되는 경우에는 계속해서 교환을 시도
최상인 경우 → O(nlogn)
최악인 경우 → O(n^2)
combine
할 때 정렬