二叉树以及 二叉树的C++实现

二叉树是一种树型结构,特点是每个节点之多有两个子树(即而产生和中不存在度大于2的节点),并且,二叉树的子树有左右之分(左边的称“左子树” , 右边的称 “右子树 ”) ,其次序不能任意颠倒。



二叉树常用于二叉查找树和二叉堆。

下面给出二叉树的基本形态


几种特殊的二叉树

1. 斜树

所有结点都只有左子树的二叉树叫左斜树,所有结点都只有右子树的二叉树叫右斜树。斜树的每一层都只有一个结点,结点的个数与斜树的深度相同。


2. 满二叉树

在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子结点都在同一层上,这样的二叉树称为满二叉树。(上图中所示的二叉树,就是一棵满二叉树)

3. 完全二叉树

对一棵具有n个结点的二叉树按层序编号,如果编号为i(1≤i≤n)的结点与同样深度的满二叉树中的编号为i的结点在二叉树中的位置完全相同,则这棵二叉树称为完全二叉树。




二叉树的性质

性质1   在二叉树的第i层上,至多有 2i-1 个节点(根节点的层数为1 )

性质2   深度为k的二叉树至多有  2k-1个节点(k >=1)

性质3   一棵二叉树的叶子结点数为n0,度为2的结点数为n2,则n0 = n2 + 1

性质4    具有n个结点的完全二叉树的深度为floor(log2n) + 1 

性质5    如果对一棵有n个结点的完全二叉树(其深度为floor(log2n) + 1 )的结点按层序编号,则对任一结点i(1≤i≤n)有:
(1) 如果i = 1,则结点i是二叉树的根,无双亲;如果i > 1,则其双亲PARENT(i)是结点 floor((i)/2)
(2)如果2i > n,则结点i无左孩子;否则其左孩子LCHILD(i)是结点2i
(3)如果2i + 1 > n,则结点i无右孩子;否则其右孩子RCHILD(i)是结点2i + 1

二叉树的存储

 1、顺序存储结构

     二叉树可以用数组或线性表来存储,而且如果是完全二叉树,那么这种方法不会浪费空间


#define LENGTH 100
typedef char datatype;
typedef struct node{
    datatype data;
    int lchild,rchild;
    int parent;
}Node;

Node tree[LENGTH];
int length;
int root;



并且这种紧凑排列,如果一个结点的索引为i,则它的子结点能在索引2i+1和2i+2找到,并且它的父节点(如果有)能在索引floor((i-1)/2)找到(假设根节点的索引为0)。

对于一般的二叉树,其层序编号不能反映出逻辑关系,但是可以将其按照完全二叉树编号,只不过把不存在的结点设置为NULL即可。但这么做有一个问题,就是会浪费存储空间。最坏情况下,一个深度为k的斜树(只有k个结点),却需要长度为2k-1的一维数组。所以顺序存储结构一般只用于完全二叉树。

2、链式存储结构

每个结点含有一个数据域和两个指针域(分别指向左右子树)。


二叉树的节点表示

struct BinaryTreeNode
{
	char _data;
	struct BinaryTreeNode*  pLeft;
        struct BinaryTreeNode* pRight;
};

利用这种结点结构所得的二叉树存储结构称之为二叉链表。在二叉链表中,如果想找到某个结点的双亲,需要从根节点开始遍历,所以有时为了便于找到结点的双亲,还可以在结点结构中增加一个指向其双亲结点的指针域,相应的二叉树存储结构称之为三叉链表。


二叉树基本实现


//二叉树 节点结构
template<class T>
struct BinaryTreeNode
{
	typedef BinaryTreeNode<T>*  Treepoint ;
	BinaryTreeNode(const T& data)
		:_data(data)
		, pLeft(NULL)
		, pRight(NULL)
	{}
	T _data;
	Treepoint pLeft;
	Treepoint pRight;
};
//二叉树的基本操作
template<class T>
class BinaryTree
{
public:

	BinaryTree()
		:_pRoot(NULL)
	{}

	BinaryTree(T arr[], size_t sz)
	{
		size_t index = 0;
		_CreatNode(_pRoot, arr, sz, index);
	}

	BinaryTree(const BinaryTree<T>& t)//拷贝构造
	{
		_pRoot = _CopyTree(t._pRoot);
	}

	BinaryTreeNode<T>& operator=(const BinaryTree<T>& t) //赋值运算符重载
	{
		if (this != &t)
		{
			_Destroy(this->_pRoot);
			this->_pRoot = _CopyTree(t._pRoot);
		}
		return *this;
	}

	~BinaryTree() //析构函数
	{
		if (this != NULL)
		{
			_Destroy(this->_pRoot);
		}
	}
private:
	BinaryTreeNode<T>* _pRoot;

protected:

	void _CreatNode(BinaryTreeNode<T>*& Root, T arr[], size_t sz, size_t& index)//创建
	{                              //传的是引用                        //引用
		if (index < sz && arr[index] != '?')
		{
			//前序遍历 :创建过程  根-左-右
			Root = new BinaryTreeNode<T>(arr[index]);
			_CreatNode(Root->pLeft, arr, sz, ++index);
			_CreatNode(Root->pRight, arr, sz, ++index);
		}
	}
	BinaryTreeNode<T>* _CopyTree(const BinaryTreeNode<T>* Root) //拷贝
	{
		BinaryTreeNode<T>* NewRoot = NULL;
		if (Root != NULL)
		{
			NewRoot = new BinaryTreeNode<T>(Root->_data);
			NewRoot->pLeft = _CopyTree(Root->pLeft);
			NewRoot->pRight = _CopyTree(Root->pRight);
		}
		return NewRoot;
	}

	void _Destroy(BinaryTreeNode<T>*& Root) //删除顺序 左-右-根
	{
		if (Root != NULL)
		{
			_Destroy(Root->pLeft);
			_Destroy(Root->pRight);
			//	_Destroy(Root);
			delete Root;
			Root = NULL;

		}
	}
};







  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值