二叉树的基本功能实现

整理了一下关于二叉树的各种操作,为了方便直接全程使用排序二叉树。
涉及到的有如下的几种功能:

1、定义二叉树数据结构;
2、由前序遍历及中序遍历构造二叉树;
3、将一组数构造成二叉搜索树;
4、求二叉树的高度;
5、查找某个结点的递归与非递归实现;
6、在指定位置插入的实现(递归与非递归);
7、寻找最大、最小结点的递归与非递归实现;
8、删除指定结点;

首先是定义相应的数据结构类型,此处结合struct和class来实现。
一开始定义的typedef int T;可以方便地对数据类型进行修改。

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;

typedef int T;
typedef struct treenode
{
    T value;
    treenode *left,*right;
}treenode;

static treenode* build_node(T value)    //创建结点 
{
    treenode* tree=new treenode;
    tree->value=value;
    tree->left=NULL;
    tree->right=NULL;
    return tree;
}
class Btree
{
    static int n,m;
    public:
        Btree()
        {
            root=NULL;
        }
        void creat_Bsearch_tree(T x);   //建立二叉查找树;
        T GetHeight();    //求树高; 
    protected:
        T GetHeight(treenode*); 
    private:
        treenode* root;
};

之后是由已知数组直接构造二叉搜索树的操作以及求树的高度。

void Btree::creat_Bsearch_tree(T x)     //建立排序二叉树 规则是 
{
    treenode *newnode=new treenode;
    newnode->value=x;
    newnode->left=NULL;
    newnode->right=NULL;
    if(root=NULL)
    {
        root=newnode;
    }
    else
    {
        treenode *back,*current=root;
        while(current!=NULL)
        {
            back=current;
            if(current->value>x)
            {
                current=current->left;
            }
            else
            {
                current=current->right;
            }
        }
        if(back->value>x)
        {
            back->left=newnode;
        }
        else
        {
            back->right=newnode;
        }
    }
}
T Btree::GetHeight(treenode* tree)  //求二叉树的高度 
{  
    if(tree==0) return 0;  
    else  
    {  
        int l_h=GetHeight(tree->left);  
        int r_h=GetHeight(tree->right);  
        return (l_h>r_h) ? l_h+1:r_h+1;  
    }  
}

然后是由先序遍历以及中序遍历序列来构造二叉树。

//由先序遍历及中序遍历建立二叉树 
treenode* fm_creat_Btree(T preOrder[],T p_l,T p_r,T inOrder[],T i_l,T i_r)
{
    if((p_r-p_l)!=(i_r-i_l)||p_r<p_l)    
    {
        return NULL;  //当两个遍历序列长度不一或始位置大于末位置时
    }

    //第一个元素是先序遍历的第一个元素,是根结点 
    treenode* tree=(treenode*)malloc(sizeof(treenode));
    tree->value=preOrder[p_l];
    tree->left=NULL;
    tree->right=NULL;
    if(p_l==p_r)
    {
        return tree;    //显然是只有一个点的树 
    }
    //在中序遍历中寻找根结点
    T itemp;
    for(itemp=i_l;itemp<=i_r;itemp++)
    {
        if(inOrder[itemp]==preOrder[p_l])
        {
            break;
        }
    } 
    if(itemp>i_r)
    {
        return NULL;    //找不到的情况 
    }

    T length;
    if(itemp>i_l)   //有左叶子时,递归调用 
    {
        length=itemp-i_l;
        tree->left=fm_creat_Btree(preOrder,p_l+1,p_l+length,inOrder,i_l,i_l+length-1);
    } 
    if(itemp<i_r)   //有右叶子时,递归调用 
    {
        length=i_r-itemp;
        tree->right=fm_creat_Btree(preOrder,p_r-length+1,p_r,inOrder,i_r-length+1,i_r);
    }
    return tree;
}

之后是分别采用递归或非递归思想来实现的查找、插入。

treenode* re_search(treenode* tree,T x) //查找关键字为x的结点(递归) 
{
    if(tree->value==x)
    {
        return  tree;
    }
    else if(tree->value>x)
    {
        if(tree->left!=NULL)
        {
            return re_search(tree->left,x);
        }
        else
        {
            return NULL;
        }
    }
    else if(tree->value<x)
    {
        if(tree->right!=NULL)
        {
            return re_search(tree->right,x);
        }
        else
        {
            return NULL;
        }
    }
}
treenode* search(treenode* tree,T x)    //查找关键字为x的结点(非递归) 
{
    if(!tree)
    {
        return NULL;
    }
    treenode* p=tree;
    while(p)
    {
        if(p->value<x)
        {
            p=p->right;
        }
        else if(p->value>x)
        {
            p=p->left;
        }
        return p;
    }
    return NULL;
}
treenode* re_BSTinsert(treenode* tree,T x)      //排序二叉树的插入(递归) 
{
    if(!tree)
    {
        return build_node(x);
    }
    if(tree->value>x)
    {
        tree->left=re_BSTinsert(tree->left,x);
    }
    else
    {
        tree->right=re_BSTinsert(tree->right,x);
    }
    return tree;
}

treenode* BSTinsert(treenode* tree,T x)     //排序二叉树的插入(非递归) 
{
    treenode* p;
    treenode* p_f;  //p_f为待插入结点的父结点 
    p=tree;
    p_f=NULL;
    while(p)
    {
        p_f=p;
        if(p->value<x)
        {
            p=p->right;
        }
        else
        {
            p=p->left;
        }
        if(tree==NULL)
        {
            tree=build_node(x);
            return tree;
        }
        else
        {
            if(p_f->value<x)
            {
                p_f->right=build_node(x);
            }
            else
            {
                p_f->left=build_node(x);
            }
            return tree;
        }
    }
}

treenode* re_findmax(treenode* tree)        //寻找最大结点(递归) 
{
    if(tree->right==NULL)
    {
        return tree;
    }
    else
    {
        re_findmax(tree->right);
    }
}
treenode* findmax(treenode* tree)   //寻找最大结点(非递归)
{
    treenode* p;
    p=tree;
    while(p->right)
    {
        p=p->right;
    }
    return p;
} 
treenode* re_findmin(treenode* tree)    //寻找最小结点(递归)
{
    if(tree->left==NULL)
    {
        return tree;
    }
    else
    {
        re_findmin(tree->left);
    }
} 
treenode* findmin(treenode* tree)   //寻找最小结点(非递归)
{
    treenode* p;
    p=tree;
    while(p->left)
    {
        p=p->left;
    }
    return p;
} 

最后是删除的操作。

treenode* remove(treenode* tree,T x)    //删除指定结点 
{
    if(!tree)
    {
        return NULL;
    }
    treenode* back;
    if(x==tree->value)
    {
        if(tree->left==NULL)    //没有左子树的情况 
        {
            back=tree;
            tree=tree->right;
            delete back;
        }
        else if(tree->right==NULL)  //没有右子树的情况 
        {
            back=tree;
            tree=tree->left;
            delete back;
        }
        else                    //寻找前驱替代(有左右子树) 
        {
            treenode* temp;
            temp=findmax(tree->left);
            tree->value=temp->value;
            remove(tree->left,temp->value);
        }
    }
    else if(x<tree->value)      //递归调用以查找 
    {
        remove(tree->left,x);
    }
    else if(x>tree->value)
    {
        remove(tree->right,x);
    }
}

总结后发现在对于二叉树的操作中,不止一次地需要领会理解递归,这也和二叉树在此处采用了单链表的存储方式有莫大的关系。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值