数据结构: 二叉搜索树

二叉搜索树

二叉查找树(Binary Search Tree),也称二叉搜索树、有序二叉树(ordered binary tree),排序二叉树(orted binary tree)

特点:

  • 二叉树
  • 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值
  • 若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值
  • 任意节点的左,右子树也分别为二叉查找树
  • 没有键值相等的节点

注:

  • 必须是完全二叉树
  • 二叉搜索树不一定是完全二叉树

优势

二叉搜索相比其他数据结构在查找和插入的复杂度较低. 均为 O(logN).

它是基础的数据结构,可用于构建更抽象的数据结构,如集合,映射等.

常用操作

0. 定义:

用一个根节点表示一个二叉搜索树

节点的结构如下所示:

template<typename Key,typename Value>
class BST {
private:
	struct Node {
		Key key;
		Value value;
		Node *left;
		Node *right;

		Node(key key, Value value) {
			this->key = key;
			this->value = value;
			this->left = this->right = NULL;
		}
	};
	Node *root;
	int count;
public:
	BST() {
		root = NULL;
		count = 0;
	}
	~BST() {
		// TODO:
	}
}

1. 查找

在二叉搜索树 root 中查找 key 是否存在

bool  contains(Node* node, Key key) {
    if (node == NULL)
        return NULL;

    if (node->key > key) {
        return contains(node->left, key);
    }
    else if (node->key < key) {
        return contains(node->right, key);
    }
    else {
        return true;
    }
}

2.插入

插入和查找是一样的

// 将(key,value)插入二叉搜索树中,返回根节点
Node* insert(Key key,Value value) {
    root = insert(root, key,value);
    return root;
}
Node* insert(Node *node, Key key, Value value) {
    if (node == NULL) {
        count++;
        root = new Node(key, value);
    } else {
        if (key == node->key) {
            node->value = value;
        }
        else if (key > node->key) {
            node->right = insert(node->right,key,value);
        } 
        else{
            // key < node->key
            node->left = insert(node->left, key, value);
        }
    }
    return node;
}

3. 删除

删除分为3种情况:

  • 只有左孩子,则将左孩子返回
  • 只有右孩子,则将右孩子返回
  • 左右孩子都有,找到这个节点的后继节点,再删除右子树中的最小节点.将后继节点的左孩子指向当前的左孩子.然后返回后继节点.
// 将关键字为key的节点,返回根节点
Node* delete(Key key) 		{
    root = delete(root, key);
}
// 
Node* delete(Node* node, Key key) {
    if (node == NULL) {
        return NULL;
    }
    if (node->key < key) {
        // 在左子树中删除,返回根节点的左孩子
        node->left = delete(node->left, key);
        return node;
    }
    else if (node->key > key) {
        // 在右子树中删除,返回根节点的右孩子
        node->right = delete(node->right, key);
        return node;
    }
    else {// 找到了该节点
        // 若左孩子为空,那么则返回其右孩子
        if (node->left == NULL) {
            Node* rightNode = node->right;
            node->right = NULL;
            size--;
            return rightNode;
        }
        // 若右孩子为空,那么则返回其左孩子
        else if (node->right == NULL) {
            Node* leftNode = node->left;
            node->left = NULL;
            size--;
            return leftNode;
        }
        else {
            // 如果二者都不为空,在右子树找最小值结点,即后继节点
            Node* successor = minimum(node->right);
            // 将这个最小值结点删除
            successor->right = deleteMin(node->right);
            // 将原来节点的左子树付给它
            successor->left = node->left;
            // 删除Node
            node->left = node->right = NULL;
            // 返回这个节点
            return successor;
        }
    }
}
// 递归找最小值节点
Node* minimum(Node* node) {
    if (node->left == NULL){
        return node;
    }
    return minimum(node->left);
}
// 递归找最大值节点
Node* Maximum(Node* node) {
    if (node->right == NULL) {
        return node;
    }
    return Maximum(node->right);
}
Node* deleteMin(Node* node) {
    if (node->left == NULL) {
        Node* rightNode = node->right;
        node->right = NULL;
        size--;
        return rightNode;
    }
    node->left = deleteMin(node->left);
    return node;
}
Node* deleteMax(Node* node) {
    if (node->right == NULL) {
        Node* leftNode = node->left;
        node->left = NULL;
        size--;
        return leftNode;
    }
    node->right = deleteMin(node->right);
    return node;
}

4.遍历

中序遍历有序

参考文献

二叉搜索树详解与实现

猜你喜欢

转载自blog.csdn.net/qjh5606/article/details/85240382