我们先来介绍一些关于树的概念:
节点:结点包含数据和指向其它节点的指针。
根节点:树第一个结点称为根节点。
结点的度:结点拥有的子节点个数。
叶节点:没有子节点的节点(度为0)。
父子节点:一个节点father指向另一个节点child,则child为孩子节点,father为父亲节点 。
兄弟节点:具有相同父节点的节点互为兄弟节点。
节点的祖先:从根节点开始到该节点所经的所有节点都可以称为该节点的祖先。
子孙:以某节点为根的子树中任一节点都称为该节点的子孙。
树的高度:树中距离根节点最远节点的路径长度。
如下图所示
而二叉树就是每个父节点最多有两个子节点的树。
完全二叉树:
满二叉树:
从图中可以看出,满二叉树一定是完全二叉树,而完全二叉树不一定是满二叉树。
#include<iostream>
#include<assert.h>
#include<queue>
#include<stack>
using namespace std;
template<class T>
struct BinaryTreeNode
{
T _data;
BinaryTreeNode<T>* _left;
BinaryTreeNode<T>* _right;
BinaryTreeNode(const T& x)
:_data(x)
, _left(NULL)
, _right(NULL)
{}
};
template<class T>
class BinaryTree
{
typedef BinaryTreeNode<T> Node;
public:
BinaryTree()
:_root(NULL)
{}
BinaryTree(int* a, size_t n, const T& invalid)
{
size_t index = 0;
_root = _CreateTree(a, n, invalid, index);
}
~BinaryTree()
{
_Destroy(_root);
}
void PreOrder()
{
_PreOrder(_root);
cout << endl;
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
void PostOrder()
{
_PostOrder(_root);
cout << endl;
}
//层序遍历(用队列)
void LeefOrder()
{
queue<Node*> q;
if (_root)
{
q.push(_root);
}
while (!q.empty())
{
Node* front = q.front();
q.pop();
cout << front->_data << " ";
if (front->_left)
q.push(front->_left);
if (front->_right)
q.push(front->_right);
}
cout << endl;
}
//求叶子节点个数
size_t LeafSize()
{
return _LeafSize(_root);
}
size_t KLeafSize(size_t k)
{
assert(k > 0);
return _KleafSize(_root,k);
}
size_t Size()
{
return _Size(_root);
}
//非递归前序遍历(用栈)
void PreOrderNoR()
{
_PreOrderNoR(_root);
}
//非递归中序遍历
void InOrderNoR()
{
_InOrderNoR(_root);
}
//非递归后续遍历
void PostOrderNoR()
{
_PostOrderNoR(_root);
}
//在二叉树中查找某个数
Node* Find(const T& data)
{
return _Find(_root, data);
}
//求二叉树的深度
size_t Depth()
{
return _Depth(_root);
}
//判断一棵树是否是完全二叉树
bool JustTree()
{
return _JustTree(_root);
}
protected:
Node* _CreateTree(int* a, size_t n, const T& invalid, size_t &index)
{
Node* root = NULL;
if (index < n && a[index] != invalid)
{
//先要创建节点
root = new Node(a[index]);
root->_left = _CreateTree(a, n, invalid, ++index);
root->_right = _CreateTree(a, n,invalid, ++index);
}
return root;
}
//后续遍历销毁
void _Destroy(Node* root)
{
if (root == NULL)
return;
_Destroy(root->_left);
_Destroy(root->_right);
delete root;
}
//递归前序遍历
void _PreOrder(Node* root)
{
if (root == NULL)
return;
else
{
cout << root->_data << " ";
_PreOrder(root->_left);
_PreOrder(root->_right);
}
}
//递归中序遍历
void _InOrder(Node* root)
{
if (root == NULL)
return;
else
{
_InOrder(root->_left);
cout << root->_data << " ";
_InOrder(root->_right);
}
}
//递归后续遍历
void _PostOrder(Node* root)
{
if (root == NULL)
return;
_PostOrder(root->_left);
_PostOrder(root->_right);
cout << root->_data << " ";
}
//求叶子节点个数
size_t _LeafSize(Node* root)
{
if (root == NULL)
return 0;
if (root->_left == NULL && root->_right == NULL)
return 1;
return _LeafSize(root->_left) + _LeafSize(root->_right);
}
//求第K层节点个数
size_t _KLeafSize(Node* root,size_t k)
{
if (root == NULL)
return 0;
if (k == 1)
return 1;
else
return _KLeafSize(root->_left, k - 1) + _KLeafSize(root->_right, k - 1);
}
size_t _Size(Node* root)
{
if (root == NULL)
return 0;
else
return _Size(root->_left) + _Size(root->_right) + 1;
}
//前序非递归
void _PreOrderNoR(Node* root)
{
stack<Node*> s;
Node* cur = _root;
while (!s.empty() || cur)
{
while (cur)
{
cout << cur->_data << " ";
s.push(cur);
cur = cur->_left;
}
//此时左子树遍历完
Node* top = s.top();
s.pop();
//子问题
cur = top->_right;
}
cout << endl;
}
//非递归中序遍历
void _InOrderNoR(Node* root)
{
stack<Node*> s;
Node* cur = root;
while (!s.empty() || cur)
{
while (cur)
{
s.push(cur);
cur = cur->_left;
}//一直到最左节点
Node* top = s.top();
cout << top->_data << " ";
s.pop();
cur = top->_right;
}
cout << endl;
}
void _PostOrderNoR(Node* root)
{
Node* cur = root;
stack<Node*> s;
Node* prev = NULL;
while (!s.empty() || cur)
{
while (cur)
{
s.push(cur);
cur = cur->_left;
}
Node* top = s.top();
if (top->_right == NULL || top->_right == prev)
{
cout << top->_data << " ";
prev = top;
s.pop();
}
else
{
cur = top->_right;
}
}
cout << endl;
}
Node* _Find(Node* root, const T& data)
{
if (root == NULL)
return NULL;
if (root->_data == data)
return root;
Node* left = _Find(root->_left, data);
if (left)
return left;
Node* right = _Find(root->_right, data);
if (right)
return right;
return NULL;
}
size_t _Depth(Node* root)
{
if (root == NULL)
return NULL;
size_t leftSize = _Depth(root->_left);
size_t rightSize = _Depth(root->_right);
return leftSize > rightSize ? leftSize + 1 : rightSize + 1;
}
bool _JustTree(Node* root)
{
queue<Node*> q;
Node* cur = root;
if (root)
q.push(root);
while ((cur = q.front())&& cur != NULL)
{
q.push(cur->_left);
q.push(cur->_right);
q.pop();
}
while (!q.empty())
{
Node* front = q.front();
if (front != NULL)
return false;
}
return true;
}
private:
Node* _root;
};
void Test()
{
int a[] = { 1, 2, 3,'#','#', 4,'#','#', 5, 6 };
BinaryTree<int> bs(a, sizeof(a) / sizeof(a[0]), '#');
bs.InOrder();
bs.InOrderNoR();
bs.PreOrder();
bs.PreOrderNoR();
bs.PostOrder();
bs.PostOrderNoR();
cout<<bs.Depth()<<endl;
cout<<bs.JustTree() << endl;
}
//递归 简洁 抽象 容易导致栈溢出
//非递归 用栈解决 重点 1,当一个节点从栈拿出来的时候,所有左节点已经访问过了,
//且都压到栈中,将右当成子问题 2,取栈里面的数据,节点右子树(子问题)
此测试用例的运行结果如下: