[알고리즘] 12 - 힙을 마스터하자

6784 단어 algorithms

1. 힙 소개



  • 정의
  • 힙은 힙 속성(최소 또는 최대 힙)을 충족하는 완전한 이진 트리입니다.
  • 최대 힙: 모든 노드가 자식에 대해 크거나 같은 키(값)를 가집니다.
  • 최소 힙: 모든 노드가 자식에 대해 더 작거나 같은 키(값)를 가집니다.



  • 속성
  • 기본적으로 힙은 배열입니다.
  • 모든 힙의 높이는 log(n)만 됩니다.
  • 왼쪽 자식은 2*i에 있습니다.
  • 오른쪽 자식은 2*i+1에 있습니다.
  • 부모는 i/2에 있습니다.


  • 2. 삽입(최대 힙)


  • 1) 배열의 끝에 요소를 삽입합니다.
  • 2) 그런 다음 부모가 요소보다 크거나 같을 때까지 요소를 부모와 바꿉니다.

  • void Insert(int arr[], int i){
      while(i > 0 && arr[i/2] < arr[i]){
    
        // Swapping parent and current  
        swap(arr[i/2], arr[i]);
    
        // Move on to the next element
        i = i/2;
      }
    }
    


    3. 삭제(최대 힙)


  • 힙에서 삭제는 루트 노드를 삭제하는 것을 의미합니다.
  • 1) 지정된 인덱스가 있는 요소를 힙의 마지막 요소와 바꿉니다.
  • 2) 현재 마지막 요소를 삭제합니다.
  • 3) 교체된 요소의 하위를 비교합니다. 더 큰 자식으로 요소를 교체합니다(자식 중 하나가 요소보다 크거나 같은 경우에만).
  • 4) 두 자식이 요소보다 작은 위치를 찾을 때까지 이 과정을 반복합니다.

  • void deleteRoot(int arr[], int& n)
    {
        // Get the last element
        int lastElement = arr[n - 1];
    
        // Replace root with last element
        arr[0] = lastElement;
    
        // Decrease size of heap by 1 (element deleted)
        n = n - 1;
    
        // Start from the bottom
        int i = n;
    
        // Construct the heap again after the deletion
        while(true){
    
          // After we proceed the root node, break out of the loop.
          if(i < 0)break;
    
          // Compare two children and swap
          if(i*2 <= n && arr[i] < arr[i*2]){
            swap(arr[i], arr[i*2]);
          } else if(arr[i] < arr[i*2+1]){
            swap(arr[i], arr[i*2+1]);
          }
    
          i--;
       }
    }
    


    4. 힙 정렬


  • 삭제 속성 중 하나를 사용합니다.
  • 힙에서 요소를 삭제할 때마다 배열 끝에 빈 공간이 추가로 생깁니다.
  • 또한 힙 중에서 최대 요소를 얻습니다.
  • 따라서 삭제된 요소를 배열 끝에 계속 삽입하면 결국 배열이 정렬됩니다.

  • 5. 히피파이


  • Heapify를 사용하면 O(N) 시간 복잡도 내에서 힙을 만들 수 있습니다. 삽입 방법을 사용하면 O(N*log(N))가 걸립니다.

  • Heapify는 밑바닥부터 시작합니다. 노드의 모든 자식을 반복적으로 비교하고 루트 노드에 도달할 때까지 부모와 교체합니다.
  • 최대 힙 예: swap(arr[i], max(arr[2*i], arr[2*i+1]))
  • 최소 힙 예: swap(arr[i], min(arr[2*i], arr[2*i+1]))


  • 6. C++에서 힙을 사용하는 방법


  • priority_queue<T>는 C++에서 최대 힙으로 사용할 수 있습니다. 최대 힙은 라이브러리의 기본 동작입니다.
  • 예) priority_queue<T> pq;


  • priority_queue<T>는 C++에서 최소 힙으로 사용할 수 있습니다. 몇 가지 추가 인수를 생성자에 전달하기만 하면 됩니다.
  • 예) priority_queue <T, vector<T>, greater<T> > pq;

  • 좋은 웹페이지 즐겨찾기