二叉树的初步实现

二叉树的初步实现,写了有一段时间了,如果有大神发现不足之处,希望可以帮我指出来,感激不尽!、

 

二叉树(Binary Tree)是一种树形结构,它的特点是每个结点至多只有两颗子树(即二叉树中不存在大于2的结点),并且,二叉树的子树有左右之分,其次序不能任意改变。

根据二叉树的性质,我们可以将二叉树的每一个结点的结构画出来:

            二叉树的结点

代码实现:

class BinaryTreeNode
{
public:
    ElemType content;                      //结点中的元素
    BinaryTreeNode *leftnode;                    //指向左子树的结点
    BinaryTreeNode *rightnode;                //指向右子树的结点

};

 

 

二叉树的结构:

                    二叉树结构 

创建二叉树:

    创建二叉树的思路是,输入值,如果不为-1,那么先为当前结点内的content赋值,再次输入值,如果值不为-1,那么为当前结点的左子树赋值,如果为-1,那么为根节点的右子树赋值,好吧,可能有点乱,画个图就好了。

    比如说输入的值是:1 2 -1 3 -1 -1 4 -1 -1
    那么,得到的二叉树的结构就是:

                        

   对于这种输入,我们可以用递归的思想,这种思想类似于二叉树的前序遍历,这个后面会说到。

   代码实现:

    

void CreatBinaryTree(BinaryTreeNode*&head)
{
    //------首先判断输入的内容是否为-1,如果为-1那么返回上一层
    //临时变量,用来储存输入的内容
    ElemType linshi;
    cout << "请输入值:";
    cin >> linshi;
    if (linshi == -1)
    {
        //如果输入的是-1号,那么当前指针指向空参数
        head = NULL;
    }
    //如果输入的不是-1号,那么,做相应的操作
    else
    {
        //为当前head指针创建新的结点
        head = new BinaryTreeNode;

        //为当前结点的内容赋值
        head->content = linshi;

        //用当前左儿子的结点作参数,再次调用CreatBinaryTree()函数
        CreatBinaryTree(head->leftnode);

        //用当前右儿子的结点做参数,再次调用CreatBianryTree()函数
        CreatBinaryTree(head->rightnode);
    }

}

 关于输入这里呢,用了递归的思路,可能有些同学会不太懂,因此,我决定在这里对上面的代码进行分析,帮助同学们对递归有更好的理解:
好吧,这个图我画了半个小时.......

              递归函数的分析

 

那么,懂了吧!懂了的话,就说明,你已经对前序遍历理解啦,接下来,中序和后序遍历理解的就很快啦!我就能不画图啦!😀

 

 那么,接下来开始说前序遍历,先放代码!

//输出二叉树结点,利用递归,先序遍历
void PreorderTraversal(BinaryTreeNode*head)
{
    if (head == NULL)
        return;
    else
    {
        //输出当前结点
        cout << head->content << " ";
        //以当前结点的左结点为参数,再次调用PrintBinaryTree()函数
        PreorderTraversal(head->leftnode);
        //以当前结点的右结点为参数,再次调用PrintBinaryTree()函数
        PreorderTraversal(head->rightnode);
    }

}

 

 有没有一种似曾相识的感觉?你可以向上翻一下,上面的输入中的else中的代码是不是和这个很相似!因为他们是一个思路啊,兄得!
那么,这里就不多说啦(因为我懒得画图了...),前序遍历输出的顺序是:1 2 3 4

 

那么,接下来就是中序遍历,上代码!

//输出二叉树结点,利用递归,中序遍历
void InorderTraversal(BinaryTreeNode*head)
{
    if (head == NULL)
        return;
    else
    {
        //以当前结点的左结点为参数,调用InorderTraversal()函数
        InorderTraversal(head->leftnode);
        //输出当前结点的内容
        cout << head->content << " ";
        //以当前结点的右结点为参数,调用InorderTraversal()函数
        InorderTraversal(head->rightnode);
    }

}

 

怎么样,是不是又有一种似曾相识的感觉,你可以向上翻一下前序遍历的代码,他们的区别就在于,输出元素的时间不一样,前序的在最前面,中序的在中间,那么,后序的
你肯定就会了吧!自己试一下吧!

中序遍历输出:2 3 1 4

后序遍历输出:3 2 4 1

对啦,这里说一个小的知识点,我们可以根据两种输出的结果,推出唯一的一颗二叉树,前提是,两种输出结果中,有一种是中序遍历!那么好啦,终于写完啦!

 

 

放出全部代码!

//本程序的目的是利用链表实现二叉树,并且实现先序遍历,中序遍历,后序遍历
#include<iostream>
using namespace std;

//二叉树的结点
template<class T>
class BinaryTreeNode
{
public:
    BinaryTreeNode<T>* leftnode;            //左边的结点
    BinaryTreeNode<T>* rightnode;            //右边的结点
    T content;                                //结点中内容
};

//创建二叉树,利用递归从左到右创建,如果输入-1则表示该结点为空
//创建二叉树函数的模块的思路是在csdn上找到的思路,利用递归函数创建,//先序的思路
template<class T>
void PreCreatBinaryTree(BinaryTreeNode<T>*&head)
{
//------首先判断输入的内容是否为-1,如果为-1那么返回上一层
    //临时变量,用来储存输入的内容
    T linshi;
    cout << "请输入值:";
    cin >> linshi;
    if (linshi == -1)
    {
        //如果输入的是-1号,那么当前指针指向空参数
        head = NULL;
    }
    //如果输入的不是-1号,那么,做相应的操作
    else
    {
        //为当前head指针创建新的结点
        head = new BinaryTreeNode<T>;

        //为当前结点的内容赋值
        head->content = linshi;

        //用当前左儿子的结点作参数,再次调用CreatBinaryTree()函数
        CreatBinaryTree(head->leftnode);

        //用当前右儿子的结点做参数,再次调用CreatBianryTree()函数
        CreatBinaryTree(head->rightnode);
    }

}
//输出二叉树结点,利用递归,先序遍历
template<class T>
void PreorderTraversal(BinaryTreeNode<T>*head)
{
    if (head == NULL)
        return;
    else
    {
        //输出当前结点
        cout << head->content << " ";
        //以当前结点的左结点为参数,再次调用PrintBinaryTree()函数
        PreorderTraversal(head->leftnode);
        //以当前结点的右结点为参数,再次调用PrintBinaryTree()函数
        PreorderTraversal(head->rightnode);
    }

}

//输出二叉树结点,利用递归,中序遍历
template<class T>
void InorderTraversal(BinaryTreeNode<T>*head)
{
    if (head == NULL)
        return;
    else
    {
        //以当前结点的左结点为参数,调用InorderTraversal()函数
        InorderTraversal(head->leftnode);
        //输出当前结点的内容
        cout << head->content << " ";
        //以当前结点的右结点为参数,调用InorderTraversal()函数
        InorderTraversal(head->rightnode);
    }

}

//输出二叉树结点,利用递归,后序遍历
template<class T>
void PostorderTraversal(BinaryTreeNode<T>*head)
{
    //如果结点为空,返回上一层
    if (head == NULL)
        return;
    //如果不为空,执行相应的操作
    else
    {
        //以当前结点的左结点为参数,调用PostorderTraversal()函数
        PostorderTraversal(head->leftnode);
        //以当前结点的右结点为参数,调用PostorderTraversal()函数
        PostorderTraversal(head->rightnode);
        //输出当前结点的内容
        cout << head->content << " ";
    }

}

//销毁二叉树,利用递归,后序遍历(销毁是用后序遍历,如果用先序遍历或者中序遍历会使树断掉)
//关于销毁二叉树的函数让我十分惊喜,因为,他可以将头节点一并删除
template<class T>
void DestoryBinaryTree(BinaryTreeNode<T>* &head)
{
    //如果结点为空,返回上一层结点
    if (head == NULL)
        return;
    //如果结点不为空,执行相应操作
    else
    {
        //调试信息
        BinaryTreeNode<int>*head1 = head;

        //以当前结点的左结点为参数,调用DestoryBinaryTree()函数
        DestoryBinaryTree(head->leftnode);
        //以当前结点的右结点为参数,调用DestoryBinaryTree()函数
        DestoryBinaryTree(head->rightnode);
        //销毁当前结点
        delete head;
    }

}


//主函数
int main()
{
    BinaryTreeNode <int>*a = new BinaryTreeNode<int>;
    PostCreatBinaryTree(a);

    cout << "先序输出:";
    PreorderTraversal<int>(a);
    cout << endl;

    cout << "中序输出:";
    InorderTraversal<int>(a);
    cout << endl;
    
    cout << "后序输出:";
    PostorderTraversal<int>(a);
    cout << endl;

    //销毁二叉树
    DestoryBinaryTree<int>(a);


    //销毁新创建的二叉树结点
    //delete a;
    
    system("pause");
    return 0;
}

 

posted @ 2018-11-29 20:41  笼包叔叔  阅读(209)  评论(0编辑  收藏  举报