很多建立二叉树都是用先序,中序或者后序建立,不过这就要求输入时要自己先想出相应的序列,比如下面的树(括号左边代表序号,里面是元素,0表示节点为空):
1(a)
2(b) 3(c)
4(0) 5(d) 6(e) 7(f)
建立此树时,比如按中序建立,要得出其中序序列,这里就是0bdaecf,这样建立不太方便,因为要按照中序输入,比如一棵树深度比较大,就比较麻烦了,而按照层次建立呢?很快就可以写出其输入序列,这里就是abc0def了
以下是我自己实现的按层析建立二叉树:
binTreeNode.h
#pragma once
# include<iostream>
template <typename T>
class binTreeNode
{
public:
binTreeNode() = default;
binTreeNode(const T&t):data(t),lChild(NULL),rChild(NULL)
{}
T data;
binTreeNode *lChild, *rChild;
};
binTree.h
#pragma once
# include"binTreeNode.h"
#include<iostream>
# include<string>
using namespace std;
template <typename T>
class binTree
{
public:
//构造函数:建立二叉树,元素为#时表示为该节点为空
binTree() = default;
void create();
void visit(binTreeNode<T> *node);
void inTraver(binTreeNode<T> *p);
void prevTraver(binTreeNode<T> *p);
void postTraver(binTreeNode<T> *p);
binTreeNode<T>* &getRoot() { return root; }
private:
binTreeNode<T> *root;//二叉树的根节点
};
template<typename T>
void binTree<T>::create()//按层次建立树
{
T elem;
int i = 1;//i表示正在处理的节点的序号,初始化为处理第一个节点
binTreeNode<T>** (arr[100]) = {};
/*
保存指向每个节点的指针,比如建立下面这样的树(括号左边是序号,括号里面节点元素,以整型为例,输入
0表示为空节点):
1(1)
2(2) 3(3)
4(0) 5(4) 6(5) 7(6)
输入时应输入:1 2 3 0 4 5 6
比如处理节点元素为4时,要改变其双亲节点,对吧,令其双亲的rChild指针指向正在处理的节点,所以
我就定义一个数组保存指针
*/
while (cin >> elem)
{
if (i == 1)//第一个元素,处理根节点
{
arr[i - 1] = &root;
root = new binTreeNode<T>(elem);
i++;
continue;
}
if (elem == 0||elem=='0')//如果是空节点
{
if (i % 2 == 0&&(arr[i/2-1]))//能够被2整除,那么该节点为其双亲的左孩子,并且其双亲
//应该存在,才可以令其双亲的左孩子指针为空
((*arr[i / 2-1]))->lChild = NULL;
else if(arr[i/2-1])//否咋是其右孩子
((*arr[i / 2-1]))->rChild = NULL;
arr[i - 1] = NULL;//此节点为空
i++;
continue;
}
arr[i - 1] = new binTreeNode<T> *;//节点不位空
binTreeNode<T> *temp = new binTreeNode<T>(elem);
if (i % 2 == 0)
(*arr[i / 2-1])->lChild = temp;//同理
else (*arr[i / 2-1])->rChild = temp;
*arr[i - 1] = temp;//保存节点指针
i++;
}
}
template <typename T>
void binTree<T>::visit(binTreeNode<T> *node)//访问元素
{
cout << node->data<<" ";
}
template <typename T>
void binTree<T>::inTraver(binTreeNode<T> *p)//中序遍历
{
if (p)
{
inTraver(p->lChild);
visit(p);
inTraver(p->rChild);
}
}
template <typename T>
void binTree<T>::prevTraver(binTreeNode<T> *p)//先序遍历
{
if (p)
{
visit(p);
prevTraver(p->lChild);
prevTraver(p->rChild);
}
}
template <typename T>
void binTree<T>::postTraver(binTreeNode<T> *p)//后序遍历
{
if (p)
{
postTraver(p->lChild);
postTraver(p->rChild);
visit(p);
}
}
main.cpp
# include"BinTree.h"
# include<iostream>
using namespace std;
int main()
{
binTree<int> myBinTree;
cout << "建立二叉树,元素为0时表示为该节点为空(元素为int型):" << endl;
myBinTree.create();
auto &p = myBinTree.getRoot();
cout << endl << "先序遍历为:";
myBinTree.prevTraver(p);
cout <<endl<<"中序遍历为:" ;
myBinTree.inTraver(p);
cout << endl << "后序遍历为:";
myBinTree.postTraver(p);
cout << endl;
return 0;
}
可以实验一下:
没错吧,下面的没看到,把窗口放大一些:
再用char型元素测试一下
不过缺点是空间开销比较大,下面我又加了一些成员:
二叉树的实现