数据结构之二叉树的递归实现

  二叉树的概念篇>

 (1).二叉树是一颗特殊的树,二叉树每个结点最多有两个孩子结点,即就是左孩子和右孩子

 (2).满二叉树:若一颗树的高度为h,则h层均满

 (3).完全二叉树:若一棵树的高度为h,则前h-1层均满最后一层可以不满,且最后一层的结点都连续集中在最左边.

    我们知道一个数组可以表示一颗树,它的思想是如果该处有结点则直接将该结点放在对应的下标处,如果没有结点则以符号占位 .

    (1).假若一个子结点的下标为i,那仫它的父节点的下标为:(i-1)/2;

    (2).假若一个父结点的下标为i,那仫它的左孩子的下标为:2*i+1,它的右孩子的下标为:2*i+2.

    (3).缺点:如果不是满二叉树和完全二叉树则有太多的内存浪费,且插入删除不便.

    用数组表示一个树适用于满二叉树和完全二叉树.

  实例分析篇>

      如果一个数组表示的二叉树:int array[]={1,2,'#',3,'#','#',4,5,'#',6,'#',7,'#','#',8},'#'代表该位置没有结点,该树被还原之后为:

      

     递归求一个树的前序遍历,中序遍历,后序遍历,层序遍历,树的叶子节点的数量,树的总结点的数量,树的深度,统计每一层的结点总数.

     (1).前序遍历:先访问根结点,再递归访问左子树,最后访问右子树.

     (2).中序遍历:先访问左子树,再访问根结点,最后访问右子树.

     (3).后序遍历:先访问左子树,再访问右子树,最后访问根结点.

     (4).层序遍历:一层层结点依次遍历,在实现层序遍历的时候用到了队列先进先出的性质,将每一层的数据一次进队列,而每次出队列的元素就是层序遍历的当前元素.

     (5).树的总结点数:根结点+左子树的结点数+右子树的结点数.

     (6).树的叶子节点数:叶子节点(即没有左子树也没有右子树),左子树的叶子节点总数+右子树的叶子节点总数.

 代码实现>,

     BinaryTree.h

        

#pragma once

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

template<typename T>
class BinaryTree
{
	typedef BinaryTreeNode<T> Node;
public:
	BinaryTree()
		:_root(NULL)
	{}
	BinaryTree(const T *array,size_t size,const T& invalid)
	{
		size_t index=0;
		_root=_CreatTree(array,size,index,invalid);
	}
	BinaryTree(const BinaryTree<T>& bt)
	{
		_root=_Copy(bt._root);
	}
	//BinaryTree<T>& operator=(const BinaryTree<T>& bt)
	//{
	//	//传统的写法
	//	if (this != &bt)
	//	{
	//		Node *root=_Copy(bt._root);
	//		_Destroy(_root);
	//		_root=root;
	//	}
	//	return *this;
	//}
	BinaryTree<T>& operator=(const BinaryTree<T>& bt)
	{
		//现代的写法
		if (this != &bt)   //防止自赋值
		{
			BinaryTree<T> tmp(bt);
			std::swap(_root,tmp._root);
		}
		return *this;
	}
	~BinaryTree()
	{
		_Destroy(_root);
	}
public:
	void PrevOrder()   //前序遍历
	{
		_PrevOrder(_root);
		cout<<endl;
	}
	void InOrder()     //中序遍历
	{
		_InOrder(_root);
		cout<<endl;
	}
	void PostOrder()   //后序遍历
	{
		_PostOrder(_root);
		cout<<endl;
	}
	void LevelOrder()   //层序遍历
	{
		_LevelOrder(_root);
		cout<<endl;
	}
	size_t Size()       //求该树的总结点数
	{
		size_t size=_Size(_root);
		return size;
	}
	size_t Depth()     //求该树的深度
	{
		size_t depth=_Depth(_root);
		return depth;
	}
	size_t LeafSize()   //求一个树叶子节点的总数
	{
		size_t leaf=_LeafSize(_root);
		return leaf;
	}
	size_t GetKLevel(int level)   //level层的所有节点的个数
	{
		size_t count=_GetKLevel(_root,level);
		return count;
	}
protected:
	Node *_CreatTree(const T *array,size_t size,size_t& index,const T& invalid)
	{
		assert(array);
		Node *root=NULL;
		if (index < size && array[index] != invalid)
		{
			root=new Node(array[index]);
			root->_left=_CreatTree(array,size,++index,invalid);
			root->_right=_CreatTree(array,size,++index,invalid);
		}
		return root;
	}
	Node *_Copy(Node *root)
	{
		//proot是拷贝的新树的根节点
		Node *cur=root;
		Node *proot=NULL;
		if (cur)
		{
			proot=new Node(cur->_data);
			proot->_left=_Copy(cur->_left);
			proot->_right=_Copy(cur->_right);
		}
		return proot;
	}
	void _Destroy(Node *root)
	{
		Node *cur=root;
		if (cur)
		{
			_Destroy(cur->_left);
			_Destroy(cur->_right);
			delete cur;
			cur=NULL;
		}
	}
protected:
	void _PrevOrder(Node *root)
	{
		Node *cur=root;
		if (cur)
		{
			cout<<cur->_data<<" ";
			_PrevOrder(root->_left);
			_PrevOrder(root->_right);
		}
	}
	void _InOrder(Node *root)
	{
		Node *cur=root;
		if (cur)
		{
			_InOrder(cur->_left);
			cout<<cur->_data<<" ";
			_InOrder(cur->_right);
		}
	}
	void _PostOrder(Node *root)
	{
		Node *cur=root;
		if (cur)
		{
			_PostOrder(cur->_left);
			_PostOrder(cur->_right);
			cout<<cur->_data<<" ";
		}
	}
	void _LevelOrder(Node *root)
	{
		queue<Node *> q;
		Node *cur=root;
		q.push(cur);
		while(!q.empty())
		{
			Node *t=q.front();
			cout<<t->_data<<" ";
			if (t->_left != NULL)
			{
				q.push(t->_left);
			}
			if (t->_right != NULL)
			{
				q.push(t->_right);
			}
			q.pop();
		}
	}
	size_t _Size(Node *root)
	{
		if (root == NULL)
		{
			return 0;     //空树
		}
		return 1+_Size(root->_left)+_Size(root->_right);
	}
	size_t _Depth(Node *root)
	{
		Node *cur=root;
		if (root == NULL)
		{
			return 0;
		}
		return 1+(_Depth(cur->_left)>_Depth(cur->_right)
			?_Depth(cur->_left):_Depth(cur->_right));
	}
	size_t _LeafSize(Node *root)
	{
		Node *cur=root;
		if (cur == NULL)   //空树
		{
			return 0;
		}
		else if ((cur->_left == NULL) && (cur->_right == NULL))
		{
			//叶子结点--一个结点即没有左子树也没有右子树
			return 1;
		}
		else
			return _LeafSize(cur->_left)+_LeafSize(cur->_right);
	}
	size_t _GetKLevel(Node *root,int level)
	{
		size_t count=0;
		if (root == NULL)
		{
			return 0;
		}
		if (level == 1)
		{
			count++;
		}
		else
		{
			count += _GetKLevel(root->_left,level-1);
			count += _GetKLevel(root->_right,level-1);
		}
		return count;
	}
protected:
	Node *_root;
};


 

 

     test.cpp

      

void testBinaryTree()
{
	int array[]={1,2,'#',3,'#','#',4,5,'#',6,'#',7,'#','#',8};
	size_t sz=sizeof(array)/sizeof(array[0]);
	BinaryTree<int> bt(array,sz,'#');

	bt.PrevOrder();   //1 2 3 4 5 6 7 8
	bt.InOrder();     //2 3 1 5 6 7 4 8
	bt.PostOrder();   //3 2 7 6 5 8 4 1
	bt.LevelOrder();  //1 2 4 3 5 8 6 7 
	cout<<bt.Size()<<endl;    //8
	cout<<bt.Depth()<<endl;   //5

	BinaryTree<int> bt1(bt);
	bt1.PrevOrder();
	bt1.InOrder();
	bt1.PostOrder();
	bt1.LevelOrder();
	cout<<bt1.Size()<<endl;    //8
	cout<<bt1.Depth()<<endl;   //5

	BinaryTree<int> bt2;
	bt2=bt;
	bt2.PrevOrder();
	bt2.InOrder();
	bt2.PostOrder();
	bt2.LevelOrder();
	cout<<bt2.Size()<<endl;     //8
	cout<<bt2.Depth()<<endl;    //5
	cout<<bt2.LeafSize()<<endl; //3  
	//该树的每一层共有多少个结点
	cout<<bt2.GetKLevel(1)<<endl;;  //1
	cout<<bt2.GetKLevel(2)<<endl;;  //2
	cout<<bt2.GetKLevel(3)<<endl;;  //3
	cout<<bt2.GetKLevel(4)<<endl;;  //1
	cout<<bt2.GetKLevel(5)<<endl;;  //1
}


 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值