二叉树

二叉树的基本概念

一、二叉树的概念:一棵二叉树是节点的一个有限集合,该集合或者为空,或者由一个根节点加上两棵左子树和右子树组成

二、二叉树的特点:

1、每个节点最多有两棵子树,即二叉树不存在度大于2的节点

2、二叉树的子树有左右之分,其子树的次序不能颠倒

三、二叉树的形式:

四、满二叉树:在一棵二叉树中,所有分支节点都存在左子树和右子树,并且所有的叶节点都在同一层上

五、完全二叉树:如果一棵具有N个节点的二叉树的结构与满二叉树的前N个节点的结构相同

六、二叉树的性质:

1、若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有2i-1个节点

2、若规定只有根节点的二叉树的深度为1,则深度为k的二叉树的最大节点数是2k-1

3、对任何一棵二叉树,如果其叶子节点个数为n0,度为2的非叶子节点个数为n2,则n0=n2+1

4、具有n个节点的完全二叉树的深度k为log2(n+1)向上取整

5、对于具有n个节点的完全二叉树,如果按照从上至下从左至右的顺序对所有结点从0开始编号,则对于序号为i的节点有:

(1)如果i>=0,则序号为i节点的双亲结点的序号为(i-1)/2;如果i=0,则序号i节点无双亲结点

(2)如果2i+1<n,则序号i结点的左孩子的序号为2i+1,右孩子的序号为2i+2;如果2i+1>=n,则序号i节点无孩子节点

七、存储结构

1、顺序存储

优点:存储完全二叉树,简单省空间

缺点:对一般二叉树尤其单支树,存储空间利用不理想

2、链式存储

3、仿真指针存储

二叉树的实现

#include<iostream>
using namespace std;
#include<queue>
#include<stack>
#include<stdlib.h>
template<class T>
struct BinTreeNode
{
BinTreeNode(const T& data)
:_pleft(NULL)
, _pright(NULL)
, _data(data)
{}
BinTreeNode<T>* _pleft;
BinTreeNode<T>* _pright;
T _data;
};
template <class T>
class BinTree
{
typedef BinTreeNode<T>* pNode;
typedef BinTreeNode<T> Node;
public:
BinTree()
:root(NULL)
{}
//创建二叉树用前序
BinTree(const T* array, size_t size, const T&invalid)//构造函数
{
size_t index = 0;
CreateBinTree(root, array, size, index, invalid);
}
BinTree(const BinTree<T>& bt)//拷贝构造
{
root = CopyBinTree(bt.root);
}
BinTree<T>& operator=(const BinTree<T>& bt)//赋值运算符重载
{
if (this != &bt)
{
root = CopyBinTree(bt.root);
}
return *this;
}
//销毁要用后序遍历
void Destroy(pNode root)
{
if (NULL == root)
return;
Destroy(root->_pleft);
Destroy(root->_pright);
delete[] root;
root = NULL;
}
~BinTree()//析构
{
Destroy(root);
}
void PreOrder()
{
_PreOrder(root);
}
void InOrder()
{
_InOrder(root);
}
void PostOrder()
{
_PostOrder(root);
}
void LevelOrder()
{
_LevelOrder(root);
}
size_t Size()
{
return _Size(root);
}
size_t KSize(size_t k)
{
return _KSize(root, k);
}
size_t leaf()
{
return _leaf(root);
}
size_t Height()
{
return _Height(root);
}
pNode Find(const T& d)
{
   return _Find(root, d);
}
pNode parent(pNode node)
{
return _parent(root, node);
}
pNode leftchild(pNode node)
{
return _leftchild(root, node);
}
pNode rightchild(pNode node)
{
return _rightchild(root, node);
}
private:
void CreateBinTree(pNode& root, const T* array, size_t size, size_t& index, const T&invalid)
{
if (index < size && invalid != array[index])
{
//根节点
pNode newNode = new Node(array[index]);
CreateBinTree(newNode->_pleft, array, size, ++index, invalid);
CreateBinTree(newNode->_pright, array, size, ++index, invalid);
root = newNode;
}
}
pNode CopyBinTree(pNode root)
{
pNode newroot = NULL;
if (root)
{
newroot = new Node(root->_data);//根节点
if (root->_pleft)
{
newroot->_pleft = CopyBinTree(root->_pleft);//左子树
}
if (root->_pright)
{
newroot->_pright = CopyBinTree(root->_pright);//右子树
}
}
return newroot;
}
void _PreOrder(pNode& root)//递归前序遍历(根节点+左子树+右子树)
{
if (root)
{
cout << root->_data << " ";
_PreOrder(root->_pleft);
_PreOrder(root->_pright);
}
}
void _InOrder(pNode& root)//递归中序遍历(左子树+根节点+右子树)
{
if (root)
{
_InOrder(root->_pleft);
cout << root->_data << " ";
_InOrder(root->_pright);
}
}
void _PostOrder(pNode& root)//递归后序遍历(左子树+右子树+根节点)
{
if (root)
{
_PostOrder(root->_pleft);
_PostOrder(root->_pright);
cout << root->_data << " ";
}
}
void _LevelOrder(pNode& root)//层次遍历
{
queue<pNode> q;
if (root)
q.push(root);
while (!q.empty())
{
pNode pCur = q.front();
q.pop();
cout << pCur->_data << " ";
if (pCur->_pleft)
q.push(pCur->_pleft);
if (pCur->_pright)
q.push(pCur->_pright);
}
cout << endl;
}
size_t _Size(pNode root)//节点的个数(用递归)
{
if (NULL == root)
return 0;
return _Size(root->_pleft) + _Size(root->_pright) + 1;
}
size_t _KSize(pNode root, size_t k)//返回k层的节点的个数
{
if (NULL == root)
return 0;
if (k == 1)
return 1;
return _KSize(root->_pleft, k - 1) + _KSize(root->_pright, k - 1);
}
size_t _leaf(pNode root)//叶子节点的个数
{
if (NULL == root)
return 0;
if (NULL == root->_pleft && NULL == root->_pright)
return 1;
return _leaf(root->_pleft) + _leaf(root->_pright);
}
size_t _Height(pNode root)//二叉树的高度
{
if (NULL == root)
return 0;
if (NULL == root->_pleft && NULL == root->_pright)
return 1;
return _Height(root->_pleft) > _Height(root->_pright)?_Height(root->_pleft) + 1 : _Height(root->_pright) + 1;
}
pNode _Find(pNode root, const T& d)//判断一个节点是否在二叉树中
{
if (root)
{
if (root->_data == d)
return root;
else
{
_Find(root->_pleft, d);
_Find(root->_pright, d);
}
}
}
pNode _parent(pNode root, pNode node)//找父母节点
{
if (NULL == root  || node == NULL || root == node)
return NULL;
if (node == root->_pleft || node == root->_pright)
return root;
if (root->_pleft)
return _parent(root->_pleft, node);
return _parent(root->_pright, node);
}
pNode _leftchild(pNode root, pNode node)//找左孩子
{
if (root == NULL || node == NULL)
return NULL;
if (root == node)
{
if (root->_pleft)
return root->_pleft;
return NULL;
}
if (root->_pleft)
_leftchild(root->_pleft, node);
if (root->_pright)
_leftchild(root->_pright, node);


}
pNode _rightchild(pNode root, pNode node)//找右孩子
{
if (root == NULL || node == NULL)
return NULL;
if (root == node)
{
if (root->_pright )
return root->_pright;
return NULL;
}
if (root->_pleft)
_rightchild(root->_pleft, node);
if (root->_pright)
_rightchild(root->_pright, node);
}
private:
pNode root;
};
void Test()
{
char pStr[] = { 'A','B','D','#','#','#','C','E','#','#','F' };
BinTree<char> bt1(pStr, sizeof(pStr)/sizeof(pStr[0]), '#');

cout << "递归前序遍历:" << endl;
bt1.PreOrder();
cout << endl;
cout << "递归中序遍历:" << endl;
bt1.InOrder();
cout << endl;
cout << "递归后序遍历:" << endl;
bt1.PostOrder();
cout << endl;
cout << "层次遍历:" << endl;
bt1.LevelOrder();


cout << "二叉树中节点的个数:" << bt1.Size() << endl;
cout << "叶子节点的个数:" << bt1.leaf() << endl;
cout << "二叉树的高度:" << bt1.Height() << endl;
cout << "二叉树第3层节点的个数:" << bt1.KSize(3) << endl;


BinTree<char> bt2(bt1);
bt2.PreOrder();
cout << endl;


BinTree<char> bt3;
bt3 = bt2;
bt3.PreOrder();
cout << endl;
 
BinTreeNode<char>* ret = bt1.Find('B');
BinTreeNode<char>* ret1 = bt1.parent(ret);
BinTreeNode<char>* ret2 = bt1.leftchild(ret);
BinTreeNode<char>* ret3 = bt1.rightchild(ret);
}
int main()
{
Test();
system("pause");
return 0;
}

 

  • 9
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值