二叉搜索樹

二叉搜索樹

二叉搜索樹:是一顆二叉樹但是其根節點的只要比左節點大比右節點小。

二叉樹的性質
二叉樹的順序存儲
這裏寫圖片描述
二叉樹的鏈式存儲

二叉樹的遍歷

給定一棵樹對其進行訪問
二叉樹
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

備註:以上資料整理自:數據結構(陳越、何欽銘)

發佈了49 篇原創文章 · 獲贊 22 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章