3. 이진 탐색 트리

2023. 4. 27. 13:18·다양한 글들/자료구조와 알고리즘

이진 탐색 트리

이진 탐색 트리(binary search tree)

: 이진 트리 기반의 탐색을 위한 자료 구조

 

탐색(search)

: 레코드(record)의 집합에서 특정한 레코드를 찾아내는 작업을 의미


레코드(record)

: 하나 이상의 필드(field)로 구성


테이블(table)

: 레코드(record)들의 집합


주요 키(primary key)

: 각각의 레코드를 구별할 수 있는 키

 

  • 탐색 작업을 할 때 주요 키가 입력이 되어 특정한 키를 가진 레코드를 찾게 됨
  • 이진 탐색 트리는 이러한 탐색 작업을 효율적으로 하기 위한 자료구조

- 이진 탐색 트리의 정의

이진 탐색 트리: 이진 탐색 트리의 성질을 만족하는 이진 트리

 

<정의 7.7.1> 이진 탐색 트리

- 모든 노드 키는 유일함
- 왼쪽 서브 트리의 키들은 루트의 키보다 작음
- 오른쪽 서브 트리의 키들은 루트의 키보다 큼
- 왼쪽과 오른쪽 서브 트리도 이진 탐색 트리임
  • 찾고자 하는 키 값 < 루트 노드의 키 값: 왼쪽 서브 트리에 존재 / 찾고자 하는 키 값 > 루트 노드의 키 값: 오른쪽 서브 트리에 존재
  • 이진 탐색 트리를 중위 순회 방법으로 순회하면 숫자들이 크기 순이 됨

- 탐색 연산

탐색 연산

: 이진 탐색 트리에서 특정 키 값을 가진 노드를 찾는 것

 

주어진 탐색 키 값과 현재 루트 노드의 키 값 비교
- 비교한 결과가 같으면 탐색이 성공적으로 끝남

 

주어진 키 값이 루트 노드의 키 값보다 작으면 탐색은 이 루트 노드의 왼쪽 자식을 기준으로 다시 시작

주어진 키 값이 루트 노드의 키 값보다 크면 탐색은 이 루트 노드의 오른쪽 자식을 기준으로 다시 시작

<알고리즘 7.7.1> 이진 탐색 트리 탐색 알고리즘(순환적)

search(x,k)

if x = NULL
	then return NULL;
if k = x->key
	then return x;
else if k < x->key
		then return search(x->left,k);
        else return search(x->right,k);
        
        
이진 탐색 트리가 공백 상태이면
그냥 복귀
탐색 키가 현재 트리의 루트 키 값과 같으면
루트를 반환
탐색 키가 루트 키 값보다 작으면
왼쪽 서브 트리를 순환 호출을 이용하여 계속 탐색
그렇지 않으면 오른쪽 서브 트리를 순환 호출을 이용하여 계속 탐색
typedef struct TreeNode{
	int key;
    struct TreeNode *left, *right;
} TreeNode;

 

<프로그램 7.7.1> 순환적인 탐색 함수

// 순환적인 탐색 함수
TreeNode *search(TreeNode *node, int key){
	if(node == NULL) return NULL;
    if(key == node->key) return node;
    else if(key < node->key){
    	return search(node->left, key); // 왼쪽 자식 노드를 매개변수로 넣어 함수 순환 호출
    }else{
    	return search(node->right, key); // 오른쪽 자식 노드를 매개변수로 넣어 함수 순환 호출
    }
}

 

<프로그램 7.7.2> 반복적인 탐색 함수

// 반복적인 탐색 함수
TreeNode *search(TreeNode *node, int key){
	while(node != NULL){
    	if(key == node->data) return node;
        else if(key < node->data){
        	node = node->left;
        }else{
        	node = node->right;
        }
    }
    return NULL; // 탐색에 실패했을 경우 NULL 반환
}

==> 반복적인 방법이 더 효울적임


- 이진 탐색 트리에서 삽입 연산

탐색 먼저 수행 -> 이진 탐색 트리에서 같은 키 값을 가진 노드가 없어야 하기 때문 + 탐색에 실패한 위치가 바로 새로운 노드를 삽입하는 위치가 됨

  • 탐색이 성공하면 탐색 키가 중복되는 것이므로 삽입이 불가능
  • 탐색이 실패하면 실패로 끝난 위치에 새로운 키 삽입

 

<알고리즘 7.7.2> 이진 탐색 트리 삽입 알고리즘(자연어 버전)

insert_node(T, z)

1. 트리 T에서 z에 대한 탐색을 먼저 수행
2. 탐색이 실패하면 탐색이 띁난 지점에 노드 z를 삽입

 

<알고리즘 7.7.3> 이진 탐색 트리 삽입 알고리즘(유사 코드)

insert_node(T, key)

p <- NULL;
t <- T;

while t != NULL do // 탐색을 수행
	p <- t;
    if key < p->key
    	then t <- p->left
        else t <- p->right
        
z <- make_node(key);
    
if p = NULL
	then T <- z; // 트리가 비어 있음
else if key < p->key
	then p->left <- z
    else p->right <- z
        
 p는 부모 노드 포인터
 t는 탐색을 위한 포인터
 
 t가 NULL이 될 때까지 탐색을 수행함
 현재 탐색 포인터의 값을 부모 노드 포인터에 복사
 삽입할 키 값이 t의 키 값보다 작으면 왼쪽 자식 노드로 탐색 진행
 삽입할 키 값이 t의 키 값보다 크면 오른쪽 자식 노드로 탐색 진행
 key를 포함하는 트리 노드 생성
 
 반복이 끝났고, 만약 부모 노드가 NULL이면 현재 트리가 공백 상태. 따라서, 새로운 노드를 루트로 설정
 부모 노드의 키 값과 비교하여 작으면 왼쪽 자식으로 연결함. 그렇지 않으면 오른쪽 자식으로 연결

 

<프로그램 7.7.3> 이진 트리 삽입 프로그램

// key를 이진 탐색 트리 root에 삽입
// key가 이미 root 안에 있으면 삽입되지 않음

void insert_node(TreeNode **root,int key){
	TreeNode *p, *t; // p는 부모 노드, t는 현재 노드
    TreeNode *n; // n은 새로운 노드
    
    t = *root;
    p = NULL;
    
    // 탐색을 먼저 수행
    while(t != NULL){
    	if(key == t->data){
        	return; // 이미 존재
        }
        p = t;
        if(key < p->key) t = p->left;
        else t = p->right;
    }
    
    // key가 트리 안에 없으므로 삽입 가능
    // 트리 노드 구성
    n = (TreeNode *)malloc(sizeof(TreeNode));
    if(n == NULL) error("memory allocate error");
    
    // 데이터 복사
    n->key= key;
    n->left = n->right = NULL;
    
    // 부모 노드와 연결
    if( p!= NULL){
    	if(key < p->key){
        	p->left = n;
        }else{
        	p->right = n;
        }
    }else{
    	*root = n;
    }
}

- 이진 탐색 트리에서 삭제 연산

탐색 먼저 수행 -> 삭제하려는 키 값이 트리 안에 어디 있는지를 알아야 삭제할 수 있음

  1. 삭제하려는 노드가 단말 노드일 경우
  2. 삭제하려는 노드가 하나의 왼쪽이나 오른쪽 서브 트리 중 하나만 가지고 있는 경우
  3. 삭제하려는 노드가 두 개의 서브 트리 모두 가지고 있는 경우

 

첫 번째 경우: 삭제하려는 노드가 단말 노드일 경우

  • 단말 노드의 부모 노드를 찾아서 부모 노드 안의 해당 링크 필드를 NULL로 만들어 연결을 끊으면 됨
  • 다음으로 만약 노드를 동적을 생성했다면 동적 메모리 해제시키면 됨

 

두 번쨰 경우: 삭제하려는 노드가 하나의 서브 트리만 가지고 있는 경우

  • 자기 노드는 삭제
  • 그 서브 트리를 자기 노드의 부모 노드가 가리키게하면 됨

 

세 번째 경우: 삭제하려는 노드가 두 개의 서브 트리를 가지고 있는 경우

  • 왼쪽 자식과 오른쪽 자식 중 어떤 노드를 삭제 노드 위치로 가져와야 하는지 생각해야 함 -> 삭제되는 노드와 값이 가장 비슷한 노드를 선택해야 함
  • 왼쪽 서브 트리에서 가장 큰 값(왼쪽 서브 트리의 가장 오른쪽)이나 오른쪽 서브 트리에서 가장 작은 값(오른쪽 서브 트리의 가장 왼쪽)이 삭제되는 노드와 가장 가깝기 때문에 후계자 대상 노드가 됨
  • 후계장 대상 노즈 중에서는 어느 노드를 선택해도 상관 없음

 

<프로그램 7.7.4> 이진 탐색 트리에서의 삭제 함수

// 삭제 함수

// 루트 노드 포인터의 포인터로 전달한 이유는 루트 노드가 삭제되거나 변경될 수 있기 때문
void delete_node(TreeNode **root, int key){
	TreeNode *p, *t, *succ, *succ_p; // 부모 노드, 현재 노드, 후계자 노드, 후계자 노드의 부모
    TreeNode *child;
    
    // key를 갖는 노드 t를 탐색, p는 t의 부모
    p = NULL;
    t = *root;
    // key를 갖는 노드 t를 탐색
    while(t!=NULL && t->key != key){
        p = t;
        t = (key < p->key) ? p->left : p->right;
    }
    
    // 탐색이 종료된 시점에 t가 NULL이면 해당 key가 이진 트이 안에 없는 것을 의미
    if(t == NULL){
    	printf("key is not in the tree\n");
    	return;
    }
    
    // 첫 번째 경우: 단말 노드의 경우
    if((t->left == NULL) && (t->right == NULL)){
    	if(p!=NULL){
        	// 부모 노드의 자식 필드를 NULL로 만듦
            if(p->left == t){
            	p->left = NULL;
            }else{
            	p->right = NULL;
            }
        }else{ // 만약 부모 노드가 NULL이면 삭제되는 노드가 루트
        	*root = NULL;
        }
    }
    
    // 두 번째 경우: 하나의 자식만 가진 경우
    else if((t->left == NULL) || (t->right == NULL)){
    	child = (t->left != NULL) ? t->left : t->right;
        if(p!=NULL){
        	// 부모와 자식을 연결
        	if(p->left == t){
            	p->left = child;
            }else{
            	p->right = child;
            }
        }else{ // 부모 노드가 NULL이면 삭제되는 노드가 루트
        	*root = child;
        }
    }
    // 세 번째 경우: 두 개의 자식을 가지는 경우
    else{
    	// 오른쪽 서브 트리에서 후계자를 찾음
        succ_p = t;
        succ = t->right;
        // 후계자를 찾아서 계속 왼쪽으로 이동
        while(succ->left != NULL){
        	succ_p = succ;
            succ = succ->left
        }
        
        // 후속자의 부모와 자식은 연결
        if(succ_p->left == succ){
        	succ_p->left = succ->right;
        }else{
        	succ_p->right = succ->right;
        }
        // 후속자가 가진 키 값을 현재 노드에 복사
        t->key = succ->key;
        // 원래의 후속자 삭제
        t = succ;
    }
    free(t);
}

- 이진 탐색 트리의 분석

  • 이진 탐색 트리에서의 탐색, 삽입, 삭제 연산의 시간 복잡도는 트리의 높이를 h라고 했을 때 O(h)가 됨 -> 노드가 n개일 때 평균적인 시간 복잡도는 O(logn)
  • 이진 탐색 트리에서 한쪽으로 치우치는 경사 이진 트리일 경우에는 O(n)의 시간 복잡도를 가짐(== 선형 탐색)
  • 따라서 이 경우 선형 탐색에 비해 전혀 시간적 이득이 없으므로, 최악의 경우를 방지하기 위해서 트리의 높이를 ⌈logn⌉으로 한정시키는 균령 기법이 필요(트리를 균형 있게 만드는 기법으로 AVL 트리를 비롯한 여러 기법들이 개발됨)

이진 탐색 트리의 응용: 영어 사전

  • 영어 단어와 그 의미가 저장된 구조체 필요
// 데이터 타입
typedef struct{
	char word[MAX_WORD_SIZE]; // 키 필드
    char meaning[MAX_MEANING_SIZE];
} element;

// 노드의 구조
typedef struct TreeNode{
	element item;
    struct TreeNode *left, *right;
}TreeNode;
  • 두 개의 element를 항목 순서를 비교하는 compare 함수가 필요함
  • compare(e1,e2) 함수는 e1과 e2를 알파벳 순서로 비교하여 e1이 e2보다 작으면 -1, 같으면 0, 크면 1을 반환시킴
// 만약 e1 < e2 -> -1 반환
// 만약 e1 = e2 -> 0 반환
// 만약 e1 > e2 -> 1 반환
int compare(element e1, element e2){
	return strcmp(e1.word, e2.word);
}

<프로그램 7.8.1> 이진 탐색 트리를 이용한 영어 사전 프로그램

// 이진 탐색 트리를 사용한 영어 사전
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>

#define MAX_WORD_SIZE 100
#define MAX_MEANING_SIZE 200

// 데이터 형식
typedef struct{
    char word[MAX_WORD_SIZE]; // 키 필드
    char meaning[MAX_MEANING_SIZE];
} element;

// 노드의 구조
typedef struct TreeNode{
    element key;
    struct TreeNode *left, *right;
} TreeNode;

// 만약 e1 < e2 -> -1 반환
// 만약 e1 = e2 -> 0 반환
// 만약 e1 > e2 -> 1 반환
int compare(element e1, element e2){
    return strcmp(e1.word, e2.word);
}

// 이진 탐색 트리 출력 함수
void display(TreeNode *p){
    if(p!=NULL){
        printf("(");
        display(p->left);
        printf("%s", p->key.word);
        display(p->right);
        printf(")");
    }
}

// 이진 탐색 트리 함수
TreeNode *search(TreeNode *root, element key){
    TreeNode* p = root;
    while(p!=NULL){
        switch (compare(key, p->key))
        {
        case -1:
            p = p->left;
            break;
        case 0:
            return p;
        case 1:
            p = p->right;
            break;
        }
    }
    return p; // 탐색에 실패했을 경우 NULL 반환
}

// key를 이진 탐색 트리 root에 삽입함
// key가 이미 root안에 있는 경우 삽입되지 않음
void insert_node(TreeNode **root, element key){
    TreeNode* p, *t; // p는 부모 노드, t는 자식 노드

    p = NULL;
    t = *root;
    // 탐색을 먼저 수행
    while(t!=NULL){
        p = t;
        if(compare(key, t->key) == 0 )
            return; // 이미 존재
        else if(compare(key,t->key) < 0)
            t = t->left;
        else
            t = t->right;
    }

    // item이 트리 앖에 없으므로 삽입 가능
    TreeNode* n = (TreeNode*)malloc(sizeof(TreeNode)); // n은 새로운 노드
    if(n == NULL){
        return;
    }
    // 데이터 복사
    n->key = key;
    n->left = n->right = NULL;
    // 부모 노드와 링크 연결
    if(p != NULL){
        if(compare(key,p->key) <0){
            p->left = n;
        }else{
            p->right = n;
        }
    }else{
        *root = n;
    }
}

void delete_node(TreeNode **root, element key){
    TreeNode *p, *t;

    p = NULL;
    t = *root;
    while(t != NULL){
        p = t;
        t = (compare(key, t->key) < 0) ? t->left : t->right;
    }

    // 탐색 트리에 없는 키
    if(t == NULL){
        printf("key is not in the tree\n");
        return;
    }

    // 단말 노드인 경우
    if((t->left == NULL) && (t->right == NULL)){
        if(p!=NULL){
            if(p->left == t){
                p->left = NULL;
            }else{
                p->right = NULL;
            }
        }else{ // 부모 노드가 없으면 루트
            *root = NULL;
        }
    }
    // 하나의 자식만 있는 경우
    else if ((t->left == NULL) || (t->right == NULL)) {
        TreeNode* child = (t->left != NULL) ? t->left : t->right;
        if(p!=NULL){
            if (p->left == t) { // 부모와 자식 노드를 연결
                p->left = child;
            } else {
                p->right = child;
            }
        }else{
            *root = child;
        }
    }
    // 두 개의 자식을 가지는 경우
    else {
        // 오른쪽 서브 트리의 후속자를 찾음
        TreeNode *succ, *succ_p;
        succ_p = t;
        succ = t->right;
        // 후속자를 찾아서 계속 왼쪽으로 이동
        while (t->left != NULL) {
            succ_p = succ;
            succ = succ->left;
        }
        // 후속자의 부모와 자식을 연결
        if(succ_p->left == succ){
            succ_p->left = succ->right;
        }else{
            succ_p->right = succ->right;
        }
        // 후속자를 현재 노드로 이동
        t->key = succ->key;
        t = succ;
    }
    free(t);
}

void help(){
    printf("*****************\n");
    printf("i: input\n");
    printf("d: delete\n");
    printf("s: search\n");
    printf("p: print\n");
    printf("q: quit\n");
    printf("*****************\n");
}

// 이진 탐색 트리를 사용하는 영어 사전 프로그램
int main(){
    char command;
    element e;
    TreeNode* root = NULL;
    TreeNode* tmp;

    do{
        help();
        command = getchar();
        fflush(stdin);
        switch (command)
        {
        case 'i':
            printf("Word: ");
            gets(e.word);
            printf("Meaning: ");
            gets(e.meaning);
            insert_node(&root, e);
            break;
        case 'd':
            printf("Word: ");
            gets(e.word);
            delete_node(&root, e);
            break;
        case 's':
            printf("Word: ");
            gets(e.word);
            tmp = search(root, e);
            if( tmp != NULL){
                printf("Meaning: %s\n", e.meaning);
            }
            break;
        case 'p':
            display(root);
            printf("\n");
            break;
        }
    } while (command != 'q');
}

저작자표시

'다양한 글들 > 자료구조와 알고리즘' 카테고리의 다른 글

우선순위 큐  (0) 2023.05.14
2. 균형 이진 탐색 트리  (0) 2023.05.11
8. 연결 리스트로 구현한 큐  (0) 2023.04.20
7. 연결 리스트로 구현한 스택  (0) 2023.04.20
5. 덱의 응용 : 미로 탐색 프로그램 ft. C++  (0) 2023.04.18
'다양한 글들/자료구조와 알고리즘' 카테고리의 다른 글
  • 우선순위 큐
  • 2. 균형 이진 탐색 트리
  • 8. 연결 리스트로 구현한 큐
  • 7. 연결 리스트로 구현한 스택
smile blog
smile blog
건국대 첨단바이오공학부 & 컴퓨터공학부 BT & IT 기술로 희망을 꿈 꿉니당
  • smile blog
    스마일 블로그
    smile blog
  • 전체
    오늘
    어제
    • 분류 전체보기 (816) N
      • 일상 생각들 (2)
      • 학과에 대해 (4)
        • 첨단바이오공학부 (4)
        • 컴퓨터공학부 (0)
      • -------- 프로젝트 -------- (0)
      • [DS] 토이 프로젝트 (1)
      • [Web, Game, XR] 토이 프로젝트 (11)
      • 경진대회 (1)
      • -------- 진로 -------- (0)
      • 생물정보학자 (18)
        • 데이터 과학이란? (0)
        • 되는 방법 (8)
        • 책 추천 (2)
        • 인강 (1)
        • 대학 (2)
        • 회사 (1)
        • 학원 (2)
        • 학회 (2)
      • 디지털 헬스케어 (72)
        • 방법 (8)
        • 생각들 (10)
        • 공부법 (4)
        • 책 추천 (2)
        • 학원 (2)
        • 참고 (2)
        • 대학 (3)
        • 회사 (3)
        • 인강 (2)
        • 게임 엔진들 (1)
        • 게임 프로그래머 개론 (2)
        • 게임 프로그래머 취업 전략 가이드 (7)
        • 취업 서류 (1)
        • 애정하는 게임들 (4)
        • XR 테크니컬 아티스트 (9)
        • 영화, 애니메이션 테크니컬 디렉터 (12)
      • -------- 기초 학문 -------- (0)
      • 생명과학 이야기 (2)
        • 대학 강의 (2)
      • 화학 이야기 (0)
      • 컴퓨터과학 이야기 (0)
      • 통계학 이야기 (0)
      • 수학 이야기 (1)
        • 공학 수학 (1)
      • 영어 이야기 (1)
      • 심리학 이야기 (7)
        • 현대인과 정신건강 (7)
      • -------- 컴퓨터 언어 -------- (0)
      • Python (3)
        • 나도코딩의 파이썬 입문 (1)
        • 파이썬 관련 정보 (1)
      • SQL (0)
      • C 언어 (32)
        • 혼자 공부하는 C언어 요약 (1)
        • [책 정리] 혼자 공부하는 C언어 (31)
      • C++ (33)
        • 명품 C++ 프로그래밍 요약 (1)
        • [책 정리] 명품 C++ 프로그래밍 (27)
        • C++ STL (0)
        • 뇌를 자극하는 C++ STL (5)
      • -------- 생명과학 -------- (0)
      • 생화학 (5)
        • 대학 강의 (5)
      • 분자세포생물학 (3)
        • 대학 강의 (3)
      • 유전자치료공학 (2)
        • 대학 강의 (2)
      • 생명정보학 (5)
        • 대학 강의 (5)
      • 약리학 (2)
        • 대학 강의 (2)
      • -------- 컴퓨터과학 -------- (0)
      • 자료구조와 알고리즘 (8)
        • 자료구조와 알고리즘의 정의 (3)
        • [책 정리] C언어로 쉽게 풀어쓴 자료구조 요약 (1)
        • [인강] 자료구조와 알고리즘 (2)
        • 코딩 테스트 대비하기! (1)
      • 컴퓨터 회로 (0)
      • 컴퓨터 구조 (43)
        • 컴퓨터 구조와 운영체제 요약 (1)
        • ---------------------------------------- (0)
        • [전공 책 정리] 컴퓨터 구조 및 설계 (1)
        • Ch1. 컴퓨터 추상화 및 관련 기술 (8)
        • Ch2. 명령어 : 컴퓨터 언어 (11)
        • Ch3. 컴퓨터 연산 (8)
        • Ch4. 프로세서 (11)
        • Ch5. 메모리 계층구조 (3)
        • Ch6. 병렬 프로세서 : 클라이언트에서 클라우드까지 (0)
      • 시스템 프로그래밍 (15)
        • [책 정리] 시스템 프로그래밍 유닉스 & 리눅스 (0)
        • [인강] 리눅스 시스템 프로그래밍 (2)
        • 리눅스에서 코딩이란? (8)
        • 대학교 강의 정리 (5)
      • 운영체제 (0)
      • 컴퓨터 네트워크 (37)
        • 모두의 네트워크 요약 (1)
        • [책 정리] 모두의 네트워크 (10)
        • ---------------------------------------- (0)
        • [전공 책 정리] 컴퓨터 네트워킹 하향식 접근 8판 (1)
        • Ch1. 컴퓨터 네트워크와 인터넷 (7)
        • Ch2. 애플리케이션 계층 (7)
        • Ch3. 트랜스포트 계층 (8)
        • Ch4. 네트워크 계층 : 데이터 평면 (3)
        • Ch5. 네트워크 계층 : 제어 평면 (0)
        • Ch6. 링크 계층과 근거리 네트워크 (0)
        • Ch7. 무선 및 이동 네트워크 (0)
        • Ch8. 컴퓨터 네트워크 보안 (0)
      • 데이터베이스 (1)
      • -------- 데이터과학 -------- (0)
      • 데이터 사이언스 (8)
        • 인강 (8)
      • 데이터 분석 (2)
        • 인강 (2)
      • 머신러닝 (2)
        • 대학 수업 (2)
      • 인공지능 (11)
        • 대학교 강의 정리 (10)
        • 인공지능 관련 정보 (1)
      • -------- +a -------- (0)
      • Visual Studio Community (7)
        • 설치법 (1)
        • 단축키 (1)
        • 오류 (5)
      • Visual Studio Code (0)
      • 노션 (1)
      • 깃허브 (7)
        • 깃허브 사용법 (5)
        • 유니티, 언리얼 & 깃허브 (1)
        • 깃허브 주의사항 (1)
      • 챗GPT 활용법 (0)
      • 기타 feat. 프로그래밍 (7)
        • 프로그래머로 살아남기 (5)
        • 코딩 vs 프로그래밍 (1)
        • 애플 비전 프로 (1)
      • 메타버스 (5)
      • -------- 예술 -------- (0)
      • 음악 (1)
      • 미술 (0)
      • -------- XR -------- (0)
      • 유니티 이야기 (23)
        • 레트로의 유니티 게임 프로그래밍 에센스 요약 (4)
        • 유니티 관련 정보 (1)
        • 유니티 디버깅 (13)
        • 유니티 인강 (3)
        • 대학교 게임 프로그래밍 강의 (2)
      • 언리얼 이야기 (0)
        • 인생 언리얼 교과서 요약 (0)
      • 컴퓨터 그래픽스 (6)
        • OpenGL (6)
      • 가상현실 & 증강현실 (4)
        • 유니티 vr (4)
      • HCI 와 UI UX (7)
        • [책 정리] HCI 개론 (6)
      • -------- Design -------- (0)
      • 캐릭터 (1)
        • 모델링 (0)
        • 리깅 (1)
      • 포토샵 (3)
      • 3ds Max (7)
      • Maya (9)
        • 블로그 (1)
        • 인강 (6)
        • 대학교 (2)
      • Blender (14)
        • 책 (1)
        • 인강 (7)
        • 기타 (3)
        • 대학교 (3)
      • 아트 작업물들 (2)
      • 에셋 사이트 (1)
      • -------- 건강관리 -------- (0)
      • 건강관리 ft. 정현 (12)
        • 목 디스크 (2)
        • 눈 관리 (2)
        • 일상생활 습관 (6)
        • 일상생활 꿀팁 (2)
        • 사무직 꿀팁 (0)
      • 헬스의 정석 ft. 정현 (28)
        • 헬스와 건강 (8)
        • 헬스 구체화 정보 (6)
        • 헬스 유튜버 (1)
        • 헬스 서적 (1)
        • 도전 바디프로필! (11)
        • 헬스장 패션 (1)
      • -------- etc -------- (0)
      • 진로 관련 잡다한 글들 (34)
        • 진도율 (9)
        • 진로 관련 글들 (15)
        • 학교 강의 관련 글들 (10)
      • 인생 꿀 Tip (23)
        • 컴퓨터 초기 설정 (9)
        • 원격 데스크톱 (1)
        • 노트북 발열 (1)
        • 전자기기 (2)
        • 중고기기 팔기 (1)
        • 아이패드 필기 어플 (1)
        • 에어팟 (1)
        • 커피 (1)
        • 맥북 (1)
        • lg 그램 (1)
        • 검색엔진에서 내 티스토리 검색 (1)
        • hELLO 다크 모드 없애기 (1)
        • 인터넷 연결 문제 (1)
        • 키보드 문제 해결 (1)
      • 유튜브 (3)
      • 청춘 그리고 추억 (1)
      • 인생 계획표 (2)
        • 2024년 2학기 (1)
        • 2024년 여름방학 (0)
        • 2024년 1학기 (0)
        • 2023년 겨울방학 (1)
      • 다양한 글들 (98)
        • C++ STL (6)
        • Win32 API (24)
        • PushPush 게임 (13)
        • 컴퓨터구조 (1)
        • 자료구조와 알고리즘 (50)
        • 게임의 정의 (3)
        • 영상 회사 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

    • Dream
    • 코딩을 시작한 이유
    • 나를 소개합니다!
    • 블로그 공부법
    • IT & 가치 있는 일들
  • 인기 글

  • 태그

    unity
    코드잇
    함수
    배열
    생물정보학
    유니티
    인공지능
    연산자
    C++
    블렌더
    C언어
    리눅스 터미널
    의생명공학
    첨단바이오공학부
    컴퓨터 네트워크
    알고리즘
    포인터
    심리학
    의생명공학과
    스택
    자료구조
    AI
    명령어
    건국대
    데이터과학
    리눅스
    C++ STL
    데이터사이언스
    컴퓨터구조
    생명공학
  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.3
smile blog
3. 이진 탐색 트리
상단으로

티스토리툴바