[자료구조] 트리 2 (최대 히프, 이진 탐색 트리)

2023. 5. 19. 23:08·전공/자료구조
728x90
반응형

우선순위 큐

  • 우선순위가 가장 높은(낮은) 원소르 먼저 삭제
  • 임의의 우선순위를 가진 원소 삽입 가능
  • 최대 우선순위 큐
template <class T>
class MaxPQ
{
public:
    virtual ~MaxPQ() {}
    // 가상 소멸자
    virtual bool IsEmpty() const = 0;
    // 우선순위 큐가 공백이면 true를 반환
    virtual const T &Top() const = 0;
    // 최대 원소에 대한 참조를 반환
    virtual void Push(const T &) = 0;
    // 우선순위 큐에 원소를 삽입
    virtual void Pop() = 0;
    // 최대 우선순위를 가진 원소를 삭제
};

 

표현 방법 - 최대 히프

 

최대 히프

  • 최대(최소) 트리: 각 노드의 키 값이 그 자식의 키 값보다 작지(크기) 않은 트리
  • 최대 히프: 최대 트리이면서 완전 이진 트리
  • 최소 히프: 최소 트리이면서 완전 이진 트리

최대 히프
최소 히프

template <typename T>
class MaxHeap : public MaxPQ
{
private:
    T *heap;      // 원소 배열
    int heapSize; // 힙의 원소 개수
    int capacity; // 힙 크기

public:
    MaxHeap(int);
    void Push(const T &);
    void Pop();
    // 그 외 함수들
    //
};

 

최대 히프에서의 삽입

- 새로 삽입되는 원소는 부모 원소와 비교하면서 최대 히프가 되는 것이 확인될 때까지 위로 올라감

template <class T>
void MaxHeap<T>::Push(const T &e)
{ // 최대 힙에 e 삽입
    if (heapSize == capacity)
    { // 크기를 2배로 확장
        ChangeSize1D(heap, capacity, 2 * capacity);
        capacity *= 2;
    }
    int currentNode = ++heapSize;
    while (currentNode != 1 && heap[currentNode / 2] < e)
    {
        heap[currentNode] = heap[currentNode / 2]; // 부모 원소를 아래로 내림
        currentNode /= 2;                          // 부모 원소로 이동
    }
    heap[currentNode] = e;
}

 

시간복잡도 - O(log n)

 

최대 히프에서의 삭제

- 루트에서 삭제

- 마지막 원소를 제거하고 제거된 마지막 원소와 루트의 왼쪽 자식, 오른쪽 자식 중 큰 값과 서로 교환

- 최대 히프가 될 때까지 원소 값을 비교하여 교환

template <class T>
void MaxHeap<T>::Pop()
{
    if (IsEmpty())
        throw "Heap is empty. Cannot delete.";
    heap[1].~T(); // 가장 큰 원소 삭제
	
    // lastE는 힙의 마지막 원소
    T lastE = heap[heapSize--];

    // trickle down
    int currentNode = 1; // 루트 노드에서 작업 시작
    int child = 2;       // currentNode의 자식
    while (child <= heapSize)
    {
        // currentNode 더 큰 자식을 위치
        if (child < heapSize && heap[child] < heap[child + 1])
            child++;

        // currentNode 위치에 lastE가 존재해도 된다면
        if (lastE >= heap[child])
            break; // 작업 종료

        heap[currentNode] = heap[child]; // 자식을 부모의 위치로 이동
        currentNode = child; // 작업 위치 이동
        child *= 2;          // 작업 위치 이동
    }
    heap[currentNode] = lastE;
}

 

시간복잡도 - O(log n)

 

 

이진 탐색 트리

더보기

사전(dictionary)

- pair<키, 원소>의 집합

template <class K, class E>
class Dictionary
{
public:
    virtual bool IsEmpty() const = 0;
    // 공백이면 true 리턴
    
    virtual pair<K, E> *Get(const K &) const = 0;
    // 지시한 키를 가진 쌍에 대한 포인터 반환, 쌍이 없으면 0 반환
    
    virtual void Insert(const pair<K, E> &) = 0;
    // 쌍을 삽입, 키가 중복되면 관련 원소 갱신
    
    virtual void Delete(const K &) = 0;
    // 지시된 키를 가진 쌍 삭제
};

 

 

정의

  • 이진트리로서 공백 가능하고, 만약 공백이 아니라면
    • 모든 원소는 상이한 키를 갖음
    • 왼쪽 서브트리의 키들은 그 루트의 키보다 작음
    • 오른쪽 서브트리의 키들은 그 루트의 키보다 큼
    • 왼쪽과 오른쪽 서브트리도 이원 탐색 트리

 

a) 15의 오른쪽 자식이 15보다 작은 10이다.

 

이진 탐색 트리의 탐색

k = 루트의 키: 성공적 종료

k < 루트의 키: 왼쪽 서브트리 탐색

k > 루트의 키: 오른쪽 서브트리 탐색

template <class K, class E> // Driver
pair<K, E> *BST<K, E>::Get(const K &k)
{   // 키 k를 가진 쌍을 이원 탐색 트리(*this)에서 탐색
    // 쌍을 발견하면 포인터 반환, 아니면 0 반환
    return Get(root, k);
}

template <class K, class E> // Workhorse
pair<K, E> *BST<K, E>::Get(TreeNode<pair<K, E>> *p, const K &k)
{
    if (!p)
        return 0;
    if (k < p->data.first)
        return Get(p->leftChild, k);
    if (k > p->data.first)
        return Get(p->rightChild, k);
    return &p->data; // 데이터의 주소 값 반환
}

template <class K, class E> // 반복문 버전
pair<K, E> *BST<K, E>::Get(const K &k)
{
    TreeNode<pair<K, E>> *currentNode = root;
    while (currentNode)
        if (k < currentNode->data.first)
            currentNode = currentNode->leftChild;
        else if (k > currentNode->data.first)
            currentNode = currentNode->rightChild;
        else
            return &currentNode->data;

    // 매치하는 쌍 없음
    return 0;
}

 

순위에 의한 이진 탐색 트리의 탐색

순위(rank)

- 중위 순서에서의 위치

- leftSize = 왼쪽 서브 트리의 원소 수 + 1

template <class K, class E> // 순위에 의한 탐색
pair<K, ~E> *BST<K, ~E>::RankGet(int r)
{ // r번째 작은 쌍을 탐색
    TreeNode<pair<K, E>> *currentNode = root;
    while (currentNode)
        if (r < currentNode->leftSize)
            currentNode = currentNode->leftChild;
        else if (r > currentNode->leftSize)
        {
            r -= currentNode->leftSize;
            currentNode = currentNode->rightChild;
        }
        else
            return &currentNode->data;
    return 0;
}

 

이진 탐색 트리에서의 삽입

- x의 key값을 가진 노드를 탐색

- 탐색이 성공하면 이 키에 연관된 원소를 변경

- 탐색이 실패하면 탐색이 끝난 지점에 쌍을 삽입

template <class K, class E>
void BST<K, E>::Insert(const pair<K, E> &thePair)
{ // 이진 탐색 트리에 pair 삽입
    // thePair.first를 탐색, pp는 p의 부모
    TreeNode<pair<K, E>> *p = root, *pp = 0;
    while (p)
    {
        pp = p;
        if (thePair.first < p->data.first)
            p = p->leftChild;
        else if (thePair.first > p->data.first)
            p = p->rightChild;
        else // 복제, 연결된 요소 업데이트
        {
            p->data.second = thePair.second;
            return;
        }
    }

    // 노드를 생성
    p = new TreeNode<pair<K, E>>(thePair);
    if (root) // 공백 트리가 아닐 경우
        if (thePair.first < pp->data.first)
            pp->leftChild = p;
        else
            pp->rightChild = p;
    else
        root = p; // 공백 트리라면 생성한 노드를 루트에 위치시킴
}

 

이진 탐색 트리에서의 삭제

리프 원소의 삭제

- 부모의 자식 필드에 0을 삽입, 삭제된 노드 반환

 

하나의 자식을 가진 비리프 노드의 삭제

- 삭제된 노드의 자식을 삭제된 노드의 자리에 위치

 

두개의 자식을 가진 비리프 노드의 삭제

- 왼쪽 서브트리에서 가장 큰 원소나 오른쪽 서브트리에서 가장 작은 원소로 대체

- 대체된 서브트리에서 대체한 원소의 삭제 과정 진행

 

시간복잡도 - O(h)

 

이원 탐색 트리의 원소 수: n

 

최악의 경우

- 이원 탐색 트리의 높이 = n

 

삽입 삭제가 무작위로 이루어질 때

- 트리의 높이 = O(log n)

 

균형 탐색 트리

- 최악의 경우에도 높이가 O(log n)이 되는 트리

- 탐색, 삽입, 삭제의 시간 복잡도: O(h)

 

 

728x90
반응형

'전공 > 자료구조' 카테고리의 다른 글

[자료구조] 그래프 2 (신장 트리, Kruskal, Prim, Sollin 알고리즘, 그래프 최단경로, AOV 네트워크)  (0) 2023.05.30
[자료구조] 그래프 1 (그래프 정의, 그래프 표현, 그래프 탐색)  (0) 2023.05.30
[자료구조] 트리 1 (트리 종류, 이진 트리 순회, 복사, 동일성 검사)  (0) 2023.05.12
[자료구조] 연결 리스트 4 (연결 스택과 큐, 다항식, 이중 연결 리스트)  (0) 2023.05.12
[자료구조] 연결 리스트 3 (원형 리스트, 가용 공간 리스트)  (0) 2023.05.12
'전공/자료구조' 카테고리의 다른 글
  • [자료구조] 그래프 2 (신장 트리, Kruskal, Prim, Sollin 알고리즘, 그래프 최단경로, AOV 네트워크)
  • [자료구조] 그래프 1 (그래프 정의, 그래프 표현, 그래프 탐색)
  • [자료구조] 트리 1 (트리 종류, 이진 트리 순회, 복사, 동일성 검사)
  • [자료구조] 연결 리스트 4 (연결 스택과 큐, 다항식, 이중 연결 리스트)
dev_ares
dev_ares
대학에서 컴퓨터공학을 전공하고 있는 학생입니다.
    반응형
    250x250
  • dev_ares
    노트
    dev_ares
  • 전체
    오늘
    어제
    • 분류 전체보기 (187)
      • IT 트랜드 (2)
      • 백엔드 (18)
        • Java + Spring (8)
        • Kotlin + Spring (5)
        • 백엔드 (5)
      • 프론트엔드 (1)
        • React (1)
      • 대외활동 (17)
        • 42서울 (17)
      • 백준 (6)
        • Java (2)
        • C++ (3)
      • 전공 (121)
        • 객체지향프로그래밍 (17)
        • 자료구조 (23)
        • 리눅스시스템관리 (16)
        • 컴퓨터구조 (25)
        • 네트워크 (25)
        • 데이터베이스 (15)
        • 기타 전공 (0)
      • 프로그래밍 언어 (18)
        • Java (5)
        • Swift (4)
        • C++ (1)
        • Kotlin (8)
      • 기타 (4)
  • 블로그 메뉴

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

  • 공지사항

  • 인기 글

  • 태그

    상속
    컴퓨터 구조 및 설계
    명령어
    티스토리챌린지
    반복자
    42서울
    자료구조
    오블완
    사설 문제
    백준
    메모리 계층 구조
    컴공 포트폴리오
    단일 사이클
    코틀린
    데이터패스
    자바
    C++
    추가 문제
    리눅스
    컴퓨터구조
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
dev_ares
[자료구조] 트리 2 (최대 히프, 이진 탐색 트리)
상단으로

티스토리툴바