데이터 구조 및 알고리즘 - 힙 트리

하나: 소개

        1. 우선순위 큐: 지난 수업에서 이야기한 허프만 트리를 아직도 기억하시나요? 개발 작업을 대폭 줄이기 위해 우선순위 큐를 사용했는데, 이 우선순위 큐가 내부적으로 어떻게 구현되는지 아시나요?

        해결 방법: 힙 상단이 크면 먼저 상단을 삭제하세요.

        2. 사용자 핫서치 순위 기능(Weibo 핫서치)을 어떻게 구현하나요? 1억 개의 키워드가 포함된 사용자 검색 로그가 있는 경우 상위 10개의 키워드를 추출하는 방법은 무엇입니까? 당신에게 주어진 처리 기계: 2CPU 2G 메모리. 연령, 0~200

        해결 방법: 1. 발생 빈도 계산 2. 크기 10의 큰 상단 힙 유지

        3.2 TOP K 문제, 예를 들어 1,000만 개의 숫자로 구성된 문자열이 주어지면 상위 k개의 가장 큰 숫자를 찾으세요. 하나는 정적 데이터이고 다른 하나는 동적 데이터입니다.

2: 힙의 정의

        힙이란 무엇입니까? 힙은 다음 두 가지 사항을 충족해야 하는 특별한 종류의 트리입니다.

1. 완전 이진 트리                 입니다 . ( 마지막 레이어를 제외하고 다른 레이어의 모든 노드는 가득 차고 마지막 레이어의 노드는 왼쪽에 배열되어야 합니다. )

                2. 각 노드의 값은 왼쪽 및 오른쪽 자식 노드의 값보다 크거나 같거나 작거나 같습니다.

        그러나 이진 검색 트리와는 다릅니다. 왼쪽 노드는 루트 노드보다 작고 오른쪽 노드는 루트 노드보다 큽니다.

작은 상단 더미
큰 꼭대기 더미

3: 힙 작업

       3.1 힙 저장 

내가 전에 말한 것을 기억한다면 완전한 이진 트리를 위한 가장 좋은 저장 구조는 배열이라는         것을 알아야 합니다 . 특별한 속성이 있기 때문에 아래 첨자를 직접 사용하여 왼쪽 및 오른쪽 노드를 나타낼 수 있습니다.

        예를 들어 오른쪽의 구조는 다음과 같습니다.

        1시 10분

        2시 8분

        3시 7분

        4시 6분

        5시 4분

        6시 3분

        이전에 이야기한 왼쪽 및 오른쪽 하위 노드에 대한 공식을 기억하십시오. Left = 2*I i는 현재 점이 위치한 배열의 첨자입니다. 오른쪽=2*i+1

                        아래 첨자가 0부터 시작하면 다음 두 공식이 됩니다: 2*i+1, 2*i+2

3.2 힙에 삽입(두 가지 삽입 방법: 위에서 아래로, 아래에서 위로)

        힙이 삽입되는 위치를 힙화라고 합니다.

        위에서 아래로: 실제로 삽입된 지점을 힙의 맨 위에 놓고 순서대로 비교하면 됩니다.

        아래에서 위로: 오른쪽 그림의 9를 삽입해 보겠습니다. 당연히 이때 9를 삽입한 후에는 힙 트리의 속성을 만족하지 못하므로 어떻게 해야 할까요? 실제로 더 이상 교환할 수 없을 때까지만 교환하면 됩니다.아래 그림을 참조하세요.

완전한 이진 트리. 완전 이진 트리와 유사하게 32개의 레이어는 21억 개 이상의 포인트를 가질 수 있습니다. n개의 숫자는 몇 번이나 교환될 수 있습니까?

최대 교환 횟수는 책의 높이이며, 마지막 레이어는 처리할 필요가 없으므로 최대 교환 횟수는 Logn-1 회 이다.

9 삽입과정

3.3 힙 삭제

        1. 힙 상단 삭제: 힙 상단의 숫자를 마지막 숫자와 교환한 다음 힙을 정렬하면 결국 완전한 이진 트리가 보장될 수 있습니다. 노드.

4: 힙 트리 적용

        1. 힙 정렬

                이전에 정렬에 대해 이야기할 때 힙 정렬에 대해 이야기하지 않았다는 것을 다들 기억하실 겁니다. 오늘은 살펴보도록 하겠습니다. 이 힙 트리를 정렬에 사용하면 어떨까요?

수열이 주어졌다고 가정합니다: 8 4 20 7 3 1 25 14 17

        힙 트리를 사용하여 정렬:

                1. 먼저 완전한 이진 트리에 순서대로 저장합니다.

                힙을 구축합니다.

                2. 리프가 아닌 마지막 노드에서 힙을 생성합니다 . 마지막 리프 노드가 아닌 마지막 비리프 노드인 이유는 무엇입니까? 예를 보세요:

하나: 처음부터 오른쪽으로, 즉 처음부터 뒤쪽으로 건물을 짓는 것입니다.

두 가지 유형: 뒤에서 앞으로 교정. 어레이 뒤에서 앞으로 이동

        정렬: 그렇다면 정렬을 어떻게 구현합니까?
힙의 상단과 마지막 요소를 교환하고 교환 후 힙 변환을 수행하며 이 작업을 순차적으로 수행합니다.
그냥 해보고 모두가 와서 보게 해주세요. 동시에, 각 정렬 후에 다시 정렬된 항목을 다시 정렬할 필요가 없습니다.

        

        

package tree.堆树;

import java.util.Arrays;

public class HeapSort {
	public static void main(String[] args) {
		int data[] = { 8, 4, 20, 7, 3, 1, 25, 14, 17 };
		heapSort(data);
		System.out.println(Arrays.toString(data));
	}

	/**
	 * 有int start, int end:参数是因为已经建好的就不需要再比较了,所以每次都有范围
	 * @param data
	 * @param start
	 * @param end
	 */
	public static void maxHeap(int data[], int start, int end) { // 建一个大顶堆,end表示最多建到的点 lgn

		int parent = start;
		int son = parent * 2 + 1; // 下标是从0开始的就要加1,从1就不用
		while (son < end) {
			int temp = son;
			// 比较左右节点和父节点的大小     son:表示左结点  son+1:表示右结点
			if (son + 1 < end && data[son] < data[son + 1]) { // 表示右节点比左节点到
				temp = son + 1; // 就要换右节点跟父节点
			}
			// temp表示的是 我们左右节点大的那一个
			if (data[parent] > data[temp])
				return; // 不用交换
			else { // 交换
				int t = data[parent];
				data[parent] = data[temp];
				data[temp] = t;
				parent = temp; // 继续堆化
				son = parent * 2 + 1;
			}
		}
		return;

	}

	public static void heapSort(int data[]) {

		int len = data.length;
		for (int i = len / 2 - 1; i >= 0; i--) { //o(nlgn)   len / 2 - 1:代表最后一个非叶子结点开始
			maxHeap(data, i, len);		//
		}
		for (int i = len - 1; i > 0; i--) { //o(nlgn)
			int temp = data[0];
			data[0] = data[i];
			data[i] = temp;
			maxHeap(data, 0, i);	//这个i能不能理解?因为len~i已经排好序了
		}
	}

}

추천

출처blog.csdn.net/qq_67801847/article/details/132870997