下面代码所用到的测试用例画成树的样子长这样:
创建树时给的是数组,用‘#’代表非法值,即该结点为空。
二叉树的递归实现:
#pragma once
#include<iostream>
#include<queue>
using namespace std;
template<class T>
struct BinaryTreeNode
{
BinaryTreeNode(T value=0)
:_value(value), _left(NULL), _right(NULL)
{}
T _value;
BinaryTreeNode<T>* _left;
BinaryTreeNode<T>* _right;
};
template<class T>
class BinaryTree
{
public:
typedef BinaryTreeNode<T> Node;
BinaryTree()
{}
BinaryTree(T* a, size_t size, const T& invalid)
{
size_t index = 0;
_root=_CreatTree( a, size,index, invalid);
}
BinaryTree(const BinaryTree<T>& bt)
{
_root = _Copy(bt._root);
}
BinaryTree<T>& operator=(BinaryTree<T>& bt)
{
if (this != &bt)
{
BinaryTree<T> tmp(bt);
swap(tmp._root, _root);
}
}
~BinaryTree()
{
_Distory(_root);
}
void PrevOrder()
{
_PrevOrder(_root);
cout << endl;
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
void PostOrder()
{
_PostOrder(_root);
cout << endl;
}
void LevelOrder() //层序遍历
{
_LevelOrder(_root);
cout << endl;
}
size_t Size()
{
return _Size(_root);
}
size_t Depth()
{
return _Depth(_root);
}
size_t LeafSize()
{
return _LeafSize(_root);
}
size_t GetKLevel(size_t k) //第K层结点个数
{
}
protected:
Node* _Distory(Node* root)
{
if (root)
{
_Distory(root->_left);
_Distory(root->_right);
Node* del = root;
delete del;
}
return root;
}
Node* _CreatTree( T*a, size_t size,size_t& index,const T& invalid)
{
Node* root = NULL;
if ((index < size)&&(a[index] != invalid))
{
root = new Node(a[index]);
root->_left = _CreatTree(a, size, ++index, invalid);
root->_right = _CreatTree(a, size, ++index, invalid);
}
return root;
}
Node* _Copy(Node* copyroot)
{
Node* root = NULL;
if (copyroot!=NULL)
{
root = new Node(copyroot->_value);
root->_left = _Copy(copyroot->_left);
root->_right = _Copy(copyroot->_right);
}
return root;
}
Node* _PrevOrder(Node* root)
{
if (root)
{
cout << root->_value << " ";
_PrevOrder(root->_left);
_PrevOrder(root->_right);
}
return root;
}
Node* _InOrder(Node* root)
{
if (root)
{
_InOrder(root->_left);
cout << root->_value<<" ";
_InOrder(root->_right);
}
return root;
}
Node* _PostOrder(Node* root)
{
if (root)
{
_PostOrder(root->_left);
_PostOrder(root->_right);
cout << root->_value << " ";
}
return root;
}
void _LevelOrder(Node* root)
{
queue<Node*> q;
q.push(root);
while (!q.empty())
{
Node* tmp = q.front();
cout << tmp->_value<<" ";
if (tmp->_left)
q.push(tmp->_left);
if (tmp->_right)
q.push(tmp->_right);
q.pop();
}
}
size_t _Size(Node* root)
{
size_t size = 0;
if (root)
{
size = _Size(root->_left) + _Size(root->_right)+1;
}
return size;
}
size_t _Depth(Node* root)
{
size_t depth1 = 0;
size_t depth2 = 0;
if (root)
{
depth1 = _Depth(root->_left) + 1;
depth2 = _Depth(root->_right) + 1;
}
return depth1 > depth2 ? depth1 : depth2;
}
size_t _LeafSize(Node* root)
{
if (root == NULL)
return 0;
else if (root->_left == NULL&&root->_right == NULL)
return 1;
return _LeafSize(root->_left) + _LeafSize(root->_right);
}
private:
Node* _root;
};
void test()
{
int array[10] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6 };
int array1[15] = { 1, 2, '#', 3, '#', '#', 4, 5, '#', 6, '#', 7, '#', '#', 8 };
BinaryTree<int> bt(array, 10, '#');
bt.PrevOrder();
bt.InOrder();
bt.PostOrder();
cout << bt.Size() << endl;
cout << bt.Depth() << endl;
cout << bt.LeafSize() << endl;
BinaryTree<int> bt2(array1, 15, '#');
cout << bt2.Depth() << endl;
cout << bt2.LeafSize() << endl;
BinaryTree<int> bt3(bt);
bt3.PrevOrder();
BinaryTree<int> bt4=bt3;
bt4.PrevOrder();
bt4.LevelOrder();
}
递归的好处在于代码简练。但递归不容易理解。
非递归的二叉树(面试经常会考的):
#pragma once
#include<iostream>
#include<cassert>
#include<queue>
#include<stack>
using namespace std;
template<class T>
struct BinaryTreeNode
{
BinaryTreeNode(T value = 0)
:_value(value), _left(NULL), _right(NULL)
{}
T _value;
BinaryTreeNode<T>* _left;
BinaryTreeNode<T>* _right;
};
template<class T>
class BinaryTree
{
public:
typedef BinaryTreeNode<T> Node;
BinaryTree()
{}
explicit BinaryTree(T* a, size_t size, const T& invalid) //构造函数,创建一棵树。
{
stack<Node*> s;
size_t index = 0;
Node* cur = NULL;
while (index < size)
{
while ((index < size) && (a[index] != invalid))
{
if (index == 0)
{
_root = new Node(a[index++]);
cur = _root;
}
else
{
cur->_left = new Node(a[index++]);
cur = cur->_left;
}
s.push(cur);
}
index++;
Node* top = s.top();
s.pop();
if ((index < size) && (a[index] != invalid))
{
cur = top;
cur->_right = new Node(a[index++]);
cur = cur->_right;
s.push(cur);
}
}
}
BinaryTree(const BinaryTree<T>& bt) //拷贝构造
{
Node* cur = bt._root;
Node* root = NULL;
stack<Node*>s;
stack<Node*>s1;
while (cur || !s.empty())
{
while (cur)
{
s.push(cur);
if (root == NULL)
{
root = new Node(cur->_value);
_root = root;
}
else
{
root->_left = new Node(cur->_value);
root = root->_left;
}
cur = cur->_left;
s1.push(root);
}
Node* top = s.top();
Node* top1 = s1.top();
s.pop();
s1.pop();
cur = top->_right;
if (cur)
{
root = top1;
root->_right = new Node(cur->_value);
root = root->_right;
cur = cur->_left;
}
}
}
BinaryTree<T>& operator=(BinaryTree<T> bt)
{
swap(_root, bt._root);
return *this;
}
void PrevOrderNoR()
{
Node* cur = _root;
stack<Node*> s;
while (cur || !s.empty())
{
while (cur)
{
cout << cur->_value << " ";
s.push(cur);
cur = cur->_left;
}
Node* top = s.top();
s.pop();
cur = top->_right;
}
cout << endl;
}
void InOrderNoR()
{
Node* cur = _root;
stack<Node*> s;
while (cur || !s.empty())
{
while (cur)
{
s.push(cur);
cur = cur->_left;
}
Node* top = s.top();
s.pop();
cout << top->_value << " ";
cur = top->_right;
}
cout << endl;
}
void PostOrderNoR()
{
Node* cur = _root;
Node* prev = NULL;
stack<Node*> s;
while (cur || !s.empty())
{
while (cur)
{
s.push(cur);
cur = cur->_left;
}
Node* top = s.top();
if ((top->_right == NULL) || (prev == top->_right))
{
prev = top;
cout << top->_value << " ";
s.pop();
//cur = top->_right;
}
else
cur = top->_right;
}
cout << endl;
}
size_t SizeNoR()
{
size_t size = 0;
Node* cur = _root;
stack<Node*> s;
while (cur || !s.empty())
{
while (cur)
{
s.push(cur);
size++;
cur = cur->_left;
}
Node* top = s.top();
s.pop();
cur = top->_right;
}
return size;
}
size_t DepthNoR()
{
if (_root == NULL)
return 0;
size_t depth = 0;
Node* cur = NULL;
queue<Node*> q;
size_t VisitNum = 0; //有多少数据出栈
size_t NodeNum = 1;
size_t LeveNum = 1; //每一层最后一个数据的序号
q.push(_root);
while (!q.empty())
{
cur = q.front();
q.pop();
VisitNum++;
if (cur->_left)
{
NodeNum++;
q.push(cur->_left);
}
if (cur->_right)
{
NodeNum++;
q.push(cur->_right);
}
if (LeveNum == VisitNum)
{
depth++;
LeveNum = NodeNum;
}
}
return depth;
}
size_t LeveNum() //叶子节点个数
{
size_t count = 0;
Node* cur = _root;
stack<Node*> s;
while (cur || !s.empty())
{
while (cur)
{
s.push(cur);
if ((cur->_left == NULL) && (cur->_right == NULL))
count++;
cur = cur->_left;
}
Node* top = s.top();
s.pop();
cur = top->_right;
}
return count;
}
size_t GetKLeve(size_t k) //得到第k层结点个数。
{
assert(k <= DepthNoR());
if (k == 1)
return 1;
queue<Node*>q;
size_t NodeNum = 1;
size_t LeveNum = 1;
size_t VisitNum = 0;
size_t leve = 1;
q.push(_root);
while (!q.empty())
{
Node* cur = q.front();
q.pop();
VisitNum++;
if (cur->_left)
{
q.push(cur->_left);
NodeNum++;
}
if (cur->_right)
{
q.push(cur->_right);
NodeNum++;
}
if (LeveNum == VisitNum)
{
leve++;
if (leve == k)
break;
LeveNum = NodeNum;
}
}
return NodeNum - VisitNum;
}
private:
Node* _root;
};
void test()
{
int array[10] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6 };
BinaryTree<int> bt(array, 10, '#');
bt.PrevOrderNoR();
bt.InOrderNoR();
bt.PostOrderNoR();
BinaryTree<int> bt1(bt);
bt1.PrevOrderNoR();
BinaryTree<int> bt2 = bt1;
bt2.PrevOrderNoR();
cout << bt.SizeNoR() << endl;
cout << bt.DepthNoR() << endl;
cout << bt.LeveNum() << endl;
cout << bt.GetKLeve(3) << endl;
}
可以看到,非递归相对来说代码量能多点,但是比较容易理解,而且几个遍历过程代码十分相似,理解其中一个,后面几个都是类似的。