二叉搜索树

二叉搜索树

二叉搜索树:是一颗二叉树但是其根节点的只要比左节点大比右节点小。

二叉树的性质
二叉树的顺序存储
这里写图片描述
二叉树的链式存储

二叉树的遍历

给定一棵树对其进行访问
二叉树
1.先序遍历
(1). 访问根节点
(2). 先序遍历其左子树
(3).先序遍历其右子树
其上图二叉树先序遍历的结果为:ABDFECGHI
其代码实现为:

void preOrderTraver(BinTree root) 
{
    if (!root) {
        //visit(root);
        cout << root->data << endl;
        preOrderTraver(root->left);
        preOrderTraver(root->right);
    }
}

上述代码为递归实现,但是我们可以非递归实现:
因为二叉树的先序遍历,总是先访问其根节点然后在遍历其左子树,最后才是右子树,因此我们可以创建一个堆栈来模拟这个过程。

//先序遍历
void preOrderTraver(BinTree root)
{
    std::stack<BinTree*> st;   //创建一个堆栈用来存储二叉树的节点
    BinTree node = root;
    while(node || !st.empty()) {
        while(node) {
            std::cout << node->data << " ";  //访问其根节点
            st.push(node); //把左子树压入堆栈
            node = node->left; //一直遍历其左子树直到为空
        }
        if(!st.empty()) {
            node = st.top();
            st.pop();
            node = node->right;//遍历其右子树
        }
    }
    std::cout << std::endl;
}

2.中序遍历
(1). 先序遍历其左子树
(2). 访问根节点
(3).先序遍历其右子树
其上图二叉树先序遍历的结果为:DBEFAGHCI
其递归代码为:

//中序遍历
void inOrderTraver(BinTree root)
{
    if (!root) {
        inOrderTraver(root->left);
        std::cout << root->data << " "; //visit(root->data);
        inOrderTraver(root->right);
    }
}

非递归实现为

void inOrderTraver(BinTree root)
{
    std::stack<BinTree> st;
    auto node = root;
    while(node || !st.empty()) {
        while(node) {
            st.push(node);
            node=node->left;
        }
        if(!st.empty()) {
            node =st.top();
            st.pop();
            std::cout << node->data << " ";
            node = node->right;
        }
    }
    std::cout << std::endl;
}

3.后序遍历
(1). 先序遍历其左子树
(2).先序遍历其右子树
(3). 访问根节点

void postOrderTraver(BinTree root) 
{
    if (!root) {
        postOrderTraver(root->left);
        postOrderTraver(root->right);
        cout << root->data << " ";  //visit(root);
    }
}

非递归实现
我们知道先序遍历的顺序为 root->left->right; 而后续遍历的顺序为left->right->root; 如果将先序遍历修改一下成root->right->left,那么就成了后序遍历的逆结果。

4.层次遍历

层次遍历
这里写图片描述

//层次遍历
void levelOrderTraver(BinTree root) {
    std::queue<BinTree> qu;
    auto node = root;
    if(!root)
        return ;
    qu.push(root);
    while(!qu.empty()) {
        node = qu.front();
        qu.pop();
        std::cout << node->data << " ";
        if(node->left) qu.push(node->left);
        if(node->right) qu.push(node->right);
    }
    std::cout << std::endl;
}

二叉树的操作

1.二叉树的插入操作
将元素插入到二叉树中,首先我我们需要找到二叉树的插入位置,然后在进行插入操作.

TreeNode* insert(TreeNode *root, int data) 
{
    if (!root) {
        root = new TreeNode();
        root->data = data;
        root->left = nullptr;
        root->right = nullptr;
        return root;
    } else if (data < root->data)
        root->left = insert(root->left);
    else 
        root->right = insert(root->right);
    return root;
}

其非递归实现为:

void insert(TreeNode *root, const int data)
{
    if(root==nullptr) {
        root = new TreeNode();
        root->data = data;
        root->left = nullptr;
        root->right = nullptr;
        return ;
    }
    TreeNode *node = new treeNode();
    node->data = data;
    node->left = nullptr;
    node->right = nullptr;

    treeNode *curr = root;
    treeNode *parent;
    while(curr) {
        parent = curr;
        curr = data > curr->data ? curr->right : curr->left;
    }
    if(data > parent->data)
        parent->right = node;
    else
        parent->left = node;
}

2.删除二叉树中的元素
叶节点
只有一个孩子
存在左右孩子

//删除数据
bstree::treeNode * bstree::_delete(treeNode * tree, int data)
{
    if(!tree)
        return tree;
    if(data > tree->data)
        tree->right = _delete(tree->right, data);
    else if(data < tree->data)
        tree->left = _delete(tree->left, data);
    else if ( data == tree->data){
        if(tree->left && tree->right) {  //如果左右儿子都存在
            //从右子树上找一个最小的节点填充该节点
            auto node = findMin(tree->right);
            tree->data = node->data;
            //从右子树上删除最小的节点
            tree->right = _delete(tree->right, tree->data);
        } else  {   //只存在一个儿子或者没有
            auto node = tree;
            if(tree->right)
                tree = tree->right;
            else
                tree = tree->left;
            delete node;
        }
    }
    return tree;
}

其上述完整代码为:

#ifndef _BS_TREE_H
#define _BS_TREE_H

#include<iostream>
#include<stack>
#include<queue>

using std::ostream ;

class bstree {
private:
    //定义二叉树的存储结构
    struct treeNode {
        treeNode *left;
        treeNode *right;
        int data;
    };

    treeNode *root;     //定义根节点

public :
    bstree() :
        root(nullptr) {}

    //插入数据
    void insert(int data);

    //删除数据
    void deleteData(int data) {
        _delete(root, data);
    }

    int getHeight() const {
        return _getHeight(root);
    }

    int findMin() {
        if(!root)  {
            std::cerr << "invalid operation: empty tree" << std::endl;
            return -1;
        }
        return findMin(root)->data;
    }

    int findMax() {
        if(!root) {
            std::cerr << "invalid operation: empty tree" << std::endl;
            return -1;
        }
        return findMax(root)->data;
    }

    /*
    *二叉树的遍历
    **/
    void preOrderTraver();
    void inOrderTraver();
    void postOrderTraver() {
        _postOrderTraver(root);
    }
    void levelOrderTraver();

private:
    void _postOrderTraver(const treeNode *tree);
    int _getHeight(const treeNode *tree) const;

    treeNode * _delete(treeNode *tree, int data);

    treeNode * findMin(treeNode *tree);
    treeNode * findMax(treeNode *tree);

};

/*
*插入数据函数
**/
void bstree::insert(const int data)
{
    if(root==nullptr) {
        //root = new treeNode(data);
        root = new treeNode();
        root->data = data;
        root->left = nullptr;
        root->right = nullptr;
        return ;
    }

    //treeNode *node = new treeNode(data);
    treeNode *node = new treeNode();
    node->data = data;
    node->left = nullptr;
    node->right = nullptr;

    treeNode *curr = root;
    treeNode *parent;
    while(curr) {
        parent = curr;
        curr = data > curr->data ? curr->right : curr->left;
    }
    if(data > parent->data)
        parent->right = node;
    else
        parent->left = node;
}

//删除数据
bstree::treeNode * bstree::_delete(treeNode * tree, int data)
{
    if(!tree)
        return tree;
    if(data > tree->data)
        tree->right = _delete(tree->right, data);
    else if(data < tree->data)
        tree->left = _delete(tree->left, data);
    else if ( data == tree->data){
        if(tree->left && tree->right) {  //如果左右儿子都存在
            //从右子树上找一个最小的节点填充该节点
            auto node = findMin(tree->right);
            tree->data = node->data;
            //从右子树上删除最小的节点
            tree->right = _delete(tree->right, tree->data);
        } else  {   //只存在一个儿子或者没有
            auto node = tree;
            if(tree->right)
                tree = tree->right;
            else
                tree = tree->left;
            delete node;
        }
    }
    return tree;
}

bstree::treeNode * bstree::findMin(treeNode *tree)
{
    if(!tree)
        return tree;
    auto node = tree;
    while (node->left)
        node=node->left;
    return node;
}

bstree::treeNode * bstree::findMax(treeNode *tree)
{
    if(!tree)
        return tree;
    auto node=tree;
    while (node->right)
        node=node->right;
    return node;
}

//获取二叉树的高度
int bstree::_getHeight(const treeNode * tree) const
{
    if(!tree)
        return 0;
    else
        return 1 + std::max(_getHeight(tree->left), _getHeight(tree->right));
}

/*
*二叉树的遍历操作
**/
//先序遍历
void bstree::preOrderTraver()
{
    std::stack<treeNode*> st;
    treeNode * node = root;

    while(node || !st.empty()) {
        while(node) {
            std::cout << node->data << " ";
            st.push(node);
            node = node->left;
        }

        if(!st.empty()) {
            node = st.top();
            st.pop();
            node = node->right;
        }
    }
    std::cout << std::endl;
}

//中序遍历
void bstree::inOrderTraver()
{
    std::stack<treeNode *> st;
    auto node = root;

    while(node || !st.empty()) {
        while(node) {
            st.push(node);
            node=node->left;
        }
        if(!st.empty()) {
            node =st.top();
            st.pop();
            std::cout << node->data << " ";
            node = node->right;
        }
    }
    std::cout << std::endl;
}


//后序遍历
void bstree::_postOrderTraver(const treeNode *tree)
{
    if(tree) {
        _postOrderTraver(tree->left);
        _postOrderTraver(tree->right);
        std::cout << tree->data << " ";
    }
}

//层次遍历
void bstree::levelOrderTraver() {
    std::queue<treeNode*> qu;
    auto node = root;

    if(!root)
        return ;
    qu.push(root);
    while(!qu.empty()) {
        node = qu.front();
        qu.pop();
        std::cout << node->data << " ";
        if(node->left) qu.push(node->left);
        if(node->right) qu.push(node->right);
    }
    std::cout << std::endl;
}

#endif // _BS_TREE_H

备注:以上资料整理自:数据结构(陈越、何钦铭)

  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值