二叉树
一:树
树是N个有限个数的集合,形状像一颗到过来的树。如下:
树是一种特殊的数据结构有点像链表,每个节点都包括指针域和一个数据域。
根节点:树的第一个节点;
节点的度:树拥有子节点的个数;
叶节点:没有子节点的节点;
树的高度:树中距离根节点最远的路径长度。
父子节点:一个节点father指向另外一个节点child,father这个节点就是父节点,child这个节点就是子节点。
二:二叉树
二叉树: 二叉树是一种特殊的树,在二叉树中每个节点最多有两个子节点,一般称为左子节点和右子节点(或左孩子和右孩子),并且二叉树的子树有左右之分,其次序不能任意颠倒。
构建一个树的结构,里面包括数据,左子树,右子树。二叉树是一种的典型的递归结构。递归要掌握两个条件(1:子问题,2:递归出口)。
定义一个简单的二叉树的结构:
struct BinaryTreeNode
{
T _data;//数据
BinaryTreeNode<T>* _left;//左子树
BinaryTreeNode<T>* _right;//右子树
BinaryTreeNode(const T&x =T())
:_data(x)
, _left(NULL)
, _right(NULL)
{}
};
二叉树的简单实现:
1:二叉树的深度;
2:二叉树的节点的个数;
3:二叉树的叶子节点的个数;
4:二叉树第K层节点的个数;
template<class T>
class BinaryTree
{
typedef BinaryTreeNode<T> Node;
public:
BinaryTree()
:_root(NULL)
{}
BinaryTree(const BinaryTree<T> &t)
{
_root = _copy(t._root);
}
BinaryTree<T>&operator = (BinaryTree<T> &t)
{
swap(_root, t._root);
return *this;
}
~BinaryTree()
{
_Destroy(_root);
}
BinaryTree(const T*a, size_t n, const T&invalued = T())
{
size_t indes = 0;
_root = _CreatTree(a, n,indes,invalued);//创建一个二叉树
}
//数节点的个数
size_t Size()
{
return _Size(_root);
}
//深度
size_t Depth()
{
return _Depth(_root);
}
//叶子节点的个数
size_t LeftSize()
{
return _LeftSize(_root);
}
//第k层节点的个数
int GetkLevel(Node *root, int k)
{
if (root == NULL||k<1)
{
return 0;
}
if (k == 1)
{
return 1;
}
int leftGetkLevel = GetkLevel(root->_left, k - 1);
int rightGetkLevel = GetkLevel(root->_right, k - 1);
return (leftGetkLevel + rightGetkLevel);
}
protected:
Node*_CreatTree(const T*a, size_t n, size_t &indes, const T&invalued)
{
assert(a);
Node* root = NULL;
if (indes<n && a[indes] != invalued)
{
root = new Node(a[indes]);//创建根节点
root->_left = _CreatTree(a, n,++indes,invalued);
root->_right= _CreatTree(a, n,++indes,invalued);
}
return root;
}
//拷贝
Node *_copy(Node *node)
{
Node*cur = node;
Node root = NULL;//
if (cur)
{
root = new Node(cur->_data);//创建新节点
root->_left = _copy(cur->_left);//递归调用
root->_right = _copy(cur->_right);//递归调用
}
return root;
}
//删除
void _Destroy(Node *node)
{
Node* del = node;
if (del)
{
_Destroy(del->_left);
_Destroy(del->_right);
delete del;
del = NULL;
}
}
//树节点的个数
size_t _Size(Node *root)
{
if (root == NULL)
{
return 0;
}
return _Size(root->_left) + _Size(root->_right) + 1;
}
//深度
size_t _Depth(Node *root)
{
Node *cur = root;
if (cur == NULL)
{
return 0;
}
//比较左子树和右子树的大小
return 1 + (_Depth(cur->_left) > _Depth(cur->_right)
? _Depth(cur->_left) : _Depth(cur->_right));
}
//叶子节点的个数
size_t _LeftSize(Node *root)
{
Node*cur = root;
if (NULL == cur)//空树
{
return 0;
}
if (cur->_left == NULL&&cur->_right == NULL)//只有根节点
{
return 1;
}
return _LeftSize(cur->_left)+_LeftSize(cur->_right);//左子树与右子树的和
}
protected:
Node *_root;
};
void TestBinaryTree()
{
int a1[10] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6 };
size_t sz = sizeof(a1) / sizeof(a1[0]);
BinaryTree<int> t(a1, sz, '#');
}
小结:
二叉树的是一种特殊的数据结构,可以通过递归来访问节点的数据域和子树的节点。假设每一次遍历都是从根节点开始,先遍历左子树,这时会生成函数栈帧,当左子树的下一个左子树为空,返回上一级,此时函数栈帧销毁,一直回退到根节点,然后遍历右子树,当右子树的下一个左子树为空测遍历结束。