C++中的二叉堆和二叉搜索树

1. 二叉堆

二叉堆是一种常用的数据结构,可以用来进行优先队列的操作。同时,它也可以实现堆排序。二叉堆是一种完全二叉树,分为大根堆和小根堆。

1.1 大根堆

大根堆的每个节点都比它的子节点大。例如,下图就是一个大根堆。

100

/ \

80 90

/ \ / \

70 60 30 40

大根堆的实现方式可以采用数组来进行存储。将父节点的下标记做i,则其左子节点的下标为2*i,右子节点的下标为2*i+1。

当我们向大根堆中插入一个数时,我们需要将该数放置在堆的最后一个位置,并且不断和其父节点进行比较、交换,以维持堆的性质。详细地说,插入的过程如下所示:

将元素插入之后,如果其值比父节点大,则交换元素和父节点。

不断重复以上步骤,直到元素不再比父节点大或者已经到达根节点。

下面是大根堆的插入代码:

void maxHeapify(int arr[], int i, int size) {

int l = 2*i+1;

int r = 2*i+2;

int largest = i;

if (l < size && arr[l] > arr[largest])

largest=l;

if (r < size && arr[r] > arr[largest])

largest=r;

if (largest != i) {

swap(arr[i], arr[largest]);

maxHeapify(arr, largest, size);

}

}

void insert(int arr[], int& size, int val) {

arr[size] = val;

int i = size;

while (i > 0 && arr[(i-1)/2] < arr[i]) {

swap(arr[i], arr[(i-1)/2]);

i = (i-1)/2;

}

size++;

}

当我们需要删除堆中的元素时,我们需要将堆的最后一个元素放置到根节点处,并且对该节点进行下滤以保证堆的性质。详细地说,删除的过程如下所示:

将最后一个元素放置到根节点处。

将该节点不断和其子节点进行比较,如果某个子节点比其大,则交换元素。

不断重复以上步骤,直到节点没有子节点或者其子节点都比其小。

下面是大根堆的删除代码:

void deleteMax(int arr[], int& size) {

size--;

swap(arr[0], arr[size]);

maxHeapify(arr, 0, size);

}

1.2 小根堆

小根堆的每个节点都比它的子节点小。例如,下图就是一个小根堆。

10

/ \

20 30

/ \ / \

40 50 60 70

小根堆可以采用与大根堆类似的方式进行实现,只需要对插入和删除进行微调即可。

下面是小根堆的插入代码:

void minHeapify(int arr[], int i, int size) {

int l = 2*i+1;

int r = 2*i+2;

int smallest = i;

if (l < size && arr[l] < arr[smallest])

smallest=l;

if (r < size && arr[r] < arr[smallest])

smallest=r;

if (smallest != i) {

swap(arr[i], arr[smallest]);

minHeapify(arr, smallest, size);

}

}

void insert(int arr[], int& size, int val) {

arr[size] = val;

int i = size;

while (i > 0 && arr[(i-1)/2] > arr[i]) {

swap(arr[i], arr[(i-1)/2]);

i = (i-1)/2;

}

size++;

}

下面是小根堆的删除代码:

void deleteMin(int arr[], int& size) {

size--;

swap(arr[0], arr[size]);

minHeapify(arr, 0, size);

}

2. 二叉搜索树

二叉搜索树是一种最常用的数据结构之一。它是一棵二叉树,其中每个节点都包含一个关键字,且每个节点的左子树中的所有节点的关键字都小于该节点的关键字,每个节点的右子树中的所有节点的关键字都大于该节点的关键字。

下面是一棵二叉搜索树的例子:

8

/ \

3 10

/ \ \

1 6 14

/ \ /

4 7 13

二叉搜索树可以用来进行快速查找、插入、删除等操作。下面介绍二叉搜索树的查找、插入、删除操作。

2.1 查找

查找一个元素在二叉搜索树中的位置可以采用递归的方式进行实现。如果需要查找的节点值小于当前节点的值,则递归查找当前节点的左子树。反之,如果需要查找的节点值大于当前节点的值,则递归查找当前节点的右子树。如果查找成功,则返回该节点;如果查找失败,则返回空值。

下面是二叉搜索树的查找代码:

TreeNode* search(TreeNode* root, int val) {

if (root == NULL || root->val == val)

return root;

if (root->val > val)

return search(root->left, val);

else

return search(root->right, val);

}

2.2 插入

在二叉搜索树中插入一个节点可以采用递归的方式进行实现。如果需要插入的节点值小于当前节点的值,则递归插入当前节点的左子树。反之,如果需要插入的节点值大于当前节点的值,则递归插入当前节点的右子树。如果查找失败,则创建一个新的节点,并且将其插入到该节点的左子树或右子树中。

下面是二叉搜索树的插入代码:

TreeNode* insert(TreeNode* root, int val) {

if (root == NULL)

return new TreeNode(val);

if (root->val > val)

root->left = insert(root->left, val);

else

root->right = insert(root->right, val);

return root;

}

2.3 删除

在二叉搜索树中删除一个节点需要考虑到多种情况。如果需要删除的节点是叶子节点,则直接删除该节点即可。如果需要删除的节点只有一个子节点,则将该节点的子节点代替该节点即可。如果需要删除的节点有两个子节点,则需要找到该节点的后继节点(即比该节点大的最小节点),将该节点的值替换为后继节点的值,并且递归删除后继节点。

下面是二叉搜索树的删除代码:

TreeNode* deleteNode(TreeNode* root, int key) {

if (root == NULL)

return NULL;

if (root->val > key) {

root->left = deleteNode(root->left, key);

return root;

}

if (root->val < key) {

root->right = deleteNode(root->right, key);

return root;

}

if (root->left == NULL) {

TreeNode* right = root->right;

delete root;

return right;

}

if (root->right == NULL) {

TreeNode* left = root->left;

delete root;

return left;

}

TreeNode* successor = getSuccessor(root);

root->val = successor->val;

root->right = deleteNode(root->right, successor->val);

return root;

}

TreeNode* getSuccessor(TreeNode* root) {

root = root->right;

while (root != NULL && root->left != NULL)

root = root->left;

return root;

}

3. 总结

本文介绍了C++中的二叉堆和二叉搜索树。二叉堆是一种常用的数据结构,可以用来进行优先队列的操作。同时,它也可以实现堆排序。二叉搜索树是一种最常用的数据结构之一。它是一棵二叉树,其中每个节点都包含一个关键字,且每个节点的左子树中的所有节点的关键字都小于该节点的关键字,每个节点的右子树中的所有节点的关键字都大于该节点的关键字。二叉搜索树可以用来进行快速查找、插入、删除等操作。

总之,C++中的二叉堆和二叉搜索树是非常重要的数据结构。它们具有广泛的应用,对于每个C++程序员来说都是必备的知识。

免责声明:本文来自互联网,本站所有信息(包括但不限于文字、视频、音频、数据及图表),不保证该信息的准确性、真实性、完整性、有效性、及时性、原创性等,版权归属于原作者,如无意侵犯媒体或个人知识产权,请来电或致函告之,本站将在第一时间处理。猿码集站发布此文目的在于促进信息交流,此文观点与本站立场无关,不承担任何责任。

后端开发标签