数据结构——二叉查找树的详细实现(c++)

github地址:https://github.com/lining91/BinTree

本文实现了二叉查找树的前序遍历(递归与非递归)、中序遍历(递归与非递归)、后序遍历(递归与非递归)、插入过程、删除过程、查找过程等。

二叉树的简单介绍:
1、二叉树中的每个节点都不能有多余两个的儿子。
2、二叉树的深度要比N小得多。

假设每个节点被指定一个关键字值(所有关键字是整数、互异的)。

二叉查找树的性质:
1、左子树的所有节点值均小于根节点值。
2、右子树的所有节点值均大于根节点值。
3、左右子树都满足上述两个条件。

插入过程:
1、若当前二叉树为空,则插入的元素为根节点。
2、若插入的元素值小于根节点值,则递归从根节点的左子树中找到可插入位置。
3、若插入的元素值大于根节点值,则递归从根节点的右子树中找到可插入位置。

删除过程:
1、待删除节点Z为叶子节点,则直接删除该节点。修改父节点的指针。
2、待删除节点Z为单支节点(只有左子树或者右子树),让Z的子树与Z的父节点相连,删除节点Z。
3、待删除节点Z左右子树都不为空。
方法一:找到Z的后继节点y,因为y一定没有左子树,所以可以直接删除y,并让y的父亲节点成为y的右子树的父亲节点。用y替换Z。
方法二:找到Z的前驱节点x,x一定没有右子树,所以可以直接删除x,并让x的父亲节点成为x的左子树的父亲节点。用x替换Z。

查找过程:
1、若待查找的元素值和根节点相同,则返回根节点。
2、若待查找的元素值小于根节点的元素值,则递归从根节点的左子树中查找。
3、若待查找的元素值大于根节点的元素值,则递归从根节点的右子树中查找。

遍历过程:
1、前序遍历(递归和非递归两种):先根节点,后左孩子节点,再右孩子结点。
2、中序遍历(递归和非递归两种):先左孩子结点,后根节点,再右孩子结点。
3、后序遍历(递归和非递归两种):先做孩子节点,后右孩子结点,再根节点。

获取最大元素的节点:
1、如果根节点无右子树,则返回根节点。
2、依次查询根节点的右子树节点,返回右子树的最后一个右节点。

获取最小元素的节点:
1、如果根节点无左子树,则返回根节点。
2、依次查询跟节点的左子树节点,返回左子树的最后一个左节点。

依次插入数据(15,3,20,8,10,18,6,1,26)之后的二叉树结构如下:
《数据结构——二叉查找树的详细实现(c++)》

代码如下:

#include <iostream>
#include <stack>
using namespace std;

typedef struct STreeNode* pSTreeNode;
typedef int TreeKeyType;

struct STreeNode 
{
    TreeKeyType key;
    pSTreeNode pLeftChild;
    pSTreeNode pRightChild;

    STreeNode( TreeKeyType Value )
    {
        key = Value;
        pLeftChild = NULL;
        pRightChild = NULL;
    }
};

class CBinTree
{
public:
    CBinTree();
    ~CBinTree();

    void Insert( TreeKeyType Value );
    void Insert( pSTreeNode pNode, TreeKeyType Value );

    pSTreeNode Search( TreeKeyType Value );
    pSTreeNode Search( pSTreeNode pNode, TreeKeyType Value );

    void Delete( TreeKeyType Value );

    void Preorder( );       // 前序遍历,非递归方法(借用堆栈)
    void Inorder( );        // 中序遍历,非递归方法(借用堆栈)
    void Postorder( );      // 后序遍历,非递归方法(借用堆栈)

    void PreorderRecursively( pSTreeNode pNode );   // 前序遍历,递归调用
    void InorderRecursively( pSTreeNode pNode );    // 中序遍历,递归调用
    void PostorderRecursively( pSTreeNode pNode );  // 后序遍历,递归调用

    pSTreeNode GetMaxKey();     // 获得二叉查找树中元素值最大的节点
    pSTreeNode GetMinKey();     // 获得二叉查找树中元素值最小的节点

    void FreeMemory( pSTreeNode pNode );    // 释放内存
public:
    pSTreeNode pRoot;
};

CBinTree::CBinTree()
{
    pRoot = NULL;
}

CBinTree::~CBinTree()
{
    if ( pRoot == NULL )
        return;

    FreeMemory( pRoot );
}

void CBinTree::FreeMemory( pSTreeNode pNode )
{
    if ( pNode == NULL )
        return;

    if ( pNode->pLeftChild != NULL )
        FreeMemory( pNode->pLeftChild );

    if ( pNode->pRightChild != NULL )
        FreeMemory( pNode->pRightChild );

    delete pNode;
    pNode = NULL;
}

void CBinTree::Insert( TreeKeyType Value )
{
    if ( pRoot == NULL )
        pRoot = new STreeNode( Value );
    else
        Insert( pRoot, Value );
}

void CBinTree::Insert( pSTreeNode pNode, TreeKeyType Value )
{
    if ( pNode->key > Value )
    {
        if ( pNode->pLeftChild == NULL)
            pNode->pLeftChild = new STreeNode( Value );
        else
            Insert( pNode->pLeftChild, Value );
    }
    else
    {
        if ( pNode->pRightChild == NULL)
            pNode->pRightChild = new STreeNode( Value );
        else
            Insert( pNode->pRightChild, Value );
    }
}

pSTreeNode CBinTree::Search( TreeKeyType Value )
{
    return Search( pRoot, Value );
}

pSTreeNode CBinTree::Search( pSTreeNode pNode, TreeKeyType Value )
{
    if ( pNode == NULL )
        return NULL;

    if ( pNode->key == Value )
        return pNode;
    else
    {
        if ( pNode->key > Value )
            return Search( pNode->pLeftChild, Value );
        else
            return Search( pNode->pRightChild, Value );
    }
}

void CBinTree::Delete( TreeKeyType Value )
{
    pSTreeNode pParentNode = pRoot;
    pSTreeNode pFindNode = pRoot;
    // 找到Value元素对应的节点
    while ( pFindNode != NULL )
    {
        if ( pFindNode->key == Value )
            break;

        pParentNode = pFindNode;
        if ( pFindNode->key > Value )
            pFindNode = pFindNode->pLeftChild;
        else
            pFindNode = pFindNode->pRightChild;
    }

    if ( pFindNode == NULL )
        return;


    // 处理Value元素的父节点和Value元素的节点
    if ( pFindNode->pLeftChild == NULL || pFindNode->pRightChild == NULL )
    {
        // 一个子结点为空或者两个子结点都为空
        pSTreeNode pTemp = NULL;
        if ( pFindNode->pLeftChild != NULL)
            pTemp = pFindNode->pLeftChild;
        else if ( pFindNode->pRightChild != NULL )
            pTemp = pFindNode->pRightChild;

        if ( pParentNode->pLeftChild == pFindNode )
            pParentNode->pLeftChild = pTemp;
        else
            pParentNode->pRightChild = pTemp;

        delete pFindNode;
        pFindNode = NULL;
    }
    else
    {
        // 找到前驱节点
        pSTreeNode pTemp = pFindNode->pLeftChild;
        pSTreeNode pTempParent = pFindNode;

        while ( pTemp->pRightChild != NULL )
        {
            pTempParent = pTemp;
            pTemp = pTemp->pRightChild; 
        }

        pFindNode->key = pTemp->key;
        pTempParent->pRightChild = NULL;
        delete pTemp;
        pTemp = NULL;
    }
}

void CBinTree::Preorder(  )
{
    if ( pRoot == NULL )
    {
        cout << "二叉树为空!" << endl;
        return;
    }

    stack<pSTreeNode> StackTree;
    pSTreeNode pNode = pRoot;
    while( pNode != NULL || !StackTree.empty())
    {
        while ( pNode != NULL )
        {
            cout << " " << pNode->key << " ";
            StackTree.push(pNode);
            pNode = pNode->pLeftChild;
        }

        pNode = StackTree.top();
        StackTree.pop();
        pNode = pNode->pRightChild;
    }

}

void CBinTree::Inorder( )
{
    if ( pRoot == NULL )
    {
        cout << "二叉树为空!" << endl;
        return;
    }

    stack<pSTreeNode> StackTree;
    pSTreeNode pNode = pRoot;
    while ( pNode != NULL || !StackTree.empty() )
    {
        while ( pNode != NULL )
        {
            StackTree.push( pNode );
            pNode = pNode->pLeftChild;
        }

        pNode = StackTree.top();
        StackTree.pop();
        cout << " " << pNode->key << " ";
        pNode = pNode->pRightChild;
    }
}


// 借助变量visited表示是否访问过该根节点。访问过的话,这输出。
void CBinTree::Postorder( )
{
    if ( pRoot == NULL )
    {
        cout << "二叉树为空!" << endl;
        return;
    }

    stack< pair<pSTreeNode, bool>> StackTree;
    StackTree.push( make_pair( pRoot, false ));

    while ( !StackTree.empty() )
    {
        pSTreeNode pNode = StackTree.top().first;
        bool bVisited = StackTree.top().second;


        if (pNode == NULL)
        {
            StackTree.pop();
            continue;
        }

        if (bVisited)
        {
            cout << " " << pNode->key << " ";
            StackTree.pop();
        }
        else
        {
            StackTree.top().second = true;
            StackTree.push( make_pair( pNode->pRightChild, false));
            StackTree.push( make_pair( pNode->pLeftChild, false));
        }
    }
}

void CBinTree::PreorderRecursively( pSTreeNode pNode )
{
    if (pNode == NULL)
        return;

    cout << " " << pNode->key << " ";
    PreorderRecursively( pNode->pLeftChild );
    PreorderRecursively( pNode->pRightChild );
}

void CBinTree::InorderRecursively( pSTreeNode pNode )
{
    if (pNode == NULL)
        return;

    InorderRecursively( pNode->pLeftChild );
    cout << " " << pNode->key << " ";
    InorderRecursively( pNode->pRightChild );
}

void CBinTree::PostorderRecursively( pSTreeNode pNode )
{
    if (pNode == NULL)
        return;

    PostorderRecursively( pNode->pLeftChild );
    PostorderRecursively( pNode->pRightChild );
    cout << " " << pNode->key << " ";
}

int main()
{
    CBinTree* pBinTree = new CBinTree();
    if ( pBinTree == NULL )
        return 0;

    pBinTree->Insert( 15 );
    pBinTree->Insert( 3 );
    pBinTree->Insert( 20 );
    pBinTree->Insert( 8 );
    pBinTree->Insert( 10 );
    pBinTree->Insert( 18);
    pBinTree->Insert( 6 );
    pBinTree->Insert( 1);
    pBinTree->Insert( 26);

    pSTreeNode pRoot = pBinTree->pRoot;

    cout << " 非递归前序遍历 :" ;
    pBinTree->Preorder();
    cout << endl;

    cout << " 递归前序遍历 :" ;
    pBinTree->PreorderRecursively( pRoot );
    cout << endl;

    cout << " 非递归中序遍历 :" ;
    pBinTree->Inorder();
    cout << endl;

    cout << " 递归中序遍历 :" ;
    pBinTree->InorderRecursively( pRoot );
    cout << endl;

    cout << " 非递归后序遍历 :" ;
    pBinTree->Postorder();
    cout << endl;

    cout << " 递归后续遍历 :";
    pBinTree->PostorderRecursively( pRoot );
    cout << endl;

    pSTreeNode pMaxNode = pBinTree->GetMaxKey();
    pSTreeNode pMinNode = pBinTree->GetMinKey();
    if ( pMaxNode != NULL )
        cout << " 该二叉查找树的最大元素是:" << pMaxNode->key << endl;

    if (pMinNode != NULL )
        cout << " 该二叉查找树的最小元素是:" << pMinNode->key << endl;

    TreeKeyType DeleteKey = 15;
    pSTreeNode pSearchNode = pBinTree->Search( DeleteKey );
    if ( pSearchNode != NULL )
        cout << " 需要查询的元素是:" << DeleteKey << ", 实际查询到的元素是:" << pSearchNode->key << endl;
    else
        cout << " 没有查询到元素" << DeleteKey << endl;
    pBinTree->Delete( DeleteKey );
    cout << " 删除元素" << DeleteKey << "之后的递归前序遍历:";
    pBinTree->PreorderRecursively( pRoot );
    cout << endl;

    DeleteKey = 1;
    pBinTree->Delete( DeleteKey );
    cout << " 删除元素" << DeleteKey << "之后的递归前序遍历:";
    pBinTree->PreorderRecursively( pRoot );
    cout << endl;

    DeleteKey = 8;
    pBinTree->Delete( DeleteKey );
    cout << " 删除元素" << DeleteKey << "之后的递归前序遍历:";
    pBinTree->PreorderRecursively( pRoot );
    cout << endl;

    DeleteKey = 26;
    pBinTree->Delete( DeleteKey );
    cout << " 删除元素" << DeleteKey << "之后的递归前序遍历:";
    pBinTree->PreorderRecursively( pRoot );
    cout << endl;

    delete pBinTree;
    pBinTree = NULL;
    system( "pause" );
    return 1;
}

运行结果如下:
《数据结构——二叉查找树的详细实现(c++)》

    原文作者:二叉查找树
    原文地址: https://blog.csdn.net/lining0420/article/details/76167901
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞