LeetCode - 2. Algoritmo de classificação de heap

Um e dois garfos

  O heap binário é essencialmente uma árvore binária completa, que é dividida em dois tipos:

  1. Heap máximo: o valor de qualquer nó pai do heap máximo é maior ou igual ao valor de seus nós filho esquerdo e direito.
    Insira a descrição da imagem aqui
  2. Pilha mínima: O valor de qualquer nó pai da pilha menor é menor ou igual ao valor de seus nós filho esquerdo e direito.
      O nó raiz de um heap binário é chamado de topo do heap. As características do maior heap e do menor heap determinam que o topo do maior heap é o maior elemento de todo o heap; o topo do menor heap é o menor elemento de todo o heap.

Em segundo lugar, o autoajuste da pilha

1. Insira o nó

  Vamos pegar o menor heap como exemplo para ver como o heap binário é ajustado.
Insira a descrição da imagem aqui

Conforme mostrado na figura, ao inserir o nó 0 no heap binário, o nó 0 e o nó 5 não atendem à estrutura do heap binário, então o nó 0 e o nó 5 são trocados; o nó 0 e o nó 3 não atendem à estrutura do heap binário, então o nó 0 e o nó 3 são trocados, e ao mesmo tempo, após a troca, ver se o nó 3 e o nó 5 atendem a estrutura da árvore binária, sim! O nó 0 e o nó 1 não atendem a estrutura da árvore binária, eles são trocados e, ao mesmo tempo, veja se o nó 1 e o nó 3 atendem a estrutura da árvore binária da mesma forma.

Princípios principais:

Se o nó inserido e o nó pai atendem à estrutura do heap binário, se não, o nó inserido é ajustado para cima e o nó pai é ajustado para baixo.

2. Exclua o nó

  Excluir um nó significa retirar um nó do heap, geralmente removendo o topo do heap. Vamos pegar o menor heap como exemplo para mostrar como o heap binário exclui nós.
Insira a descrição da imagem aqui
  Quando excluímos o topo do menor heap (não excluímos completamente, mas substituímos até o fim)

Conforme mostrado na figura, primeiro troque o nó superior 1 pelo último nó folha 10. Então veja se o nó 10 atende a estrutura do heap binário, se não, ajuste para baixo, e o nó 10 troca com o nó folha pequeno 2 (se ele troca com o nó folha 3, a estrutura do heap binário ainda não está satisfeita) , O nó 10 ainda não atende à definição de heap mínimo e troca com o nó folha 7.

3. Construir um heap binário

  Construa um heap binário. É para ajustar uma árvore binária completa desordenada a um heap binário, que é essencialmente para fazer todos os nós não-folha afundarem de uma vez.

  • debaixo para cima
  • Careca

Insira a descrição da imagem aqui
O seguinte descreve a abordagem ascendente para ajustar a árvore binária não ordenada acima para o menor heap:

Primeiro, o nó 6 troca com o nó 10, o nó 2 troca com o nó 3. Como o nó 5 e o nó 2 são nós folha na árvore binária original, não há necessidade de ajustar para baixo. O nó 1 é trocado pelo nó 7, o nó 7 é ajustado para baixo, o nó 7 é trocado pelo nó 5 e o heap binário mínimo é estabelecido!

Três, a realização da pilha

  Embora o heap binário seja uma árvore binária completa, seu método de armazenamento não é armazenamento em cadeia, mas armazenamento sequencial . Em outras palavras, todos os nós do heap binário são armazenados na matriz .
  Então, como localizar o nó pai do nó filho ou o nó filho do nó pai?
Insira a descrição da imagem aqui
  O heap binário pode ser convertido em uma matriz. Os arrays também podem ser convertidos em heaps binários. A relação de índice entre o nó filho e o nó pai na matriz é a seguinte:

Se o índice do nó pai for n, os índices dos dois nós filhos serão 2n + 1, 2n + 2, respectivamente.
Conforme mostrado na figura acima, os índices dos nós 6, 9 e 10 são 3,
7 e
8. 7 = 2 × 3 + 1 8 = 2 × 3 + 2
Se o índice do nó filho for conhecido, ( nó filho index-1) / 2 e, em seguida, arredondar para baixo.

Quatro, LeetCode

  215. Encontre o maior k-ésimo elemento na matriz não classificada (você precisa encontrar o k-ésimo maior elemento após a matriz ser classificada)

Entrada: [3,2,1,5,6,4] e
saída k : 5

class Solution():
    def findKthLarget(self, nums, k):
        self._k = k
        return self.heap_sort(nums)

    def heap_sort(self, nums):
        """
        堆排序
        将根节点取出与最后一位做对调,对前面len-1个节点继续进行堆调整过程
        :param nums: 数组
        :return:
        """
        self.build_max_heap(nums)
        print(nums)
        cnt = 0
        # 调整后列表的第一个元素就是这个列表中最大的元素,
        # 将其与最后一个元素交换,然后将剩余的列表再递归的调整为最大堆
        for i in range(len(nums) - 1, -1, -1):
            nums[0], nums[i] = nums[i], nums[0]
            cnt += 1
            if cnt == self._k:
                return nums[i]
            self.max_heapify(nums, i, 0)

    def build_max_heap(self, nums):
        """
        构建最大堆
        :param nums: 数组
        :return: 最大堆
        """
        length = len(nums)
        for i in range((length - 2) // 2, -1, -1):  # 自底向上建堆
            self.max_heapify(nums, length, i)

    def max_heapify(self, nums, length, root):
        '''
        调整列表中的元素并保证以root为根的堆是一个大根堆
        给定某个节点的下标root,这个节点的父节点、左子节点、右子节点的下标都可以被计算出来。
        索引从0开始时
        父节点:(root-1)//2
        左子节点:2*root + 1
        右子节点:2*root + 2  即:左子节点 + 1
        '''
        left = 2 * root + 1
        right = left + 1
        larger = root
        if left < length and nums[larger] < nums[left]:
            larger = left
        if right < length and nums[larger] < nums[right]:
            larger = right
        # larger的值等于左节点或者右节点的值时,需要做堆调整
        if larger != root:
            nums[larger], nums[root] = nums[root], nums[larger]
            # 递归的对子树做调整
            self.max_heapify(nums, length, larger)


def main():
    nums = [3,2,1,5,6,4]
    k = 2
    s = Solution()
    kth_element = s.findKthLarget(nums, k)
    print('数组中第%d个最大元素为%d' % (k, kth_element))


if __name__ == '__main__':
    main()
[6, 5, 4, 3, 2, 1]
数组中第2个最大元素为5

Acho que você gosta

Origin blog.csdn.net/weixin_46649052/article/details/114379527
Recomendado
Clasificación