书上有个例题看不懂啊,二叉树查找数据元素,C高手帮帮忙 O_O (菜鸟在线)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了书上有个例题看不懂啊,二叉树查找数据元素,C高手帮帮忙 O_O (菜鸟在线)相关的知识,希望对你有一定的参考价值。

二叉树查找数据元素:

BiTree Search(BiTree *bt,elemtype x)

BiTree p;
p=bt;

if(p->data==x) return p;
if(p->Lchild!=null)
return(Search(p->Lchild,x));......//这句
书上说在 p->Lchild为根结点指针的二叉树可查找数据
元素。 可是要是找不到,就return null;不会
执行下句的右子树里查找了?如果找的元素在右子树,
那就找不到了,到底是不是这样??

if(p->Rchild!=null))
return(Search(p->Rchild,x));
return null;


高手帮我分析一下,多谢了、

(是,如果有左子树 则查询左子树,如果没左子树,但是有右边子树则查询右子树木..2个都没有,则返回null)
但是一个查询程序应该不应该return ,因为return 的话 就会当左子树查询不到,则返回null,就不会在继续查询了

所以不用return 那么这个程序应该算中序遍历.
中(根) 左 右 这样的顺序就是中序遍历;

这样程序就变成..
1,设第一次进入这个函数 传入根节点 ,他先判断这个根节点是否 符合要求?符合 返回点:不符合 进入步骤2
2,当根节点不符合要求,判断其是否含有左孩子,如果有 传入左子树根节点(就是其左孩子).重新进入步骤1;如果上面 左孩子为空 进入步骤3
3,当根节点不符合要求 其左孩子不符合要求 则判断其右孩子,其右孩子如果不为空,传入右子树根节点(就是其右孩子).重新进入步骤1;如果上面右孩子为空,则进入步骤4
4,当以上的所有都不符合要求 意味,以此为根节点的子树找不到合适的数字,(但是不能否认所有子数都没有符合要求的结果)
参考技术A 恩。
简单来说:函数里一旦遇到return就返回,不再执行return下面的语句。

所以上面的函数中一旦执行到return(Search(p->Lchild,x));这句,函数就返回,下面右子树中的查找等语句就不执行了。

而执行这条return语句的条件就是上面的那个if成立:if(p->Lchild!=null) ,即左子树非空。

综合来看就是:
if当前结点(即函数中的第一个参数bt)的值为所查找的,就return当前结点。
if(左子树非空)就对左子树调用Search,并return函数Search的返回值。
if(右子树非空)就对右子树调用Search,并return函数Search的返回值。
return null;

任何一个if成立,函数都将返回,因为if后面接的都是return。
若三个if都不成立,就执行最后一条语句return null;

数据结构开发(23):二叉树中结点的查找插入删除与清除操作

0.目录

1.二叉树中结点的查找操作

2.二叉树中结点的插入操作

3.二叉树中结点的删除操作

4.二叉树中结点的清除操作

5.小结

1.二叉树中结点的查找操作

查找的方式:

  • 基于数据元素值的查找
    1. BTreeNode<T>* find(const T& value) const
  • 基于结点的查找
    1. BTreeNode<T>* find(TreeNode<T>* node) const

树中数据元素和结点的查找:
技术分享图片

基于数据元素值的查找:

  • 定义功能:find(node, value)
    1. node 为根结点的二叉树中查找 value 所在的结点

技术分享图片

在BTree.h中实现基于数据元素值的查找:

protected:
    virtual BTreeNode<T>* find(BTreeNode<T>* node, const T& value) const
    {
        BTreeNode<T>* ret = NULL;

        if( node != NULL )
        {
            if( node->value == value )
            {
                return node;
            }
            else
            {
                if( ret == NULL )
                {
                    ret = find(node->left, value);
                }

                if( ret == NULL )
                {
                    ret = find(node->right, value);
                }
            }
        }

        return ret;
    }
public:
    BTreeNode<T>* find(const T& value) const
    {
        return find(root(), value);
    }

基于结点的查找:

  • 定义功能:find(node, obj)
    1. node 为根结点的二叉树中查找是否存在 obj 结点

技术分享图片

在BTree.h中实现基于结点的查找:

protected:
    virtual BTreeNode<T>* find(BTreeNode<T>* node, BTreeNode<T>* obj) const
    {
        BTreeNode<T>* ret = NULL;

        if( node == obj )
        {
            return node;
        }
        else
        {
            if( node != NULL )
            {
                if( ret == NULL )
                {
                    ret = find(node->left, obj);
                }

                if( ret == NULL )
                {
                    ret = find(node->right, obj);
                }
            }
        }

        return ret;
    }
public:
    BTreeNode<T>* find(TreeNode<T>* node) const
    {
        return find(root(), dynamic_cast<BTreeNode<T>*>(node));
    }

2.二叉树中结点的插入操作

需要考虑的问题:

  • 是否能够在二叉树的任意结点处插入子结点?
  • 是否需要指定新数据元素 ( 新结点 ) 的插入位置?

二叉树结点的位置枚举类型:
技术分享图片

插入的方式

  • 插入新结点
    1. bool insert(TreeNode<T>* node)
    2. bool insert(TreeNode<T>* node, BTNodePos pos)
  • 插入数据元素
    1. bool insert(const T& value, TreeNode<T>* parent)
    2. bool insert(const T& value, TreeNode<T>* parent, BTNodePos pos)

新结点的插入:
技术分享图片

指定位置的结点插入:
技术分享图片

插入新结点:
技术分享图片

插入数据元素:
技术分享图片

在BTreeNode.h中实现BTNodePos枚举类型:

#ifndef BTREENODE_H
#define BTREENODE_H

#include "TreeNode.h"

namespace StLib
{

enum BTNodePos
{
    ANY,
    LEFT,
    RIGHT
};

template <typename T>
class BTreeNode : public TreeNode<T>
{
public:
    BTreeNode<T>* left;
    BTreeNode<T>* right;

    BTreeNode()
    {
        left = NULL;
        right = NULL;
    }

    static BTreeNode<T>* NewNode()
    {
        BTreeNode<T>* ret = new BTreeNode<T>();

        if( ret != NULL )
        {
            ret->m_flag = true;
        }

        return ret;
    }
};

}

#endif // BTREENODE_H

在BTree.h中实现结点的插入操作:

protected:
    virtual bool insert(BTreeNode<T>* n, BTreeNode<T>* np, BTNodePos pos)
    {
        bool ret = true;

        if( pos == ANY )
        {
            if( np->left == NULL )
            {
                np->left = n;
            }
            else if( np->right == NULL )
            {
                np->right = n;
            }
            else
            {
                ret = false;
            }
        }
        else if( pos == LEFT )
        {
            if( np->left == NULL )
            {
                np->left = n;
            }
            else
            {
                ret = false;
            }
        }
        else if( pos == RIGHT )
        {
            if( np->right == NULL )
            {
                np->right = n;
            }
            else
            {
                ret = false;
            }
        }
        else
        {
            ret = false;
        }

        return ret;
    }
public:
    bool insert(TreeNode<T>* node)
    {
        return insert(node, ANY);
    }

    virtual bool insert(TreeNode<T>* node, BTNodePos pos)
    {
        bool ret = true;

        if( node != NULL )
        {
            if( this->m_root == NULL )
            {
                node->parent = NULL;
                this->m_root = node;
            }
            else
            {
                BTreeNode<T>* np = find(node->parent);

                if( np != NULL )
                {
                    ret = insert(dynamic_cast<BTreeNode<T>*>(node), np, pos);
                }
                else
                {
                    THROW_EXCEPTION(InvalidParameterException, "Invalid parent tree node ...");
                }
            }
        }
        else
        {
            THROW_EXCEPTION(InvalidParameterException, "Parameter node can not be NULL ...");
        }

        return ret;
    }

    bool insert(const T& value, TreeNode<T>* parent)
    {
        return insert(value, parent, ANY);
    }

    virtual bool insert(const T& value, TreeNode<T>* parent, BTNodePos pos)
    {
        bool ret = true;
        BTreeNode<T>* node = BTreeNode<T>::NewNode();

        if( node == NULL )
        {
            THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create new node ...");
        }
        else
        {
            node->value = value;
            node->parent = parent;

            ret = insert(node, pos);

            if( !ret )
            {
                delete node;
            }
        }

        return ret;
    }

mian.cpp测试这棵树:
技术分享图片

#include <iostream>
#include "BTree.h"

using namespace std;
using namespace StLib;

int main()
{
    BTree<int> bt;
    BTreeNode<int>* n = NULL;

    bt.insert(1, NULL);

    n = bt.find(1);
    bt.insert(2, n);
    bt.insert(3, n);

    n = bt.find(2);
    bt.insert(4, n);
    bt.insert(5, n);

    n = bt.find(4);
    bt.insert(8, n);
    bt.insert(9, n);

    n = bt.find(5);
    bt.insert(10, n);

    n = bt.find(3);
    bt.insert(6, n);
    bt.insert(7, n);

    n = bt.find(6);
    bt.insert(11, n, LEFT);

    int a[] = {8, 9, 10, 11, 7};

    for(int i=0; i<5; i++)
    {
        TreeNode<int>* node = bt.find(a[i]);

        while( node )
        {
            cout << node->value << " ";
            node = node->parent;
        }

        cout << endl;
    }

    return 0;
}

运行结果为:

8 4 2 1 
9 4 2 1 
10 5 2 1 
11 6 3 1 
7 3 1 

3.二叉树中结点的删除操作

删除的方式:

  • 基于数据元素值的删除
    1. SharedPointer< Tree<T> > remove(const T& value)
  • 基于结点的删除
    1. SharedPointer< Tree<T> > remove(TreeNode<T>* node)

二叉树中的结点删除:
技术分享图片

删除操作功能的定义:

  • void remove(BTreeNode<T>* node, BTree<T>*& ret)
    1. 将 node 为根结点的子树从原来的二叉树中删除
    2. ret 作为子树返回 ( ret 指向堆空间中的二叉树对象 )

删除功能函数的实现:
技术分享图片

在BTree.h中实现结点的删除操作:

protected:
    virtual void remove(BTreeNode<T>* node, BTree<T>*& ret)
    {
        ret = new BTree<T>();

        if( ret == NULL )
        {
            THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create new tree ...");
        }
        else
        {
            if( root() == node )
            {
                this->m_root = NULL;
            }
            else
            {
                BTreeNode<T>* parent = dynamic_cast<BTreeNode<T>*>(node->parent);

                if( parent->left == node )
                {
                    parent->left = NULL;
                }
                else if( parent->right == node )
                {
                    parent->right = NULL;
                }

                node->parent = NULL;
            }

            ret->m_root = node;
        }
    }
public:
    SharedPointer< Tree<T> > remove(const T& value)
    {
        BTree<T>* ret = NULL;
        BTreeNode<T>* node = find(value);

        if( node == NULL )
        {
            THROW_EXCEPTION(InvalidParameterException, "Can not find the tree node via value ...");
        }
        else
        {
            remove(node, ret);
        }

        return ret;
    }

    SharedPointer< Tree<T> > remove(TreeNode<T>* node)
    {
        BTree<T>* ret = NULL;

        node = find(node);

        if( node == NULL )
        {
            THROW_EXCEPTION(InvalidParameterException, "Parameter node is invalid ...");
        }
        else
        {
            remove(dynamic_cast<BTreeNode<T>*>(node), ret);
        }

        return ret;
    }

mian.cpp测试:

#include <iostream>
#include "BTree.h"

using namespace std;
using namespace StLib;

int main()
{
    BTree<int> bt;
    BTreeNode<int>* n = NULL;

    bt.insert(1, NULL);

    n = bt.find(1);
    bt.insert(2, n);
    bt.insert(3, n);

    n = bt.find(2);
    bt.insert(4, n);
    bt.insert(5, n);

    n = bt.find(4);
    bt.insert(8, n);
    bt.insert(9, n);

    n = bt.find(5);
    bt.insert(10, n);

    n = bt.find(3);
    bt.insert(6, n);
    bt.insert(7, n);

    n = bt.find(6);
    bt.insert(11, n, LEFT);

    int a[] = {8, 9, 10, 11, 7};

    SharedPointer< Tree<int> > sp = bt.remove(3);

    for(int i=0; i<5; i++)
    {
        TreeNode<int>* node = sp->find(a[i]);

        while( node )
        {
            cout << node->value << " ";
            node = node->parent;
        }

        cout << endl;
    }

    return 0;
}

运行结果为:




11 6 3 
7 3 

4.二叉树中结点的清除操作

清除操作的定义:

  • void clear()
    1. 将二叉树中的所有结点清除 ( 释放堆中的结点 )

二叉树中结点的清除:
技术分享图片

清除操作功能的定义:

  • free(node)
    1. 清除 node 为根结点的二叉树
    2. 释放二叉树中的每一个结点

技术分享图片

在BTree.h中实现结点的清除操作:

protected:
    virtual void free(BTreeNode<T>* node)
    {
        if( node != NULL )
        {
            free(node->left);
            free(node->right);

            if( node->flag() )
            {
                delete node;
            }
        }
    }
public:
    void clear()
    {
        free(root());

        this->m_root = NULL;
    }

5.小结

  • 二叉树的插入操作需要指明插入的位置
  • 插入操作必须正确处理指向父结点的指针
  • 插入数据元素时需要从堆空间中创建结点
  • 当数据元素插入失败时需要释放结点空间

  • 删除操作将目标结点所代表的子树移除
  • 删除操作必须完善处理父结点和子结点的关系
  • 清除操作用于销毁树中的每个结点
  • 销毁结点时判断是否释放对应的内存空间 ( 工厂模式 )

最终的BTree.h代码:
BTree.h

#ifndef BTREE_H
#define BTREE_H

#include "Tree.h"
#include "BTreeNode.h"
#include "Exception.h"
#include "LinkQueue.h"

namespace StLib
{

template <typename T>
class BTree : public Tree<T>
{
protected:
    virtual BTreeNode<T>* find(BTreeNode<T>* node, const T& value) const
    {
        BTreeNode<T>* ret = NULL;

        if( node != NULL )
        {
            if( node->value == value )
            {
                return node;
            }
            else
            {
                if( ret == NULL )
                {
                    ret = find(node->left, value);
                }

                if( ret == NULL )
                {
                    ret = find(node->right, value);
                }
            }
        }

        return ret;
    }

    virtual BTreeNode<T>* find(BTreeNode<T>* node, BTreeNode<T>* obj) const
    {
        BTreeNode<T>* ret = NULL;

        if( node == obj )
        {
            return node;
        }
        else
        {
            if( node != NULL )
            {
                if( ret == NULL )
                {
                    ret = find(node->left, obj);
                }

                if( ret == NULL )
                {
                    ret = find(node->right, obj);
                }
            }
        }

        return ret;
    }

    virtual bool insert(BTreeNode<T>* n, BTreeNode<T>* np, BTNodePos pos)
    {
        bool ret = true;

        if( pos == ANY )
        {
            if( np->left == NULL )
            {
                np->left = n;
            }
            else if( np->right == NULL )
            {
                np->right = n;
            }
            else
            {
                ret = false;
            }
        }
        else if( pos == LEFT )
        {
            if( np->left == NULL )
            {
                np->left = n;
            }
            else
            {
                ret = false;
            }
        }
        else if( pos == RIGHT )
        {
            if( np->right == NULL )
            {
                np->right = n;
            }
            else
            {
                ret = false;
            }
        }
        else
        {
            ret = false;
        }

        return ret;
    }

    virtual void remove(BTreeNode<T>* node, BTree<T>*& ret)
    {
        ret = new BTree<T>();

        if( ret == NULL )
        {
            THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create new tree ...");
        }
        else
        {
            if( root() == node )
            {
                this->m_root = NULL;
            }
            else
            {
                BTreeNode<T>* parent = dynamic_cast<BTreeNode<T>*>(node->parent);

                if( parent->left == node )
                {
                    parent->left = NULL;
                }
                else if( parent->right == node )
                {
                    parent->right = NULL;
                }

                node->parent = NULL;
            }

            ret->m_root = node;
        }
    }

    virtual void free(BTreeNode<T>* node)
    {
        if( node != NULL )
        {
            free(node->left);
            free(node->right);

            if( node->flag() )
            {
                delete node;
            }
        }
    }
public:
    bool insert(TreeNode<T>* node)
    {
        return insert(node, ANY);
    }

    virtual bool insert(TreeNode<T>* node, BTNodePos pos)
    {
        bool ret = true;

        if( node != NULL )
        {
            if( this->m_root == NULL )
            {
                node->parent = NULL;
                this->m_root = node;
            }
            else
            {
                BTreeNode<T>* np = find(node->parent);

                if( np != NULL )
                {
                    ret = insert(dynamic_cast<BTreeNode<T>*>(node), np, pos);
                }
                else
                {
                    THROW_EXCEPTION(InvalidParameterException, "Invalid parent tree node ...");
                }
            }
        }
        else
        {
            THROW_EXCEPTION(InvalidParameterException, "Parameter node can not be NULL ...");
        }

        return ret;
    }

    bool insert(const T& value, TreeNode<T>* parent)
    {
        return insert(value, parent, ANY);
    }

    virtual bool insert(const T& value, TreeNode<T>* parent, BTNodePos pos)
    {
        bool ret = true;
        BTreeNode<T>* node = BTreeNode<T>::NewNode();

        if( node == NULL )
        {
            THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create new node ...");
        }
        else
        {
            node->value = value;
            node->parent = parent;

            ret = insert(node, pos);

            if( !ret )
            {
                delete node;
            }
        }

        return ret;
    }

    SharedPointer< Tree<T> > remove(const T& value)
    {
        BTree<T>* ret = NULL;
        BTreeNode<T>* node = find(value);

        if( node == NULL )
        {
            THROW_EXCEPTION(InvalidParameterException, "Can not find the tree node via value ...");
        }
        else
        {
            remove(node, ret);
        }

        return ret;
    }

    SharedPointer< Tree<T> > remove(TreeNode<T>* node)
    {
        BTree<T>* ret = NULL;

        node = find(node);

        if( node == NULL )
        {
            THROW_EXCEPTION(InvalidParameterException, "Parameter node is invalid ...");
        }
        else
        {
            remove(dynamic_cast<BTreeNode<T>*>(node), ret);
        }

        return ret;
    }

    BTreeNode<T>* find(const T& value) const
    {
        return find(root(), value);
    }

    BTreeNode<T>* find(TreeNode<T>* node) const
    {
        return find(root(), dynamic_cast<BTreeNode<T>*>(node));
    }

    BTreeNode<T>* root() const
    {
        return dynamic_cast<BTreeNode<T>*>(this->m_root);
    }

    int degree() const
    {
        return NULL;
    }

    int count() const
    {
        return NULL;
    }

    int height() const
    {
        return NULL;
    }

    void clear()
    {
        free(root());

        this->m_root = NULL;
    }

    ~BTree()
    {
        clear();
    }
};

}

#endif // BTREE_H











以上是关于书上有个例题看不懂啊,二叉树查找数据元素,C高手帮帮忙 O_O (菜鸟在线)的主要内容,如果未能解决你的问题,请参考以下文章

史上最详细的二叉树B树,看不懂怨我

平衡二叉树的操作(高手进)

谁帮我翻译下这段 完全看不懂啊! - -见つかりませんでした。 人名の场合は姓名を分けて検索してみ

C语言,哪位好心的大哥,姐姐:能告述我位运算吗?我看不懂啊!

求C语言高手! 1:用动画演示二叉树的三种遍历。2:绘制出一个小球,在屏幕左右端之间不停滚动。

高手啊 求救求救啊帮我用c语言编写个先进先出的算法 急需啊