一,概念
二叉树就是一颗特殊的树,二叉树每个结点最多有两个孩子结点,即就是左孩子和右孩子。
接下来我们将以此树为例来进行分析!
表示
(1)数组表示
当二叉树的大小和形态不发生剧烈变化时,用一组连续的存储单元存储二叉树的数据元素,为反应各结点在二叉树中的位置及相互关系,须适当安排各结点的存储次序。
假若一个子结点的下标为i,那仫它的父节点的下标为:(i-1)/2;
假若一个父结点的下标为i,那仫它的左孩子的下标为:2*i+1,它的右孩子的下标为:2*i+2.
缺点:如果不是满二叉树和完全二叉树则有太多的内存浪费,且插入删除不便.
用数组表示一个树适用于满二叉树和完全二叉树.
(2)链式存储表示
在一棵树中进行插入和删除时,为反应结点层次的变动,可能需要移动许多节点,常用的是二叉链表,每一个结点至少包括数据data,左孩子leftchild和右孩子rightchild。
分类
(1)满二叉树:所有叶子节点在同一层,通俗点说就是每一层都是满的 (2)完全二叉树局:n-1层是满的
图示:
二,基本实现
(1)定义一个二叉树节点
template <class T>//定义一个二叉树节点
struct BinaryTreeNode
{
BinaryTreeNode<T>* _left;
BinaryTreeNode<T>* _right;
T _data;
BinaryTreeNode(const T& x)
:_left(NULL)
,_right(NULL)
,_data(x)
{}
};
(2)构造二叉树
BinaryTree()
:_root(NULL)
{}
BinaryTree(T* a,size_t n,const T& invalid)
{
size_t index = 0;
_root = CreateTree(a,n,invalid,index);
}
BinaryTree(const BinaryTree<T>& t)
{
_root = _Copy(t._root);
}
BinaryTree<T>& operator=(const BinaryTree<T> t)
{
if(this != %t)
{
swap(t._root,_root)
}
}
递归调用过程图:
(3)前序遍历
先访问根结点,再递归访问左子树,最后访问右子树
void _PrevOrder(Node* root)
{
if(root==NULL)
{
return;
}
cout<<root->_data<<" ";
_PrevOrder(root->_left);
_PrevOrder(root->_right);
}
(4)中序遍历
先访问左子树,再访问根结点,最后访问右子树.
void _InOrder(Node* root)
{
if(root==NULL)
{
return;
}
_InOrder(root->_left);
cout<<root->_data<<" ";
_InOrder(root->_right);
}
(5)后序遍历
先访问左子树,再访问右子树,最后访问根结点.
void _PosOrder(Node* root)
{
if(root==NULL)
{
return;
}
_PosOrder(root->_left);
_PosOrder(root->_right);
cout<<root->_data<<" ";
}
(6)层序遍历(广度优先遍历)
一层层结点依次遍历,在实现层序遍历的时候用到了队列先进先出的性质,将每一层的数据一次进队列,而每次出队列的元素就是层序遍历的当前元素.
void _LevelOrder (Node* root)
{
queue<Node*> q;
if(root!=NULL)
{
q.push(root);
while(!q.empty())
{
Node* front = q.front();
cout<<front->_data<<" ";
q.pop();
if(front->_left)
{
q.push(front->_left);
}
if(front->_right)
{
q.push(front->_right);
}
}
}
}
在这里用到了队列,先压入根节点,依据父节点出队列,子节点进队列原则,然后依次访问对头元素求得层序遍历顺序
(7)叶子节点个数
叶子节点(即没有左子树也没有右子树),左子树的叶子节点总数+右子树的叶子节点总数.
size_t _LeafSize(Node* root)
{
if(root==NULL)
{
return 0;
}
if(root->_left==NULL&&root->_right==NULL)
{
return 1;
}
size_t i = _LeafSize(root->_left);
size_t j = _LeafSize(root->_right);
return i+j;
}
(8)第k层节点数
size_t _GetKLevel(Node* root,size_t k)
{
if(root == NULL)
{
return 0;
}
if(k == 1)
{
return 1;
}
return _GetKLevel(root->_left,k-1)+(root->_right,k-1);
}
三,完整代码
using namespace std;
template <class T>//定义一个二叉树节点
struct BinaryTreeNode
{
BinaryTreeNode<T>* _left;
BinaryTreeNode<T>* _right;
T _data;
BinaryTreeNode(const T& x)
:_left(NULL)
,_right(NULL)
,_data(x)
{}
};
template <class T>
class BinaryTree
{
typedef BinaryTreeNode<T> Node;
public:
BinaryTree()
:_root(NULL)
{}
BinaryTree(T* a,size_t n,const T& invalid)
{
size_t index = 0;
_root = CreateTree(a,n,invalid,index);
}
BinaryTree(const BinaryTree<T>& t)
{
_root = _Copy(t._root);
}
BinaryTree<T>& operator=(const BinaryTree<T> t)
{
if(this != %t)
{
swap(t._root,_root)
}
}
void PrevOrder()//前序遍历
{
return _PrevOrder(_root);
}
void InOrder()//中序遍历
{
return _InOrder(_root);
}
void PosOrder()//后续遍历
{
return _PosOrder(_root);
}
void LevelOrder()//层序遍历
{
return _LevelOrder(_root);
}
size_t Size()//大小
{
return _Size(_root);
}
Node* find(const T&x)//查找一个节点
{
return _find(_root,x);
}
size_t Depth()//求深度
{
return _Depth(_root);
}
size_t LeafSize()
{
return _LeafSize(_root);
}
size_t GetKLevel(size_t k)
{
return _GetKLevel(_root,k);
}
protected:
//成员函数
Node* _find(Node* root,const T& x)
{
if(root==NULL)
{
return NULL;
}
if(root->_data == x)
{
return root;
}
Node* ret=_find(root->_left,x);
if(ret)
{
return ret;
}
return _find(root->_right,x);
}
size_t _LeafSize(Node* root)
{
if(root==NULL)
{
return 0;
}
if(root->_left==NULL&&root->_right==NULL)
{
return 1;
}
size_t i = _LeafSize(root->_left);
size_t j = _LeafSize(root->_right);
return i+j;
}
size_t _GetKLevel(Node* root,size_t k)
{
if(root == NULL)
{
return 0;
}
if(k == 1)
{
return 1;
}
return _GetKLevel(root->_left,k-1)+(root->_right,k-1);
}
size_t _Size(Node* root)
{
if(root==NULL)
{
return 0 ;
}
size_t i =_Size(root->_left);
size_t j =_Size(root->_right);
return i+j+1;
}
void _LevelOrder (Node* root)
{
queue<Node*> q;
if(root!=NULL)
{
q.push(root);
while(!q.empty())
{
Node* front = q.front();
cout<<front->_data<<" ";
q.pop();
if(front->_left)
{
q.push(front->_left);
}
if(front->_right)
{
q.push(front->_right);
}
}
}
}
size_t _Depth(Node* root)
{
if(root==NULL)
{
return 0;
}
else
{
size_t i = _Depth(root->_left);
size_t j = _Depth(root->_right);
if(i>j)
{
return i+1;
}
else
{
return j+1;
}
}
}
//前序遍历
void _PrevOrder(Node* root)
{
if(root==NULL)
{
return;
}
cout<<root->_data<<" ";
_PrevOrder(root->_left);
_PrevOrder(root->_right);
}
//中序遍历
void _InOrder(Node* root)
{
if(root==NULL)
{
return;
}
_InOrder(root->_left);
cout<<root->_data<<" ";
_InOrder(root->_right);
}
//后序遍历
void _PosOrder(Node* root)
{
if(root==NULL)
{
return;
}
_PosOrder(root->_left);
_PosOrder(root->_right);
cout<<root->_data<<" ";
}
Node* _Copy(Node* root)
{
if(root==NULL)
{
return NULL;
}
Node* newroot = new Node(root->_data);
newroot->_left = _Copy(root->_left);
newroot->_right = _Copy(root->_right);
return newroot;
}
//构建二叉树
Node* CreateTree(T* 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;
}
protected:
Node* _root;
size_t index;
size_t invalid;
};
int main()
{
int a1[10] = {1, 2, 3, '#', '#', 4, '#' , '#', 5, 6};
BinaryTree<int>t1(a1,sizeof(a1)/sizeof(a1[0]),'#');
//t1.PosOrder();
//cout<<endl;
//cout<<t1.Size()<<" ";
//cout<<t1.LeafSize();
//cout<<t1.GetKLevel(2);
t1.LevelOrder();
//cout<<(t1.find(3));
//cout<<t1.Depth();
return 0;
}