算法导论(5) 二叉搜索树

二叉搜索树

设x是二叉搜索树的一个结点,如果y是x左子树的一个结点,那么y.key≤x.key,如果y是x有字数的一个结点,那么y.key≥x.key。

二叉树有三种遍历的方法:
先序遍历:输出根的关键字在其左右子树的关键字之前。
中序遍历:输出根的关键字在其左右子树的关键字之间。
后序遍历:输出根的关键字在其左右子树的关键字之后。

主要的操作包括查找,遍历,最大最小关键字寻找,前驱后继结点查找,插入和删除。代码如下:

class Node
{
private:
    int key;//值
public:
    Node *left;//左子树
    Node *right;//右子树
    Node *parent;//父结点
    int getkey();
    void setkey(int k);
    Node(int k = 0);
    bool operator == (Node &z);
    Node& operator = (Node &z);

};
//二叉搜索树
class BSTree
{

public:
    Node *root;
    BSTree(){
        root = NULL;
    }
    void treeinsert(Node &root, Node &z);//插入结点
    Node treesearch(Node *root, int k);//查询结点
    void treewalk(Node *root);//遍历
    Node treemin(Node *root);//寻找结点root下最小值结点
    Node treemax(Node *root);//寻找结点root下最大值结点
    Node treesuccessor(Node *x);//寻找结点x的后继结点
    Node treeprodecessor(Node *x);//寻找结点x的前驱结点
    void treetransplant(Node &root, Node *u, Node *v);//在根结点root下移动子树v到u
    void treedelete(Node &root, Node *z);//删除结点
};
#include<iostream>
#include"BinarySearchTree.h"
using namespace std;

Node::Node(int k):key(k)
{
    left = NULL;
    right = NULL;
    parent = NULL;
}
bool Node::operator == (Node &z)
{
    if ((key == z.key)&&(left == z.left)&&(right == z.right)&&(parent == z.parent))
    {
        return true;
    }
    else{
        return false;
    }
}
Node& Node::operator = (Node &z)
{
    delete left;
    delete right;
    delete parent;
    left = z.left;
    right = z.right;
    parent = z.parent;
    key = z.key;
    z.left = NULL;
    z.right = NULL;
    z.parent = NULL;
    return *this;
}
int Node::getkey()
{
    return key;
}
void Node::setkey(int k)
{
    key = k;
}

//查询、最大值、最小值、前驱、后继函数均可以在O(h)时间内完成,h为树的高度
Node BSTree::treesearch(Node *root, int k)//查询结点
{
    //递归版本
    if (k == root->getkey())
    {
        return *root;
    }
    if (k < root->getkey())
    {
        return treesearch(root->left, k);
    }
    else
    {
        return treesearch(root->right, k);
    }
    return 0;


}


void BSTree::treewalk(Node *root)//中序遍历
{
    if (root != NULL)
    {
        treewalk(root->left);
        cout << root->getkey() << " ";
        treewalk(root->right);
    }

}
Node BSTree::treemin(Node *root)//寻找结点root下最小值结点
{
    //最左边最小
    Node *x;
    x = root;
    while (x->left != NULL)
    {
        x = x->left;
    }
    return *x;
}
Node BSTree::treemax(Node *root)//寻找结点root下最大值结点
{
    //最右边最大
    Node *x;
    x = root;
    if (x->right != NULL)
    {
    return treemax(x->right);
    }
    return *x;
}
Node BSTree::treesuccessor(Node *x)//寻找结点x的后继结点
{
    Node *y;
    //如果右孩子不空,则右子树中的最小值即为后继
    if (x->right != NULL){
        return treemin(x->right);
    }
    y = x->parent;
    //如果父结点也为空,无后继结点
    //父结点存在时,后继结点为它的最底层祖先,并且后继结点的左结点也是它的祖先
    //因此循环的终止条件为x == y->right,当x是一个左孩子时终止,x的父结点为后继结点
    while (y != NULL && x == y->right)
    {
        x = y;
        y = y->parent;
    }
    //y=NULL时,返回y会出错
    if (y != NULL)
    {
        return *y;
    }
    return 0;
}
Node BSTree::treeprodecessor(Node *x)//寻找结点x的前驱结点
{
    Node *y;
    //如果左孩子存在,前驱结点为左子树中最大值
    if (x->left != NULL){
        return treemax(x->left);
    }
    y = x->parent;
    //与后继结点类似,当x为右孩子时终止,x父结点为前驱结点
    while (y != NULL && x == y->left)
    {
        x = y;
        y = y->parent;
    }
    if (y != NULL)
    {
        return *y;
    }
    return 0;
}
void BSTree::treeinsert(Node &root, Node &z)//插入结点
{
    Node *x, *y = NULL;
    x = &root;
    //向下寻找位置
    while (x != NULL)
    {
        y = x;
        if (z.getkey() < x->getkey())
        {
            x = x->left;
        }
        else{
            x = x->right;
        }
    }
    z.parent = y;
    //判断树是否为空
    if (y == NULL)
    {
        root = z;
    }
    else if (z.getkey() < y->getkey())
    {
        y->left = &z;
    }
    else{
        y->right = &z;
    }

}

void BSTree::treetransplant(Node &root, Node *u, Node *v)//在根结点root下移动子树v到u
{
    //u为根结点
    if (u->parent == NULL)
    {
        root = *v;
    }
    else if (u == u->parent->left)
    {
        u->parent->left = v;
    }
    else{
        u->parent->right = v;
    }
    if (v != NULL)
    {
        v->parent = u->parent;
    }

}
void BSTree::treedelete(Node &root, Node *z)//删除结点
{
    Node *y=new Node;
    if (z->left == NULL){
        //如果左孩子为空,利用右孩子替换,右孩子为空时,相当于直接删除
        treetransplant(root, z, z->right);
    }
    else if (z->right == NULL){
        //执行此步时,一定只有左孩子,拿左孩子替换即可
        treetransplant(root, z, z->left);
    }
    else{
        //左右孩子都存在,首先需要寻找它的后继结点
         y= &treemin(z->right);

        if (!(*y == *z->right)){
            //如果后继结点不是它的右孩子,后继结点没有左孩子,否则不是后继结点
            //先拿后继结点右孩子替换后继结点,再拿后继结点替换要删除的结点
            treetransplant(root, y, y->right);
            //将z的右孩子换到y上,if外的语句把z的左孩子换到y上
            y->right = z->right;
            y->right->parent = y;
        }
        //如果后继结点就是它的右孩子,并且这个右孩子没有左孩子,否则不可能是后继结点,因此直接拿后继结点替换
        treetransplant(root, z, y);
        y->left = z->left;
        y->left->parent = y;

    }   
}

结构上,指针、引用的应用都比较乱,只做参考。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值