二叉树的定义在这里不做陈述,我们直接来看看如何实现一个二叉树的创建(c++)
首先定义结点,这里我们呢用结构体来创建
template<typename T>
struct BinaryTreeNode //创建孩子二叉树的结点
{
BinaryTreeNode(const T& data = T())
:_data(data)
, _pLeft(NULL)
, _pRight(NULL)
{}
T _data;
BinaryTreeNode* _pLeft;
BinaryTreeNode* _pRight;
};
定义好结点之后我们就可以来想办法创建一个二叉树类,其中包含二叉树的创建和基本操作
template<typename T>
class BinaryTree
{
typedef BinaryTreeNode<T> Node;
public:
BinaryTree()
: _pRoot()
{}
/***********用函数封装来做************/
BinaryTree(const T* array, size_t size, const T& invalid) //构造函数构造二叉树
{
size_t index = 0;
_pRoot = CreatTree(array, size, index, invalid);
}
BinaryTree(const BinaryTree<T>& b) //拷贝构造一个相同的二叉树
{
_pRoot = Copy(b._pRoot);
}
BinaryTree& operator=(BinaryTree<T>& b) //重载=
{
if (this != &b) //防止自己给自己赋值
{
BinaryTree<T> tem(b);
std::swap(_pRoot, tem._pRoot);
}
return *this;
}
~BinaryTree() //析构函数释放树
{
Destory(_pRoot);
}
size_t _Leaf() //求叶子结点个数
{
return Leaf(_pRoot);
}
size_t _Size() //求结点个数
{
return Size(_pRoot);
}
size_t _Depth() //求树的深度
{
return Depth(_pRoot);
}
void _PreOder() //先序遍历
{
PreOder(_pRoot);
cout << endl;
}
void _InOder() //中序遍历
{
InOder(_pRoot);
cout << endl;
}
void _BackOder() //后序遍历
{
BackOder(_pRoot);
cout << endl;
}
protected:
Node* _pRoot;
}
创建好这个二叉树类之后我们来将其中的功能进行相应的实现(这里我将所有的函数实现都已private的形式写在了类内部)
··········创建二叉树
/*先序递归创建二叉树*/
Node* CreatTree(const T* array, size_t size, size_t& index, const T& invalid)
{
assert(array);
Node* pRoot = NULL;
if (index < size&&array[index] != invalid)
{
pRoot = new Node(array[index]);
pRoot->_pLeft = CreatTree(array, size, ++index, invalid);
pRoot->_pRight = CreatTree(array, size, ++index, invalid);
}
return pRoot;
}
/*非递归创建二叉树*/
Node *CreatTree(const T* a, size_t size, size_t index, const T& invalid)
{
stack<Node*> s;
Node* pRoot = new Node(a[index++]);
int flag = 1; //flag =1创建左孩子,=2创建右孩子,=3出栈
s.push(pRoot);
Node *pPre = NULL;
Node *pCur = NULL;
while (index<size)
{
if (flag == 1) //创建左孩子
{
if (a[index] == invalid) //如果左孩子为空,则flag=2创建右孩子
{
flag = 2;
}
else
{
pCur = new Node(a[index]);
pPre = s.top();
pPre->_pLeft = pCur; //链接到左指针上
s.push(pCur); //将新节点压入栈中
}
}
else if (flag == 2) //flag=2,创建右孩子
{
if (a[index] == invalid) //如果右孩子为空,则flag=3准备出栈
{
flag = 3;
}
else
{
pCur = new Node(a[index]);
pPre = s.top();
pPre->_pRight = pCur; //链接到左指针上
s.push(pCur); //将新节点压入栈中
flag = 1; //再创建新结点的左孩子
}
}
else
{
if (!s.empty())
{
pPre = s.top();
s.pop();
}
//如果已经出栈的元素是当前栈顶的右孩子,则表示这个结点的左右子树已经创建完毕,则一直出栈
while (!s.empty() && s.top()->_pRight == pPre)
{
pPre = s.top();
s.pop();
}
flag = 2;
index--;
}
index++;
}
return pRoot;
}
··········先序遍历
/*递归先序遍历*/
void PreOder(Node* pRoot)
{
Node* pCur = pRoot;
if (pCur)
{
cout << pCur->_data << " ";
PreOder(pCur->_pLeft);
PreOder(pCur->_pRight);
}
}
/*非递归先序遍历*/
void PreOder(Node* _pRoot)
{
assert(_pRoot);
Node *pRoot = _pRoot;
stack<Node*> s;
s.push(pRoot);
int flag = 1;
Node *pCur = NULL;
while (!s.empty())
{
pCur = s.top();
if (flag == 1) //遍历左子树
{
if (pCur->_pLeft == NULL) //如果左子树为空,则flag=2
{
flag = 2;
}
else
{
cout << pCur->_Data << " "; //先序输出,先输出根结点
s.push(pCur->_pLeft);
}
}
else if (flag == 2)
{
if (pCur->_pRight == NULL)
{
flag = 3;
}
else
{
s.push(pCur->_pRight);
flag = 1;
}
}
else
{
Node *pPre = NULL;
if (!s.empty())
{
pPre = s.top();
s.pop();
}
pCur = pPre;
while (!s.empty() && s.top()->_pRight == pPre) //将输出过的结点出栈
{
pPre = s.top();
s.pop();
}
if (!s.empty()) //输出右子树的叶子节点
{
cout << pCur->_Data << " ";
}
flag = 2;
}
}
cout << endl;
}
·········中序遍历
/*递归中序遍历*/
void InOder(Node* pRoot)
{
Node* pCur = pRoot;
if (pCur)
{
InOder(pCur->_pLeft);
cout << pCur->_data << " ";
InOder(pCur->_pRight);
}
}
/*非递归中序遍历*/
void InOder(Node* _pRoot)
{
assert(_pRoot);
Node *pRoot = _pRoot;
stack<Node*> s;
s.push(pRoot);
int flag = 1;
while (!s.empty())
{
Node *pCur = s.top();
if (flag == 1) //先遍历左子树
{
if (pCur->_pLeft == NULL)
{
flag = 2;
}
else
{
s.push(pCur->_pLeft);
}
}
else if (flag == 2) //遍历右子树
{
if (pCur->_pRight == NULL)
{
flag = 3;
}
else
{
cout << pCur->_Data << " "; //输出右子树的跟结点
s.push(pCur->_pRight);
flag = 1;
}
}
else
{
Node* pPre = NULL;
if (!s.empty())
{
pPre = s.top();
s.pop();
}
cout << pPre->_Data << " "; //输出左子树结点和左子树的根结点
while (!s.empty() && s.top()->_pRight == pPre)
{
pPre = s.top();
s.pop();
}
flag = 2;
}
}
cout << endl;
}
········后序遍历
/*递归后序遍历*/
void BackOder(Node* pRoot)
{
Node* pCur = pRoot;
if (pCur)
{
BackOder(pCur->_pLeft);
BackOder(pCur->_pRight);
cout << pCur->_data << " ";
}
}
/*非递归后序遍历*/
void BackOder(Node* _pRoot)
{
assert(_pRoot);
Node *pRoot = _pRoot;
stack<Node*> s;
int flag = 1; //=1遍历左子树,=2 遍历右子树,=3 输出结点
s.push(pRoot); //根节点入栈
Node *pCur = NULL;
while (!s.empty())
{
pCur = s.top();
if (flag == 1) //遍历左子树
{
if (pCur->_pLeft == NULL) //如果左子树为空,则flag=2,准备遍历右子树
{
flag = 2;
}
else
{
s.push(pCur->_pLeft);
}
}
else if (flag == 2) //遍历右子树
{
if (pCur->_pRight == NULL) //右子树为空,准备输出结点
{
flag = 3;
}
else
{
s.push(pCur->_pRight);
flag = 1; //遍历当前结点的左子树
}
}
else
{
Node *pPre = NULL;
if (!s.empty())
{
pPre = s.top(); //保存当前栈顶元素
s.pop(); //抛出栈顶元素
}
cout << pPre->_Data << " "; //输出结点的信息
//如果当前栈顶元素的右子树是pPre,则抛出pPre之后按照后序也要抛出栈顶元素
while (!s.empty() && s.top()->_pRight == pPre)
{
pPre = s.top(); //保存当前栈顶元素
s.pop(); //抛出栈顶元素
cout << pPre->_Data << " "; //输出结点的信息
}
flag = 2;
}
}
cout << endl;
}
········求叶子结点个数
/*递归*/
size_t Leaf(Node* pRoot)
{
Node* pCur = pRoot;
if (NULL == pCur)
return 0;
if (pCur->_pLeft == NULL&&pCur->_pRight == NULL) //如果左右子树都为空,则返回1
return 1;
return Leaf(pCur->_pLeft) + Leaf(pCur->_pRight);
}
/*非递归*/
size_t Leaf(Node* pRoot)
{
size_t index = 0;
Node* pCur = pRoot;
stack<Node*> s;
while (pCur || !s.empty())
{
while (pCur)
{
//如果左右子树都为空,则为叶子结点
if (pCur->_pLeft == NULL&&pCur->_pRight == NULL)
index++;
s.push(pCur);
pCur = pCur->_pLeft;
}
Node* pPre = s.top();
s.pop();
pCur = pPre ->_pRight;
}
return index;
}
·········求结点个数
/*递归*/
size_t Size(Node* pRoot)
{
if (pRoot == NULL)
return 0;
return 1 + Size(pRoot->_pLeft) + Size(pRoot->_pRight);
}
/*非递归*/
size_t Size(Node* pRoot)
{
size_t index = 0;
Node* pCur = pRoot;
stack<Node*> s;
while (pCur || !s.empty())
{
while (pCur)
{
index++; //遍历一个结点就让count++
s.push(pCur);
pCur = pCur->_pLeft;
}
Node * top = s.top();
s.pop();
pCur = top->_pRight;
}
return index;
}
········树的深度
/*递归*/
size_t Depth(Node* pRoot)
{
Node* pCur = pRoot;
if (NULL == pCur)
return 0;
return 1 + (Depth(pCur->_pLeft) > Depth(pCur->_pRight)
? Depth(pCur->_pLeft) : Depth(pCur->_pRight));
}
/*非递归*/
size_t Depth(Node* pRoot)
{
if (pRoot == NULL)
return 0;
queue<Node*> q;
size_t deep = 0;
size_t NodeNum = 1; //统计有多少数据入过队
size_t LeveLast = 1; //标记正在访问的这层的最后一个数据的序号
size_t VisitNum = 0; //统计已经出队的数据的个数
q.push(pRoot);
while (!q.empty())
{
Node* pCur = q.front();
q.pop();
VisitNum++;
if (NULL != pCur->_pLeft)
{
q.push(pCur->_pLeft);
NodeNum++;
}
if (NULL != pCur->_pRight)
{
q.push(pCur->_pRight);
NodeNum++;
}
//如果以出队的个数等于这一层的最后一个数据的序号
if (LeveLast == VisitNum)
{
deep++; //访问完一层就让深度加一
LeveLast = NodeNum; //更新到下一层的最后一个数据的位置
}
}
return deep;
}
创建好之后让我么来测试一下,首先测试递归版本的二叉树
测试代码如下
void FunTest()
{
int array[] = { 1, 2, 3, '#', 4, '#', '#', 5, 6, '#', '#', 7 };
BinaryTree<int> t(array, sizeof(array) / sizeof(array[0]), '#');
cout << t._Leaf() << endl;
cout << t._Size() << endl;
cout << t._Depth() << endl;
t._PreOder();
t._InOder();
t._BackOder();
}
int main()
{
FunTest();
return 0;
}
输出结果为
接下来是非递归版本的二叉树
测试代码如下
void FunTest()
{
int arr[] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6 };
BinaryTree<int> t(arr, sizeof(arr) / sizeof(arr[0]), '#');
t._PrevOder();
t._InOder();
t._BackOder();
cout << t._Leaf() << endl;
cout << t._Size() << endl;
cout << t._Depth() << endl;
}
int main()
{
FunTest();
system("pause");
return 0;
}
输出结果为
以上就是二叉树的创建及基本操作