算法导论第12章:二叉搜索树

基本性质

左子树 < 根 < 右子树

基本操作 O(logn)

1.查找最大、最小关键字元素

根据二叉树的基本性质,向左子树或右子树递归即可

2.查找前驱和后继

查找结点X的后继Y分为两种情况:

①右结点存在,即只需要找到右子树中最小的元素就好了

②右结点不存在,此时就要向亲代查找,直到找到右上方的亲代,此时Y是X的最底层祖先,且Y的左孩子是X的一个祖先。

3.插入

迭代算法:类似于一根小棒在树中移动,最终把待插入元素放置在一个空结点上

4.删除

假设要删除结点Z,那么需要分3种情况讨论:

①若没有孩子,直接删除即可,以空结点NULL代替之。

②若只有一个孩子,以孩子代替结点Z

③若有两个孩子

a)若右孩子为其后继:将右子树代替结点Z即可

扫描二维码关注公众号,回复: 9055670 查看本文章

b)若右孩子不是其后继:设Z的后继为Y,Y的右孩子为X,则将Y原来的位置以X代替,Y将Z代替

利用二叉树进行排序 Ω(n*logn)

不断地插入节点,最后中序遍历即可——元素之间的比较和快速排序相同,故它们的运行效率相似。若采用随机化策略,则平均运行时间为θ(n*logn),树高为θ(logn)

二叉搜索树类的实现(C++)

#include <iostream>
using namespace std;

#pragma once
//设想是:当树为空时,root一定为nullptr 
struct node
{
    int element = 0;
    node* parent = nullptr;
    node* left = nullptr;
    node* right = nullptr;
};

class BinarySearchTree
{
public:
    BinarySearchTree() {}
    ~BinarySearchTree();
    int size();
    int maximum();
    int minimum();
    void print();
    void clear();
    void insert(const int&);
    void remove(const int&);
private:
    int cnt = 0;
    node* root = nullptr;

    node* minimum(node* x);
    void transplant(node* u, node* v);
    void clear(node*);
    void print(node*);
};

void BinarySearchTree::clear(node* x)
{
    if(x == nullptr) return;

    if(x->left != nullptr) clear(x->left);
    if(x->right != nullptr) clear(x->right);
    delete x;
    x = nullptr;
}

void BinarySearchTree::clear()
{
    cnt = 0;	
    clear(root);
}

BinarySearchTree::~BinarySearchTree()
{
    clear(root);
}

int BinarySearchTree::maximum()
{
    node* x = root;
    if(x == nullptr) return 0;
    while(x->right != nullptr)
        x = x->right;
    return x->element;
}

node* BinarySearchTree::minimum(node* x)
{
    if(x == nullptr) return 0;
    while(x->left != nullptr)
        x = x->left;
    return x;
}

int BinarySearchTree::minimum()
{
    return minimum(root)->element;
}

int BinarySearchTree::size()
{
    return cnt;
}

void BinarySearchTree::print(node* x)
{
    if(x == nullptr) return;
    if(x->left != nullptr) print(x->left);
    cout << x->element << ' ';
    if(x->right != nullptr) print(x->right);
}

void BinarySearchTree::print()
{
    print(root);
    cout<<'\n';
}

void BinarySearchTree::insert(const int& a)
{
    if(cnt == 0)
    {
        root = new node;
        root->element = a;
    }
    else
    {
        node* x = root;
        node* y = nullptr;
        while(x != nullptr)
        {
            y = x;
            if(a > x->element) x = x->right;
            else x = x->left;
        }

        node* t = new node;
        t->parent = y;
        t->element = a;
        if(a > y->element) y->right = t;
        else y->left = t;
    }
    ++cnt;
}

void BinarySearchTree::transplant(node* u, node* v)
{
    if(u->parent == nullptr) root = v;
    else if(u == u->parent->left) u->parent->left = v;
    else u->parent->right = v;

    if(v != nullptr) v->parent = u->parent;
}

void BinarySearchTree::remove(const int& a)
{
    node* x = root;
    while(x != nullptr && x->element != a)
    {
        if(a > x->element) x = x->right;
        else x = x->left;
    }
    if(x == nullptr) return;

    --cnt;
    if(x->left == nullptr)
        transplant(x, x->right);
    else if(x->right == nullptr)
        transplant(x, x->left);
    else
    {
        node* y = minimum(x->right);
        if(y->parent != x)
        {
            transplant(y, y->right);
            y->right = x->right;
            y->right->parent = y;
        }
        transplant(x, y);
        y->left = x->left;
        y->left->parent = y;
    }
}
发布了91 篇原创文章 · 获赞 142 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/leelitian3/article/details/83930785