原文: https://www.programiz.com/dsa/heap-data-structure

在本教程中,您将学习什么是堆数据结构。 此外,您还将找到在 C,C++ ,Java 和 Python 中进行堆操作的工作示例。

堆数据结构是满足堆属性的完全二叉树,也称为二叉堆。

完全二叉树是一种特殊的二叉树,其中

  • 除最后一个级别外,每个级别都已填充
  • 所有节点都尽可能地向左

堆数据结构 - 图1

堆属性是其中节点的属性

  • (对于最大堆)每个节点的键始终大于其子节点,并且根节点的键在所有其他节点中最大;
    堆数据结构 - 图2
  • (对于最小堆)每个节点的键始终小于子节点,而根节点的键在所有其他节点中最小。

堆数据结构 - 图3


堆操作

下面将对在堆上执行的一些重要操作及其算法进行描述。

建堆

建堆是从二叉树创建堆数据结构的过程。 它用于创建最小堆或最大堆。

  1. 令输入数组为
    堆数据结构 - 图4
  2. 从数组创建完全二叉树
    堆数据结构 - 图5
  3. 从索引为n/2 - 1的非叶节点的第一个索引开始。
    堆数据结构 - 图6
  4. 将当前元素i设置为largest
  5. 左子索引由2i + 1给出,右子索引由2i + 2给出。
    如果leftChild大于currentElement(即位于ith索引处的元素),则将leftChildIndex设置为最大。
    如果rightChild大于largest中的元素,请将rightChildIndex设置为largest
  6. largestcurrentElement交换
  7. 重复步骤 3-7,直到子树也被堆积。
    堆数据结构 - 图7

算法

  1. Heapify(array, size, i)
  2. set i as largest
  3. leftChild = 2i + 1
  4. rightChild = 2i + 2
  5. if leftChild > array[largest]
  6. set leftChildIndex as largest
  7. if rightChild > array[largest]
  8. set rightChildIndex as largest
  9. swap array[i] and array[largest]

要创建最大堆:

  1. MaxHeap(array, size)
  2. loop from the first index of non-leaf node down to zero
  3. call heapify

对于最小堆,对于所有节点,leftChildrightChild都必须小于父节点。


将元素插入堆

最大堆中的插入算法

  1. If there is no node,
  2. create a newNode.
  3. else (a node is already present)
  4. insert the newNode at the end (last node from left to right.)
  5. heapify the array
  1. 在树的末尾插入新元素。
    堆数据结构 - 图8
  2. 对树建堆。

堆数据结构 - 图9

对于最小堆,对上述算法进行了修改,以使parentNode始终小于newNode


从堆中删除元素

最大堆中的删除算法

  1. If nodeToBeDeleted is the leafNode
  2. remove the node
  3. Else swap nodeToBeDeleted with the lastLeafNode
  4. remove noteToBeDeleted
  5. heapify the array
  1. 选择要删除的元素。
    堆数据结构 - 图10
  2. 将其与最后一个元素交换。
    堆数据结构 - 图11
  3. 删除最后一个元素。
    堆数据结构 - 图12
  4. 对树建堆。

堆数据结构 - 图13

对于最小堆,对上述算法进行了修改,以使childNodes均小于currentNode


窥视(找到最大/最小)

窥视操作从最大堆中返回最大元素,或者从最小堆中返回最小元素,而不删除节点。

对于最大堆和最小堆

  1. return rootNode

提取最大/最小

从最大堆中删除后,Extract-Max返回具有最大值的节点,而从最小堆中删除后,Extract-Min返回具有最小值的节点。


Python,Java,C/C++ 示例

  1. # Max-Heap data structure in Python
  2. def heapify(arr, n, i):
  3. largest = i
  4. l = 2 * i + 1
  5. r = 2 * i + 2
  6. if l < n and arr[i] < arr[l]:
  7. largest = l
  8. if r < n and arr[largest] < arr[r]:
  9. largest = r
  10. if largest != i:
  11. arr[i],arr[largest] = arr[largest],arr[i]
  12. heapify(arr, n, largest)
  13. def insert(array, newNum):
  14. size = len(array)
  15. if size == 0:
  16. array.append(newNum)
  17. else:
  18. array.append(newNum);
  19. for i in range((size//2)-1, -1, -1):
  20. heapify(array, size, i)
  21. def deleteNode(array, num):
  22. size = len(array)
  23. i = 0
  24. for i in range(0, size):
  25. if num == array[i]:
  26. break
  27. array[i], array[size-1] = array[size-1], array[i]
  28. array.remove(size-1)
  29. for i in range((len(array)//2)-1, -1, -1):
  30. heapify(array, len(array), i)
  31. arr = []
  32. insert(arr, 3)
  33. insert(arr, 4)
  34. insert(arr, 9)
  35. insert(arr, 5)
  36. insert(arr, 2)
  37. print ("Max-Heap array: " + str(arr))
  38. deleteNode(arr, 4)
  39. print("After deleting an element: " + str(arr))
  1. // Max-Heap data structure in Java
  2. import java.util.ArrayList;
  3. class Heap {
  4. void heapify(ArrayList<Integer> hT, int i) {
  5. int size = hT.size();
  6. int largest = i;
  7. int l = 2 * i + 1;
  8. int r = 2 * i + 2;
  9. if (l < size && hT.get(l) > hT.get(largest))
  10. largest = l;
  11. if (r < size && hT.get(r) > hT.get(largest))
  12. largest = r;
  13. if (largest != i) {
  14. int temp = hT.get(largest);
  15. hT.set(largest, hT.get(i));
  16. hT.set(i, temp);
  17. heapify(hT, largest);
  18. }
  19. }
  20. void insert(ArrayList<Integer> hT, int newNum) {
  21. int size = hT.size();
  22. if (size == 0) {
  23. hT.add(newNum);
  24. } else {
  25. hT.add(newNum);
  26. for (int i = size / 2 - 1; i >= 0; i--) {
  27. heapify(hT, i);
  28. }
  29. }
  30. }
  31. void deleteNode(ArrayList<Integer> hT, int num)
  32. {
  33. int size = hT.size();
  34. int i;
  35. for (i = 0; i < size; i++)
  36. {
  37. if (num == hT.get(i))
  38. break;
  39. }
  40. int temp = hT.get(i);
  41. hT.set(i, hT.get(size-1));
  42. hT.set(size-1, temp);
  43. hT.remove(size-1);
  44. for (int j = size / 2 - 1; j >= 0; j--)
  45. {
  46. heapify(hT, j);
  47. }
  48. }
  49. void printArray(ArrayList<Integer> array, int size) {
  50. for (Integer i : array) {
  51. System.out.print(i + " ");
  52. }
  53. System.out.println();
  54. }
  55. public static void main(String args[]) {
  56. ArrayList<Integer> array = new ArrayList<Integer>();
  57. int size = array.size();
  58. Heap h = new Heap();
  59. h.insert(array, 3);
  60. h.insert(array, 4);
  61. h.insert(array, 9);
  62. h.insert(array, 5);
  63. h.insert(array, 2);
  64. System.out.println("Max-Heap array: ");
  65. h.printArray(array, size);
  66. h.deleteNode(array, 4);
  67. System.out.println("After deleting an element: ");
  68. h.printArray(array, size);
  69. }
  70. }
  1. // Max-Heap data structure in C
  2. #include <stdio.h>
  3. int size = 0;
  4. void swap(int *a, int *b)
  5. {
  6. int temp = *b;
  7. *b = *a;
  8. *a = temp;
  9. }
  10. void heapify(int array[], int size, int i)
  11. {
  12. if (size == 1)
  13. {
  14. printf("Single element in the heap");
  15. }
  16. else
  17. {
  18. int largest = i;
  19. int l = 2 * i + 1;
  20. int r = 2 * i + 2;
  21. if (l < size && array[l] > array[largest])
  22. largest = l;
  23. if (r < size && array[r] > array[largest])
  24. largest = r;
  25. if (largest != i)
  26. {
  27. swap(&array[i], &array[largest]);
  28. heapify(array, size, largest);
  29. }
  30. }
  31. }
  32. void insert(int array[], int newNum)
  33. {
  34. if (size == 0)
  35. {
  36. array[0] = newNum;
  37. size += 1;
  38. }
  39. else
  40. {
  41. array[size] = newNum;
  42. size += 1;
  43. for (int i = size / 2 - 1; i >= 0; i--)
  44. {
  45. heapify(array, size, i);
  46. }
  47. }
  48. }
  49. void deleteRoot(int array[], int num)
  50. {
  51. int i;
  52. for (i = 0; i < size; i++)
  53. {
  54. if (num == array[i])
  55. break;
  56. }
  57. swap(&array[i], &array[size - 1]);
  58. size -= 1;
  59. for (int i = size / 2 - 1; i >= 0; i--)
  60. {
  61. heapify(array, size, i);
  62. }
  63. }
  64. void printArray(int array[], int size)
  65. {
  66. for (int i = 0; i < size; ++i)
  67. printf("%d ", array[i]);
  68. printf("\n");
  69. }
  70. int main()
  71. {
  72. int array[10];
  73. insert(array, 3);
  74. insert(array, 4);
  75. insert(array, 9);
  76. insert(array, 5);
  77. insert(array, 2);
  78. printf("Max-Heap array: ");
  79. printArray(array, size);
  80. deleteRoot(array, 4);
  81. printf("After deleting an element: ");
  82. printArray(array, size);
  83. }
// Max-Heap data structure in C++

#include <iostream>
#include <vector>
using namespace std;

void swap(int *a, int *b)
{
  int temp = *b;
  *b = *a;
  *a = temp;
}
void heapify(vector<int> &hT, int i)
{
  int size = hT.size();
  int largest = i;
  int l = 2 * i + 1;
  int r = 2 * i + 2;
  if (l < size && hT[l] > hT[largest])
    largest = l;
  if (r < size && hT[r] > hT[largest])
    largest = r;

  if (largest != i)
  {
    swap(&hT[i], &hT[largest]);
    heapify(hT, largest);
  }
}
void insert(vector<int> &hT, int newNum)
{
  int size = hT.size();
  if (size == 0)
  {
    hT.push_back(newNum);
  }
  else
  {
    hT.push_back(newNum);
    for (int i = size / 2 - 1; i >= 0; i--)
    {
      heapify(hT, i);
    }
  }
}
void deleteNode(vector<int> &hT, int num)
{
  int size = hT.size();
  int i;
  for (i = 0; i < size; i++)
  {
    if (num == hT[i])
      break;
  }
  swap(&hT[i], &hT[size - 1]);

  hT.pop_back();
  for (int i = size / 2 - 1; i >= 0; i--)
  {
    heapify(hT, i);
  }
}
void printArray(vector<int> &hT)
{
  for (int i = 0; i < hT.size(); ++i)
    cout << hT[i] << " ";
  cout << "\n";
}

int main()
{
  vector<int> heapTree;

  insert(heapTree, 3);
  insert(heapTree, 4);
  insert(heapTree, 9);
  insert(heapTree, 5);
  insert(heapTree, 2);

  cout << "Max-Heap array: ";
  printArray(heapTree);

  deleteNode(heapTree, 4);

  cout << "After deleting an element: ";

  printArray(heapTree);
}

堆数据结构应用

  • 在实现优先队列时使用堆。
  • Dijkstra 算法
  • 堆排序