二叉树

二叉树的遍历方式:

前序,中序,后序,层序

二叉树的储存方式:

链式:动态

数组:静态


二叉树的基本操作:构造,拷贝构造,析构,求深度,叶子节点数,第k层节点,前、中、后序,层序


树的节点结构:

template<class T>
struct BinaryTreeNode
{
	BinaryTreeNode<T>* _left;
	BinaryTreeNode<T>* _right;
	T _data; 
	BinaryTreeNode(const T& x)
		:_left(NULL)
		, _right(NULL)
		, _data(x)
	{}
};
 
构造函数:
	BinaryTree( T* a, size_t n, const T& invalid)
	{
		size_t index = 0;
		_root = CreatTree(a, n, invalid, index);
	}

	Node* CreatTree( T* a, size_t n, const T& invalid, size_t& index)
	{
		Node* root = NULL;
		if (index >= n || a[index] == invalid)
		{
			return NULL;
		}
			root = new Node(a[index]);
			root->_left = CreatTree(a, n, invalid, ++index);
			root->_right = CreatTree(a, n, invalid, ++index);
		return root;
	}

拷贝构造函数:

BinaryTree(const BinaryTree& t)
	{
		_root = _Copy(t._root);
	}
	Node* _Copy(Node* root)
	{
		if (NULL == root);
		{
			return NULL;
		}
		Node* newroot = new Node(root->_data);
		newroot->_left = _Copy(root->_left);
		newroot->_right = _Copy(root->_right);
		return newroot;
	}

赋值运算符重载:

	BinaryTree& operator=(const BinaryTree& t)
	{
		if (this != &t)
		{
			BinaryTree tmp(t);
			swap(tmp._root, _root);
		}
		return *this;
	}


析构函数:

析构掉整棵树的时候需要析构他的每个节点,这就要考虑析构节点的先后顺序

前序,中序都不能实现,所以我们选择后序


	~BinaryTree()
	{
		Destroy(_root);
		_root = NULL;
	}
	void Destroy(Node* root)
	{
		if (NULL == root)
		{
			return;
		}
		Destroy(root->_left);
		Destroy(root->_right);
		delete root;
	}


前序(递归写法)

void _PrevOrder(Node* root)
	{
		if (NULL==root)
		{
			return;
		}
		cout << root->_data << " ";
		_PrevOrder(root->_left);
		_PrevOrder(root->_right);
	}

中序

void InOrder()
	{
		_InOrder(_root);
		cout << endl;
	}
	void _InOrder(Node* root)
	{
		if (NULL==root)
		{
			return;
		}
		_InOrder(root->_left);
		cout << root->_data << " ";
		_InOrder(root->_right);
	}

后序

void PostOrder()
	{
		_PostOrder(_root);
		cout << endl;
	}
	void _PostOrder(Node* root)
	{
		if (NULL==root)
		{
			return;
		}
		_PostOrder(root->_left);
		_PostOrder(root->_right);
		cout << root->_data << " ";
	}

层序

层序不能使用递归的写法,但我们可以利用队列。先将根节点插入队列,看队列是否为空,不为空的话就取队列的头,然后将头节点的左右节点插入队列,

最后pop掉这个头节点。这样就可以实现层序了。

	void LevelOrder()
	{
		queue<Node*> q;
		if (_root != NULL)
		{
			q.push(_root);
			while (!q.empty())
			{
				Node* Front = q.front();
				cout << Front->_data << " ";
				if (Front->_left != NULL)
				{
					q.push(Front->_left);
				}
				if (Front->_right != NULL)
				{
					q.push(Front->_right);
				}
				q.pop();
			}
		}
	}
求深度

size_t Depth()
	{
		return _Depth(_root);
	}
	size_t _Depth(Node* root)
	{
		if (NULL==root)
		{
			return 0;
		}
		size_t LD = _Depth(root->_left);
		size_t LR = _Depth(root->_right);
		return LD > LR ? LD + 1 : LR + 1;
	}

求叶子节点

size_t LeafSize()//叶子节点
	{
		return _LeafSize(_root);
	}
	size_t _LeafSize(Node* root)
	{
		if (NULL==root)
		{
			return 0;
		}
		if (root->_left == NULL && root->_right == NULL)
		{
			return 1;
		}
		size_t i = _LeafSize(root->_left);
		size_t j = _LeafSize(root->_right);
		return i + j;
	}
求第k层节点
size_t GetKLevel(size_t k)
	{
		size_t count = 0;
		_GetKLevel(_root, k, count);
		return count;
	}
	void _GetKLevel(Node* root, size_t k, size_t& count)
	{
		if (root == NULL)
		{
			return ;
		}
		if (k == 1)
		{
			++count;
		}
		_GetKLevel(root->_left, k - 1, count);
		_GetKLevel(root->_right, k - 1, count);
	}

求节点数:

将整棵树遍历一遍,用一个变量计数即可

	size_t Size()
	{
		size_t ret = 0;
		_Size(_root,ret);
		return ret;
	}
	void _Size(Node* root,size_t &ret)
	{
		if (root == NULL)
		{
			return ;
		}
		ret++;
		_Size(root->_left);
		_Size(root->_right);

	}



全部实现:

#include<iostream>
#include<queue>
using namespace std;

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

template<class T>
class BinaryTree
{
	typedef BinaryTreeNode<T> Node;
public:
	BinaryTree()//构造函数
		:_root(NULL)
	{}

	BinaryTree( T* a, size_t n, const T& invalid)//构造树
	{
		size_t index = 0;//数组下标
		_root = CreatTree(a, n, invalid, index);
	}

	Node* CreatTree( T* a, size_t n, const T& invalid, size_t& index)//构造二叉树 ,这里的index要用引用,否则上一层递归到里面的++对index没有影响
	{
		Node* root = NULL;
		if (index >= n || a[index] == invalid)
		{
			return NULL;
		}
			root = new Node(a[index]);
			root->_left = CreatTree(a, n, invalid, ++index);
			root->_right = CreatTree(a, n, invalid, ++index);
		return root;
	}

	BinaryTree(const BinaryTree& t)//拷贝构造
	{
		_root = _Copy(t._root);
	}
	Node* _Copy(Node* root)
	{
		if (NULL == root)
		{
			return NULL;
		}
		Node* newroot = new Node(root->_data);
		newroot->_left = _Copy(root->_left);
		newroot->_right = _Copy(root->_right);
		return newroot;
	}

	BinaryTree& operator=(const BinaryTree& t)
	{
		if (this != &t)
		{
			BinaryTree tmp(t);
			swap(tmp._root, _root);
		}
		return *this;
	}
	void PrevOrder()
	{
		_PrevOrder(_root);
		cout << endl;
	}
	void _PrevOrder(Node* root)
	{
		if (NULL==root)
		{
			return;
		}
		cout << root->_data << " ";
		_PrevOrder(root->_left);
		_PrevOrder(root->_right);
	}

	void InOrder()
	{
		_InOrder(_root);
		cout << endl;
	}
	void _InOrder(Node* root)
	{
		if (root == NULL)
		{
			return;
		}
		_InOrder(root->_left);
		cout << root->_data << " ";
		_InOrder(root->_right);
	}

	void PostOrder()
	{
		_PostOrder(_root);
		cout << endl;
	}
	void _PostOrder(Node* root)
	{
		if (root == NULL)
		{
			return;
		}
		_PostOrder(root->_left);
		_PostOrder(root->_right);
		cout << root->_data << " ";
	}

	void LevelOrder()
	{
		queue<Node*> q;
		if (_root != NULL)
		{
			q.push(_root);
			while (!q.empty())
			{
				Node* Front = q.front();
				cout << Front->_data << " ";
				if (Front->_left != NULL)
				{
					q.push(Front->_left);
				}
				if (Front->_right != NULL)
				{
					q.push(Front->_right);
				}
				q.pop();
			}
		}
		cout << endl;
	}

	size_t Size()
	{
		size_t ret = 0;
		_Size(_root,ret);
		return ret;
	}
	void _Size(Node* root,size_t &ret)
	{
		if (root == NULL)
		{
			return ;
		}
		ret++;
		_Size(root->_left);
		_Size(root->_right);

	}

	size_t Depth()
	{
		return _Depth(_root);
	}
	size_t _Depth(Node* root)
	{
		if (NULL==root)
		{
			return 0;
		}
		size_t LD = _Depth(root->_left);
		size_t LR = _Depth(root->_right);
		return LD > LR ? LD + 1 : LR + 1;
	}

	size_t LeafSize()//叶子节点
	{
		return _LeafSize(_root);
	}
	size_t _LeafSize(Node* root)
	{
		if (NULL==root)
		{
			return 0;
		}
		if (root->_left == NULL && root->_right == NULL)
		{
			return 1;
		}
		size_t i = _LeafSize(root->_left);
		size_t j = _LeafSize(root->_right);
		return i + j;
	}
	/*size_t GetKLevel(size_t k)
	{
		size_t count = 0;
		_GetKLevel(_root, 1, k, count);
		return count;
	}
	void _GetKLevel(Node* root, size_t cur, size_t k, size_t& count)
	{
		if (root == NULL)
		{
			return;
		}
		if (cur == k)
		{
			count++;
		}
		_GetKLevel(root->_left, cur + 1, k, count);
		_GetKLevel(root->_right, cur + 1, k, count);
	}*/

	size_t GetKLevel(size_t k)
	{
		size_t count = 0;
		_GetKLevel(_root, k, count);
		return count;
	}
	void _GetKLevel(Node* root, size_t k, size_t& count)
	{
		if (root == NULL)
		{
			return ;
		}
		if (k == 1)
		{
			++count;
		}
		_GetKLevel(root->_left, k - 1, count);
		_GetKLevel(root->_right, k - 1, count);
	}
	//析构函数即销毁这棵树,几种遍历只有后序可以实现
	~BinaryTree()
	{
		Destroy(_root);
		_root = NULL;
	}
	void Destroy(Node* root)
	{
		if (NULL == root)
		{
			return;
		}
		Destroy(root->_left);
		Destroy(root->_right);
		delete root;
	}
private:
	Node* _root;
};

int main()
{
	int arr[10] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6 };
	int arr2[5] = { 1, 2, 3, 4 };
	BinaryTree<int> t1(arr, sizeof(arr) / sizeof(arr[0]), '#');
	BinaryTree<int> t2(arr2, sizeof(arr2) / sizeof(arr2[0]), '#');
	//t1 = t2;

	t1.PostOrder();
	t1.InOrder();
	t1.PrevOrder();
	t1.LevelOrder();

	size_t i = t1.Depth();
	cout << i << endl;

	size_t k=t1.GetKLevel(2);
	cout << k << endl;

	size_t j = t1.LeafSize();
	cout << j << endl;

	system("pause");
	return 0;
}





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值