数据结构与算法(C++) 二叉查找树, 插入 查找 显示位置和数据 中序遍历

binary_search_tree.h

#ifndef __BINART_SEARCH_H
#define __BINARY_SEARCH_H

#include <iostream>

template<class T>
class Node;
template<class T>
class BST;

enum Boolean { FALSE, TRUE };

template<class T>
class Element // 存在的意义是 可以添加更多的数据
{
public:
    Element() { }
    Element(T k) { key = k; } 
    T key;
    // 
};
template<class T>
class Node
{
    // friend class BST<T>;
public:
    Node()
    : llink(0), rlink(0) { }
    void display(const int i); // // 显示位置 和 key, 显示当前节点数据,包括左右子节点的数据,递归
// private:
    Element<T> data;
    Node<T>* llink;
    Node<T>* rlink;
};
template<class T>
class BST
{
public:
    BST(Node<T>* rt = 0)
    : root(rt) { }
    Boolean Insert(const Element<T>& ); 
    Node<T>* Search(const Element<T>& );
    Node<T>* Search(Node<T>* , const Element<T>& ); // 递归查找
    Node<T>* IterSearch(const Element<T>& );  // 迭代查找
    void InOrder() const;
    void InOrder(const Node<T>* n) const;
    void display() { if(root) root->display(1); };
private:
    Node<T>* root;
};

//------------------Ndde-------------------
template<class T> // 位置 和 key
void Node<T>::display(const int i) // // 显示当前节点数据,包括左右子节点的数据, 递归
{
    std::cout << "position: " << i << "  element: " << data.key << std::endl; // 显示当前节点数据
    if(llink) llink->display(2 * i);     // 存在左节点, 显示左节点数据  *******必须是llink-> ********
    if(rlink) rlink->display(2 * i + 1); // 存在右节点, 显示右节点数据  *******必须是rlink-> ********
}

//-----------------------------------------

//------------------BST--------------------
template<class T>
Boolean BST<T>::Insert(const Element<T>& elmt)
{
    // 1.如果是一个空树
    if(!root) 
    {
        root = new Node<T>;
        root->data.key = elmt.key;
        return TRUE;
    }

    // 2.如果树已经有节点
    // 2.1 查找应该插入的位置
    Node<T>* crtNode = root; // 每次都从root节点开始查找
    Node<T>* p =0 ;          // 暂存上一个节点指针
    while(crtNode) // 一直到最后一层  
    {
        if(crtNode->data.key == elmt.key) return FALSE; // 不能存在相同数据的节点
        p = crtNode; // 暂存父节点
        if(elmt.key < crtNode->data.key) // 左子节点
            crtNode = crtNode->llink;    // 更新当前位置
        else                             // 右子节点
            crtNode = crtNode->rlink;    // 更新当前位置
    }
    // 2.2 查找到位置p, 插入新节点
    if(elmt.key < p->data.key)  // 插入左边, *******再次判断父节点, 准备插入新节点********
    {
        p->llink = new Node<T>; // 新节点连接到 父节点的llink
        p->llink->data.key = elmt.key; // *******给 新节点赋值*******
    }
    else                        // 插入到右边
    {
        p->rlink = new Node<T>; // 新节点连接到 父节点的llink
        p->rlink->data.key = elmt.key; // *******给 新节点赋值*******
    }
}
template<class T>
Node<T>* BST<T>::Search(const Element<T>& elmt)
{
    return Search(root, elmt);
}
template<class T>
Node<T>* BST<T>::Search(Node<T>* crtNode, const Element<T>& elmt) // 递归查找
{
    if(elmt.key == crtNode->data.key) return crtNode; // 找到就返回节点指针

    if(elmt.key < crtNode->data.key) Search(crtNode->llink, elmt); // 找左边
    else Search(crtNode->rlink, elmt);                             // 找右边
}
template<class T>
Node<T>* BST<T>::IterSearch(const Element<T>& elmt)
{
    Node<T>* crtNode = root;
    while(crtNode) // 一直找到最后
    {
        if(elmt.key == crtNode->data.key) return crtNode; // 找到就返回节点指针
        if(elmt.key < crtNode->data.key) crtNode = crtNode->llink;// 找左边
        else crtNode = crtNode->rlink;                            // 找右边
    }
}
template<class T>
void BST<T>::InOrder() const
{
    InOrder(root);
}
template<class T>
void BST<T>::InOrder(const Node<T>* n) const // 中序遍历
{
    if(n)
    {
        InOrder(n->llink);
        std::cout << n->data.key << " ";
        InOrder(n->rlink);
    }
}
//-----------------------------------------

#endif

main.cpp中的二叉查找树的例子
在这里插入图片描述
main.cpp

#include <iostream>
#include "binary_search_tree.h"
using namespace std;
/*
二叉查找树(BST, binary search tree)
性质:
    1.每个元素都有一个键值, 而且不允许重复
    2.左子树的键值 都小于 跟节点的键值
    3.右子树的键值 都大于 跟节点的键值
    4.左右子树都是二叉查找树
当插入的数据是由大到小, 那么二叉查找树变成了链表, 无法实现快速的二分查找
如果存在一种自动平衡分支的树,那么就很完美了--->红黑树
*/
/*
        5
      4   6
    2
      3
*/
int main()
{
    // ----测试display(), 显示节点和子节点的位置 和 key----
    Node<int> a;
    Node<int> b;
    Node<int> c;
    Node<int> d;
    Node<int> e;

    a.data.key = 5;
    b.data.key = 4;
    c.data.key = 2;
    d.data.key = 6;
    e.data.key = 3;
    
    a.llink = &b;
    a.rlink = &d;
    b.llink = &c;
    c.rlink = &e;

    a.display(1); 
    //-------------------------------------------------

    cout << "----------------------------\n";
    Element<int> aa{5};
    Element<int> bb{4};
    Element<int> cc{2};
    Element<int> dd{6};
    Element<int> ee{3};

    BST<int> bst;
    bst.Insert(aa);
    bst.Insert(bb);
    bst.Insert(cc);
    bst.Insert(dd);
    bst.Insert(ee);
    bst.display();

    cout << "\nrecursion result: " << bst.Search(dd)->data.key << endl;
    cout << "\n iterator result: " << bst.IterSearch(cc)->data.key << endl;

    cout << "   inOrder: ";  bst.InOrder();  cout << endl;

// output:
// position: 1  element: 5
// position: 2  element: 4
// position: 4  element: 2
// position: 9  element: 3
// position: 3  element: 6
// ----------------------------
// position: 1  element: 5
// position: 2  element: 4
// position: 4  element: 2
// position: 9  element: 3
// position: 3  element: 6

// recursion result: 6

//  iterator result: 2
//    inOrder: 2 3 4 5 6 

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值