数据结构小记【Python/C++版】——BST树篇

一,基础概念

BST树,英文全称:Binary Search Tree,被称为二叉查找树或二叉搜索树。

如果一个二叉查找树非空,那么它具有如下性质:

1.左子树上所有节点的值小于根节点的值,节点上的值沿着边的方向递减。

2.右子树上所有节点的值大于根节点的值,节点上的值沿着边的方向递增。

3.非空的左子树和右子树也分别是二叉查找树。

4.按照中序遍历(左子树->根节点->右子树)的方式遍历该二叉查找树,可以得到一个递增的有序序列。

~来个复杂点的热热身~

该BST树的中序遍历结果:7 15 17 22 27 30 45 60 75

注意,BST树的结构不是一次性立即生成的,而是基于查找过程逐渐生成的。在查找过程中,当树中的节点元素不等于被查找值时,才进行插入节点的操作。

使用二叉查找树的好处

如果BST树是一棵平衡二叉树,那么在BST树上进行插入和删除操作的速度会很快。

由于BST树的特殊结构,导致在上面搜索元素的时候特别高效。

使用二叉查找树的缺点       

BST树的最终形状依赖于插入操作的顺序,导致BST树可以退化成单链表(如果单调递减式的插入元素),后面会讲到AVL树,可以规避此缺点。

二,BST树的基本操作

查找节点:

1.从树的根节点开始移动。

2.如果被查找值小于当前节点,则向左移动。

3.如果被查找值大于当前节点,则向右移动。

插入节点:

1.先执行查找操作,来确定新节点的位置。

2.确认位置后,插入新节点,新节点成为叶子节点。

删除节点:

从BST树删除节点时,我们关心的是保持树的其余节点以正确的顺序排列。

删除节点的实际操作是将节点替换为NULL。

根据删除节点的位置不同,分下面三种情况:

(1)要删除的节点是叶子节点。简单执行删除操作。

(2)如果节点只有一个子节点。删除后,用子节点填充它原来的位置。

(3)如果节点有两个子节点。根据大小,将它和左子树的最大节点交换,或者和右子树的最小节点交换。因为左子树的最大节点是叶子节点,没有右子节点且不会继续扩展,右子树的最小节点也是叶子节点,没有左子节点且不会继续扩展。

三,BST树的代码实现

代码样例中的BST树采用的是链式存储实现,代码中节点的初始化和一般的二叉树代码类似,由数据域、左指针、右指针构成。

遍历顺序:1->3->4->6->7->8->10->14

Python代码实现:

#初始化节点
class Node:
    def __init__(self, key):
        self.key = key
        self.left = None
        self.right = None

#中序遍历
def inorder(root):
    if root is not None:
        inorder(root.left)
        print(str(root.key) + "->", end=' ')
        inorder(root.right)

#插入节点
def insert(node, key):
    if node is None:
        return Node(key)
    if key < node.key:
        node.left = insert(node.left, key)
    else:
        node.right = insert(node.right, key)
    return node

def minValueNode(node):
    current = node
    while(current.left is not None):
        current = current.left
    return current

#删除节点
def deleteNode(root, key):
    if root is None:
        return root

    if key < root.key:
        root.left = deleteNode(root.left, key)
    elif(key > root.key):
        root.right = deleteNode(root.right, key)
    else:
        if root.left is None:
            temp = root.right
            root = None
            return temp

        elif root.right is None:
            temp = root.left
            root = None
            return temp

        #如果被删除节点有两个子节点
        temp = minValueNode(root.right)
        root.key = temp.key
        root.right = deleteNode(root.right, temp.key)
    return root

root = None
root = insert(root, 8)
root = insert(root, 3)
root = insert(root, 1)
root = insert(root, 6)
root = insert(root, 7)
root = insert(root, 10)
root = insert(root, 14)
root = insert(root, 4)

print("Inorder traversal: ", end=' ')
inorder(root)

print("\nDelete 10")
root = deleteNode(root, 10)
print("Inorder traversal: ", end=' ')
inorder(root)

运行结果:

Inorder traversal:  1-> 3-> 4-> 6-> 7-> 8-> 10-> 14->
Delete 10
Inorder traversal:  1-> 3-> 4-> 6-> 7-> 8-> 14->

C++代码实现:

#include <iostream>
using namespace std;
//初始化节点
struct node {
    int key;
    struct node* left, * right;
};
//创建新的节点
struct node* newNode(int item) {
    struct node* temp = (struct node*)malloc(sizeof(struct node));
    temp->key = item;
    temp->left = temp->right = NULL;
    return temp;
}
//中序遍历
void inorder(struct node* root) {
    if (root != NULL) {
        inorder(root->left);
        cout << root->key << " -> ";
        inorder(root->right);
    }
}
//插入节点
struct node* insert(struct node* node, int key) {
    if (node == NULL) return newNode(key);
    if (key < node->key)
        node->left = insert(node->left, key);
    else
        node->right = insert(node->right, key);
    return node;
}
struct node* minValueNode(struct node* node) {
    struct node* current = node;
    while (current && current->left != NULL)
        current = current->left;
    return current;
}
//删除节点
struct node* deleteNode(struct node* root, int key) {
    if (root == NULL) return root;
    if (key < root->key)
        root->left = deleteNode(root->left, key);
    else if (key > root->key)
        root->right = deleteNode(root->right, key);
    else {
        if (root->left == NULL) {
            struct node* temp = root->right;
            free(root);
            return temp;
        }
        else if (root->right == NULL) {
            struct node* temp = root->left;
            free(root);
            return temp;
        }

        //如果被删除节点有两个子节点
        struct node* temp = minValueNode(root->right);
        root->key = temp->key;
        root->right = deleteNode(root->right, temp->key);
    }
    return root;
}
int main() {
    struct node* root = NULL;
    root = insert(root, 8);
    root = insert(root, 3);
    root = insert(root, 1);
    root = insert(root, 6);
    root = insert(root, 7);
    root = insert(root, 10);
    root = insert(root, 14);
    root = insert(root, 4);
    cout << "Inorder traversal: ";
    inorder(root);
    cout << "\nAfter deleting 10\n";
    root = deleteNode(root, 10);
    cout << "Inorder traversal: ";
    inorder(root);
}

运行结果:

Inorder traversal: 1 -> 3 -> 4 -> 6 -> 7 -> 8 -> 10 -> 14 ->
After deleting 10
Inorder traversal: 1 -> 3 -> 4 -> 6 -> 7 -> 8 -> 14 ->

四,参考阅读 

https://courses.engr.illinois.edu/cs225/sp2019/notes/bst/

https://www.programiz.com/dsa/binary-search-tree

  • 17
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值