LeetCode — 2. Algoritmo de clasificación de montón

Uno y dos tenedores

  El montón binario es esencialmente un árbol binario completo, que se divide en dos tipos:

  1. Montón máximo: el valor de cualquier nodo padre del montón máximo es mayor o igual que el valor de sus nodos secundarios izquierdo y derecho.
    Inserte la descripción de la imagen aquí
  2. Montón mínimo: el valor de cualquier nodo principal del montón más pequeño es menor o igual que el valor de sus nodos secundarios izquierdo y derecho.
      El nodo raíz de un montón binario se denomina la parte superior del montón. Las características del montón más grande y el montón más pequeño determinan que la parte superior del montón más grande es el elemento más grande de todo el montón; la parte superior del montón más pequeño es el elemento más pequeño de todo el montón.

En segundo lugar, el autoajuste del montón

1. Insertar nodo

  Tomemos el montón más pequeño como ejemplo para ver cómo se ajusta el montón binario.
Inserte la descripción de la imagen aquí

Como se muestra en la figura, al insertar el nodo 0 en el montón binario, el nodo 0 y el nodo 5 no cumplen con la estructura del montón binario, por lo que el nodo 0 y el nodo 5 se intercambian; el nodo 0 y el nodo 3 no cumplen con la estructura del montón binario, por lo que el nodo 0 y el nodo 3 se intercambian, y al mismo tiempo, después del intercambio, ver si el nodo 3 y el nodo 5 cumplen con la estructura del árbol binario, ¡sí! El nodo 0 y el nodo 1 no cumplen con la estructura del árbol binario, se intercambian y, al mismo tiempo, ver si el nodo 1 y el nodo 3 cumplen la estructura del árbol binario de la misma manera.

Principios fundamentales:

Si el nodo insertado y el nodo principal cumplen con la estructura del montón binario, si no, el nodo insertado se ajusta hacia arriba y el nodo principal se ajusta hacia abajo.

2. Eliminar el nodo

  Eliminar un nodo significa sacar un nodo del montón, generalmente haciendo estallar la parte superior del montón. Tomemos el montón más pequeño como ejemplo para mostrar cómo el montón binario elimina nodos.
Inserte la descripción de la imagen aquí
  Cuando eliminamos la parte superior del montón más pequeño (no eliminamos por completo, sino reemplazamos hasta el final)

Como se muestra en la figura, primero intercambie el nodo superior 1 con el último nodo hoja 10. Luego, vea si el nodo 10 cumple con la estructura del montón binario, si no, ajuste hacia abajo, y el nodo 10 intercambia con el nodo hoja pequeño 2 (si intercambia con el nodo hoja 3, la estructura del montón binario todavía no está satisfecha) , El nodo 10 aún no cumple con la definición de montón mínima y se intercambia con el nodo hoja 7.

3. Crea un montón binario

  Construye un montón binario. Consiste en ajustar un árbol binario completo desordenado a un montón binario, que es esencialmente para hacer que todos los nodos que no son hojas se hundan a la vez.

  • de abajo hacia arriba
  • De arriba hacia abajo

Inserte la descripción de la imagen aquí
A continuación, se describe el enfoque ascendente para ajustar el árbol binario desordenado anterior al montón más pequeño:

Primero, el nodo 6 se intercambia con el nodo 10, el nodo 2 se intercambia con el nodo 3. Dado que el nodo 5 y el nodo 2 son nodos hoja en el árbol binario original, no hay necesidad de ajustar hacia abajo. El nodo 1 se intercambia con el nodo 7, el nodo 7 se ajusta hacia abajo, el nodo 7 se intercambia con el nodo 5 y se establece el montón binario mínimo.

Tres, la realización del montón

  Aunque el montón binario es un árbol binario completo, su método de almacenamiento no es el almacenamiento en cadena, sino el almacenamiento secuencial . En otras palabras, todos los nodos del montón binario se almacenan en la matriz .
  Entonces, ¿cómo ubicar el nodo principal del nodo secundario o el nodo secundario del nodo principal?
Inserte la descripción de la imagen aquí
  El montón binario se puede convertir en una matriz. Las matrices también se pueden convertir en montones binarios. La relación de índice entre el nodo hijo y el nodo padre en la matriz es la siguiente:

Si el índice del nodo principal es n, los índices de los dos nodos secundarios son 2n + 1, 2n + 2 respectivamente.
Como se muestra en la figura anterior, los índices de los nodos 6, 9 y 10 son 3,
7 y
8. 7 = 2 × 3 + 1 8 = 2 × 3 + 2
Si se conoce el índice del nodo hijo, ( child node index-1) / 2 y luego redondee hacia abajo.

Cuatro, LeetCode

  215. Encuentre el k-ésimo elemento más grande en la matriz no ordenada (necesita encontrar el k-ésimo elemento más grande después de ordenar la matriz)

Entrada: [3,2,1,5,6,4] yk
salida: 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

Supongo que te gusta

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