2009-06-03 6 views
35

누군가가 make_heap과 같은 STL 힙 함수의 요점을 알려주시겠습니까? 왜 아무도 그걸 사용하지 않았을까요? 실용적인 사용이 있습니까?make_heap의 요점은 무엇입니까?

+5

make_heap 함수없이 힙 정렬을 확인하고 싶습니다 : P – workmad3

답변

17

을 유지하는 데 사용됩니다, 잘, 당신은 make_heap 사용할 수 있습니다

내부적으로 힙이 나무있는 곳입니다 각 노드는 자체 값보다 큰 값 에 연결되지 않습니다. 힙에서 항상 최고 값 인 * 제 와, make_heap하여 나무보다는 의 요소가 시퀀스에서 절대 위치로 결정되는 메모리 소모 링크들에 의해 결정되는 의 특정 위치를 생성 힙.

힙, 및 push_heap pop_heap 힙의 특성을 보존 추가 또는 기능을 사용하여 로그 시간에서의 요소를 제거 할 수 . 상기 이외에

+1

'make_heap'가 빠른 검색을 지원할 때'make_heap'을 적용하면'vector' 구조가 변경됩니까? 벡터 정렬과 다른 점은 무엇입니까? –

+0

예 mozart에 회신 해주십시오. –

+0

힙 (heap)은 위에 설명 된 범위를 충족시킬 수있는 요소의 순차적 순열에 지나지 않습니다. 즉, make_heap은 벡터에서 데이터를 스크램블하는 것뿐입니다. 요소를 정렬하는 것도 옵션 일 수 있지만 삽입 및 삭제에는 로그 시간 대신 선형 * 시간이 필요합니다 (추가 할 때 새 요소에 공간을 만들어야하고 예를 들어 선형 시간이 필요합니다). – akappa

4

에서, STL의 정렬 알고리즘은 퀵 힙 정렬과의 혼합물 인 introsort이다 (이는 전자가 저조한 경우 힙 정렬하는 퀵에서 장애). make_heap은 introsort에 필요한 heapsort를 실행하는 데 필요한 힙 구조를 만듭니다.

40

귀하의 직접적인 질문은 알고리즘 및 데이터 구조의 수업에서 잘 대답 할 것입니다. 힙은 컴퓨터 과학 알고리즘의 모든 곳에서 사용됩니다. 아래 링크 된 make_heap 함수를 인용하면 "힙은 각 노드가 자신의 값보다 크지 않은 값에 연결되는 트리입니다." 힙에 대한 많은 응용 프로그램이 있지만 가장 자주 사용하는 응용 프로그램은 N 값의 정렬 된 목록을 효율적으로 추적하려는 경우 검색 문제입니다.

내가 처음 STL 힙 기능을 만났을 때 나는 당신과 비슷한 혼란을 겪었습니다. 내 질문은 조금 다르다. "STD :: vector와 같은 클래스의 데이터 구조에서 STL 힙이 왜없는가?"

std::heap<int> my_heap; 
my_heap.heap_insert(7); 
my_heap.heap_insert(3); 

STL과 힙 기능 뒤에 아이디어는하지만 그들은 당신이 표준 : : 벡터를 포함하여 여러 가지 기본 STL 컨테이너에서 힙 데이터 구조를 만들 수 있다는 것입니다 : 나는이 같은 일을해야한다고 생각했다. 이 기능은 프로그램의 다른 곳에서 사용하기 위해 컨테이너를 전달하려는 경우에 매우 유용 할 수 있습니다. std :: vector 이외의 다른 것을 사용하도록 선택한 경우 힙의 기본 컨테이너를 선택할 수 있기 때문에 약간의 장점도 있습니다.

template <class RandomAccessIterator> 
    void make_heap (RandomAccessIterator first, RandomAccessIterator last); 

이것은 당신이 힙 비교기에 다른 컨테이너를 많이 만들 수 있다는 것을 의미 당신이 시도 할 수있는 다른 것들에 대해 더 읽을 수 있습니다, 또한 메소드 서명에서 선택 사항입니다 : 당신이 정말로 필요로하는 것은 다음과 같다 make_heap 함수에 대한 STL 페이지에서.

링크는 :

+7

실제로 힙 템플릿 클래스'std :: priority_queue'가 있으므로 힙을 빌드하기 위해'std :: make_heap'을 사용할 필요가 없습니다. –

5

당신은 벡터 나 배열의 상단에 바이너리 힙을 유지하기 위해 std::push_heap()std::pop_heap()과 함께 std::make_heap()를 사용하기로되어있다; 후자의 두 함수는 힙 불변성을 유지합니다. std::heap_sort()을 사용하여 그러한 힙을 정렬 할 수도 있습니다. 우선 순위 큐에 std::priority_queue을 사용할 수는 있지만 실제로는 원하는대로 처리 할 수는 없습니다. 또한 std::make_heap()std::heap_sort()은 함께 C++에서 heaport를 수행하는 매우 간단한 방법을 만듭니다.

4

[바이너리] 힙을 생성하려면 기본적으로 두 가지 방법이 있습니다. 빈 힙을 만들어 각 요소를 한 번에 하나씩 삽입하거나 값의 범위를 가져 와서 값을 늘립니다.

힙을 누를 때마다 O (logn) 시간이 걸리므로 N 개의 항목을 힙으로 밀어 넣으면 O (NlogN) 시간이 걸립니다. 그러나 값 배열로 바이너리 힙을 만들려면 O (N) 시간 만 필요합니다.

따라서 각 요소를 배열 (또는 임의 액세스 반복자를 지원하는 다른 컨테이너)에 삽입 한 다음 삽입하는 동안 힙 구조를 유지 관리하는 것보다 배열에서 make_heap()을 호출하는 것이 더 적합합니다.

7

std::make_heap은 실제로 거의 사용하지 않아야합니다. 힙이 우선 순위 큐에 유용하다는 것은 사실이지만 구조를 수동으로 유지하려는 이유는 설명하지 않습니다. std::priority_queue에는 우선 순위 대기열이 필요한 경우 훨씬 더 유용한 인터페이스가 있습니다.

make_heap 및 해당 형제를 직접 사용하는 경우 기본 컨테이너를 변경할 때마다 사용해야합니다. 나는 그들이 2 ~ 3 번 사용되었고 매번 그들이 잘못 사용 된 것을 보았습니다.

잠시 동안 우선 순위 큐로 벡터를 사용하고 정렬해야하기 때문에 직접 힙 연산을 한 번 사용했습니다. 대부분 std::make_heap은 절대로 필요하지 않습니다.

요소를 변경할 수있는 우선 순위 큐가 필요한 경우 std::set을 사용할 수 있습니다. 각각 *s.begin() 또는 *s.rbegin()으로 최소 또는 최대 요소를 가져올 수 있으며 이전 값을 제거하고 새 값을 삽입하여 요소를 업데이트 할 수 있습니다.

+3

2 년 전 * 다른 사람들이 지적했듯이이 질문이 제기 될 때 기능에 이점이 있습니다.특히 두 개의 개별 데이터 세트를 유지하지 않고도 정렬되지 않은 데이터에서 정렬 된 데이터로 신속하게 이동할 수 있습니다. 'std :: priority_queue'는 여러분이 필요로하는 것이 모두 힙인 경우에 유용합니다. 그러나 여러분의 요구가 그보다 복잡하다면, 힙 함수가 아주 쉽게 만들 수 있습니다. –

+3

@Dennis Zickefoose : 내가 말할 수있는 한, 나는 우선 순위 큐로 사용한 후에 데이터를 정렬하는 경우를 언급 한 유일한 사람입니다. 그래서 나는 거의 * 거의 쓰지 않았습니다. 'make_heap'가 힙을 만드는 데 사용된다고 말하는 것은 유용한 답이 아닙니다. 특히 힙만 필요하면 거의 사용하지 않기 때문에 유용합니다. –

+0

@ JørgenFogh std :: priority_queue에는 알려진 세트를 대기열로 변환 할 수있는 방법이 없습니다. 한 번에 모두 완료되면 대기열을 만드는 것은 O (n)이지만 한 번에 하나의 요소 만 수행하면 O (n log n)가됩니다. 그게 중요하면 std :: priority_queue –

관련 문제