二叉树的创建与相关操作

二叉树的创建与相关操作

1、二叉树:是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。

如图:

 

2、二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。

3、二叉树的第i层至多有2^(i-1)个结点;深度为k的二叉树至多有2^k-1个结点;对任何一棵二叉树T,如果其终端结点数为n0,度为2的结点数为n2,则n0=n2+1。

4、一棵深度为k,且有2^k-1个节点称之为满二叉树(如上图);深度为k,有n个节点的二叉树,当且仅当其每一个节点都与深度为k的满二叉树中,序号为1至n的节点对应时,称之为完全二叉树

如下图:



一、创建二叉树


假设我们要创建一个二叉树:

对应数组为:char array[] = "abc##d##ef##g";

这是因为以下程序中设置无效值为‘#’,在递归的过程中,遇到无效值则置为NULL。

代码如下:

// 根+左子树+右子树 
	PNode _CreateBinTree(const T* array, size_t size, size_t& index, const T& invalid)
	{
		if (NULL == array)
			return 0;
		PNode root = NULL;
		if (index < size && array[index] != invalid)
		{
			root = new Node(array[index]);
			root->_left = _CreateBinTree( array, size, ++index, invalid);
			root->_right = _CreateBinTree( array, size, ++index, invalid);
		}
		return root;
	}

在判断语句中,最好将index<size放在前面,因为当越界后根本不需要判断是否为有效值。

二、前中后遍历二叉树

前序遍历:首先访问根,再遍历左子树,最后遍历右子树

// 根--->根的左子树---->根的右子树
	void _PreOrder(PNode& pRoot)
	{
		if (pRoot == NULL)
			return;
		cout << pRoot->_data << " ";
		_PreOrder(pRoot->_left);
		_PreOrder(pRoot->_right);
	}

中序遍历:首先遍历左子树,再访问根,最后遍历右子树。

// 左子树--->根节点--->右子树 
	void _InOrder(PNode pRoot)
	{
		//pNode pCur = pRoot;
		if (pRoot == NULL)
			return;
		_InOrder(pRoot->_left);
		cout << pRoot->_data << " ";
		_InOrder(pRoot->_right);
	}

后序遍历:首先遍历左子树,再遍历右子树,最后访问根。

// 左子树--->右子树--->根节点 
	void _PostOrder(PNode pRoot)
	{
		if (pRoot == NULL)
			return;
		_PostOrder(pRoot->_left);
		_PostOrder(pRoot->_right);
		cout << pRoot->_data << " ";	
	}

三、层序遍历二叉树

按照层次访问,访问根,访问子女,再访问子女的子女。

这里递归很难实现,我们利用了队列的特性,创建一个队列,先将根节点入队,将队头的数据打印并出队,再看左右节点,如果左节点不为空,将左节点入队,如果右节点不为空,将右节点入队。

代码如下:

void _LeverOrder(PNode pRoot)
	{
		if (NULL == pRoot)
			return;
		queue<PNode> q;
		q.push(pRoot);
		while (!q.empty())
		{
			PNode front = q.front();
			cout << front->_data << " ";
			q.pop();

			if (front->_left)
				q.push(front->_left);
			if (front->_right)
				q.push(front->_right);
		}
	}

四、求二叉树的高度

先求出左子树的高度,和右子树比较。

size_t _Height(PNode pRoot)
	{
		if (NULL == pRoot)
			return 0;
		return 1+(_Height(pRoot->_left) > _Height(pRoot->_right)?_Height(pRoot->_left): _Height(pRoot->_right));
	}

五、求二叉树中节点的个数

size_t _Size(PNode pRoot)
	{
		if (NULL == pRoot)
			return 0;
		return _Size(pRoot->_left) + _Size(pRoot->_right) + 1;
	}

六、求叶子节点的个数

size_t _GetLeafCount(PNode pRoot)
	{
		if (NULL == pRoot)
			return 0;
		if (pRoot->_left == NULL&&pRoot->_right == NULL)
			return 1;
		return _GetLeafCount(pRoot->_left) + _GetLeafCount(pRoot->_right);
	}

七、求二叉树中第k层节点的个数

size_t _GetKLevelCount(PNode pRoot, int K)
	{
		if (NULL == pRoot || K < 1)
			return 0;
		if (K == 1)
			return 1;
		int leftLevel = _GetKLevelCount(pRoot->_left, K - 1);
		int rightLevel = _GetKLevelCount(pRoot->_right, K - 1);
		return leftLevel + rightLevel;
	}

八、求一个节点的双亲节点,及左、右孩子节点。

PNode _Parent(PNode pRoot, PNode pNode)
	{
		if (pNode == pRoot->_left || pNode == pRoot->_right)
			return pRoot;
		if (pRoot->_left)
		{
			_Parent(pRoot->_left, pNode);
		}
		if (pRoot->_right)
		{
			_Parent(pRoot->_right, pNode);
		}
		return pRoot;
	}

	PNode LeftChild(PNode pNode)
	{
		if (NULL == pNode)
			return NULL;
		return pNode->_left;
	}

	PNode RightChild(PNode pNode)
	{
		if (NULL == pNode)
			return NULL;
		return pNode->_right;
	}


还有一些辅助函数,比如寻找某一元素所在节点。

整体代码如下:

#include<iostream>
using namespace std;
#include<queue>
#include<string.h>

template<class T>
struct TreeNode
{
	T _data;
	TreeNode *_left;
	TreeNode *_right;
	TreeNode(const T& data)
		:_data(data)
		, _left(NULL)
		, _right(NULL)
	{}
};

template<class T>
class BinTree
{
	typedef TreeNode<T> Node;
	typedef TreeNode<T> *PNode;
public:
	BinTree()
		: _pRoot(NULL)
	{}

	BinTree(const T* array, size_t size, const T& invalid)
	{
		size_t index = 0;
		_pRoot = _CreateBinTree(array, size, index, invalid);
	}

	BinTree(const BinTree& bt)
	{
		_pRoot = _CopyBinTree(bt._pRoot);
	}

	BinTree& operator=(const BinTree& bt)
	{
		if (this == bt)
			return;
		_DestroyBinTree(_pRoot);
		_pRoot = new Node(bt->_data);
		_pRoot->_left = bt->_left;
		_pRoot->_right = bt->_right;
	}

	~BinTree()
	{
		_DestroyBinTree(_pRoot);
	}
	void PreOrder()
	{
		_PreOrder(_pRoot);
		cout << endl;
	}

	void InOrder()
	{
		_InOrder(_pRoot);
		cout << endl;
	}

	void PostOrder()
	{
		_PostOrder(_pRoot);
		cout << endl;
	}

	void LevelOrder()
	{
		_LeverOrder(_pRoot);
		cout << endl;
	}

	size_t Size()
	{
		return _Size(_pRoot);
	}

	size_t GetLeafCount()
	{
		return _GetLeafCount(_pRoot);
	}

	// 获取第K层结点的个数 
	size_t GetKLevelCount(size_t K)
	{
		return _GetKLevelCount(_pRoot, K);
	}

	size_t Height()
	{
		return _Height(_pRoot);
	}

	PNode Find(const T& data)
	{
		return _Find(_pRoot, data);
	}

	PNode Parent(PNode pNode)
	{
		return _Parent(_pRoot, pNode);
	}

	PNode LeftChild(PNode pNode)
	{
		if (NULL == pNode)
			return NULL;
		return pNode->_left;
	}

	PNode RightChild(PNode pNode)
	{
		if (NULL == pNode)
			return NULL;
		return pNode->_right;
	}
private:
	// 根+左子树+右子树 
	PNode _CreateBinTree(const T* array, size_t size, size_t& index, const T& invalid)
	{
		if (NULL == array)
			return 0;
		PNode root = NULL;
		if (index < size && array[index] != invalid)
		{
			root = new Node(array[index]);
			root->_left = _CreateBinTree( array, size, ++index, invalid);
			root->_right = _CreateBinTree( array, size, ++index, invalid);
		}
		return root;
	}

	PNode _CopyBinTree(PNode pRoot)
	{
		if (this == pRoot)
			return;
		if (pRoot)
		{
			_pRoot = new Node(pRoot->_data);
			_pRoot->_left = _CopyBinTree(pRoot->_left);
			_pRoot->_right = _CopyBinTree(pRoot->_right);
		}
		return *this;
	}

	void _DestroyBinTree(PNode pRoot)
	{
		if (NULL == pRoot)
			return;
		if (pRoot)
		{
			_Destroy(pRoot->_left);
			_Destroy(pRoot->_right);
			delete pRoot;
			pRoot = NULL;
		}
	}

	// 根--->根的左子树---->根的右子树
	void _PreOrder(PNode& pRoot)
	{
		if (pRoot == NULL)
			return;
		cout << pRoot->_data << " ";
		_PreOrder(pRoot->_left);
		_PreOrder(pRoot->_right);
	}

	// 左子树--->根节点--->右子树 
	void _InOrder(PNode pRoot)
	{
		//pNode pCur = pRoot;
		if (pRoot == NULL)
			return;
		_InOrder(pRoot->_left);
		cout << pRoot->_data << " ";
		_InOrder(pRoot->_right);
	}

	// 左子树--->右子树--->根节点 
	void _PostOrder(PNode pRoot)
	{
		if (pRoot == NULL)
			return;
		_PostOrder(pRoot->_left);
		_PostOrder(pRoot->_right);
		cout << pRoot->_data << " ";	
	}

	//层次遍历
	void _LeverOrder(PNode pRoot)
	{
		if (NULL == pRoot)
			return;
		queue<PNode> q;
		q.push(pRoot);
		while (!q.empty())
		{
			PNode front = q.front();
			cout << front->_data << " ";
			q.pop();

			if (front->_left)
				q.push(front->_left);
			if (front->_right)
				q.push(front->_right);
		}
	}

	size_t _Size(PNode pRoot)
	{
		if (NULL == pRoot)
			return 0;
		return _Size(pRoot->_left) + _Size(pRoot->_right) + 1;
	}

	size_t _GetLeafCount(PNode pRoot)
	{
		if (NULL == pRoot)
			return 0;
		if (pRoot->_left == NULL&&pRoot->_right == NULL)
			return 1;
		return _GetLeafCount(pRoot->_left) + _GetLeafCount(pRoot->_right);
	}

	size_t _Height(PNode pRoot)
	{
		if (NULL == pRoot)
			return 0;
		return 1+(_Height(pRoot->_left) > _Height(pRoot->_right)?_Height(pRoot->_left): _Height(pRoot->_right));
	}

	PNode _Find(PNode pRoot, const T& data)
	{
		if (data == pRoot->_data)
			return pRoot;
		if (pRoot->_left)
		{
			_Find(pRoot->_left, data);
		}
		if (pRoot->_right)
		{
			_Find(pRoot->_right, data);
		}
	}

	PNode _Parent(PNode pRoot, PNode pNode)
	{
		if (pNode == pRoot->_left || pNode == pRoot->_right)
			return pRoot;
		if (pRoot->_left)
		{
			_Parent(pRoot->_left, pNode);
		}
		if (pRoot->_right)
		{
			_Parent(pRoot->_right, pNode);
		}
		return pRoot;
	}

	size_t _GetKLevelCount(PNode pRoot, int K)
	{
		if (NULL == pRoot || K < 1)
			return 0;
		if (K == 1)
			return 1;
		int leftLevel = _GetKLevelCount(pRoot->_left, K - 1);
		int rightLevel = _GetKLevelCount(pRoot->_right, K - 1);
		return leftLevel + rightLevel;
	}

private:
	PNode _pRoot;
};


测试,传文章开头所示的数组,如下:

int main()
{
	char array[] = "abc##d##ef##g";
	BinTree<char> bt(array,strlen(array),'#');

	cout << bt.GetKLevelCount(2) << endl;

	cout << bt.GetLeafCount() << endl;

	cout << bt.Height() << endl;

	bt.PreOrder();
	bt.InOrder();
	bt.PostOrder();
	bt.LevelOrder();

	cout << bt.LeftChild(bt.Find('a'))->_data << endl;
    cout << bt.RightChild(bt.Find('a'))->_data << endl;

	cout << bt.Parent(bt.Find('b'))->_data << endl;

	cout << bt.Size() << endl;

	system("pause");
	return 0;
}

结果如下:


我们来比对看一下结果,正确。


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值