BinaryTree

/******************************************************************************************
Copyright (c) Bit Software, Inc.(2016), All rights reserved.

Purpose: 实现二叉树的基本操作     

Author: MaJing

Reviser: yyy

Created Time: 2016-9-5
******************************************************************************************/
#pragma once

#include<queue>
#include<stack>

// 一般二叉树实现接口实现

template<class T>
struct BinaryTreeNode
{
	T _data;					// 数据
	BinaryTreeNode<T>* _left;	// 左孩子
	BinaryTreeNode<T>* _right;	// 右孩子

	BinaryTreeNode(const T& x)
		:_data(x)
		,_left(NULL)
		,_right(NULL)
	{}
};

template<class T>
class BinaryTree
{
public:
	BinaryTree()
		:_root(NULL)
	{}

	BinaryTree(T array[], size_t size)
	{
		// 1.创建二叉树
		int index = 0;
		_CreateTree(_root, array, size, index);
	}

	//
	// 实现深拷贝二叉树
	//
	BinaryTree(const BinaryTree<T>& t)
	{
		this->_root = _CopyTree(t._root);
	}

	/*BinaryTree<T>& operator=(const BinaryTree<T>& t)
	{
		if (this != &t)
		{
			this->Destory();
			this->_root = _CopyTree(t._root);
		}

		return *this;
	}*/

	BinaryTree<T>& operator=(BinaryTree<T> t)
	{
		swap(_root, t._root);
		return *this;
	}

	~BinaryTree()
	{
		Destory();
	}

	// 2.遍历二叉树(前序、中序、后序、层序)
	void PrevOrder()
	{
		cout<<"PrevOrder:";
		_PrevOrder(_root);
		cout<<endl;
	}

	void InOrder()
	{
		cout<<"InOrder:";
		_InOrder(_root);
		cout<<endl;
	}
	void PostOrder()
	{
		cout<<"PostOrder:";
		_PostOrder(_root);
		cout<<endl;
	}

	void LevelOrder()
	{
		cout<<"LevelOrder:";
		if (_root == NULL)
			return;

		// 1.入队列根节点
		queue<BinaryTreeNode<T>*> q;
		q.push(_root);

		// 队列为空时遍历完成
		while (!q.empty())
		{
			BinaryTreeNode<T>* root = q.front();
			if (root->_left)
			{
				q.push(root->_left);
			}

			if (root->_right)
			{
				q.push(root->_right);
			}

			cout<<root->_data<<" ";
			q.pop();
		}
		cout<<endl;
	}

	// 非递归实现前/中/后序遍历
	void PrevOrder_NonR()
	{
		cout<<"PrevOrder_NonR:";
		stack<BinaryTreeNode<T>*> s;
		if (_root)
		{
			s.push(_root);
		}

		while (!s.empty())
		{
			//
			// 先访问根节点,先入右节点再入左节点,
			// 出栈时才能先访问到左节点,再访问到右节点。
			//
			BinaryTreeNode<T>* root = s.top();
			cout<<root->_data<<" ";
			s.pop();

			if (root->_right)
			{
				s.push(root->_right);
			}

			if (root->_left)
			{
				s.push(root->_left);
			}
		}

		cout<<endl;
	}

	void InOrder_NonR()
	{
		cout<<"InOrder_NonR:";
		stack<BinaryTreeNode<T>*> s;

		BinaryTreeNode<T>* cur = _root;

		while (cur || !s.empty())
		{
			// 1.先将左节点全部入栈
			while (cur)
			{
				s.push(cur);
				cur = cur->_left;
			}

			//
			// 2.栈不为空时,访问栈顶节点。
			// 将cur指向栈顶节点的右子树,继续中序遍历右子树。
			//
			if (!s.empty())
			{
				BinaryTreeNode<T>* top = s.top();
				cout<<top->_data<<" ";
				s.pop();
				cur = top->_right;
			}
		}

		cout<<endl;
	}

	void PostOrder_NonR()
	{
		cout<<"PostOrder_NonR:";
		stack<BinaryTreeNode<T>*> s;
		BinaryTreeNode<T>* cur = _root;
		BinaryTreeNode<T>* prevVisited = NULL;

		while (cur || !s.empty())
		{
			// 入栈做孩子节点
			while (cur)
			{
				s.push(cur);
				cur = cur->_left;
			}

			// 2.右节点为空/之前右节点已经访问过了的时候访问当前的栈顶节点
			BinaryTreeNode<T>* top = s.top();
			if (top->_right == NULL || prevVisited == top->_right)
			{
				cout<<top->_data<<" ";
				s.pop();
				prevVisited = top;
			}
			else
			{
				cur = top->_right;
			}
		}

		cout<<endl;
	}


	// 3.查找
	BinaryTreeNode<T>* Find(const T& x)
	{
		return _Find(_root, x);
	}

	int Height()
	{
		return _Height(_root);
	}

	int Size()
	{
		return _Size(_root);
	}

	void Destory()
	{
		_Destory(_root);
		_root = NULL;
	}

protected:
	// 构建二叉树
	void _CreateTree(BinaryTreeNode<T>*& root, T array[], size_t size, int& index)
	{
		if (index < size && array[index] != '#')
		{
			root = new BinaryTreeNode<T>(array[index]);
			_CreateTree(root->_left, array, size, ++index);
			_CreateTree(root->_right, array, size, ++index);
		}
	}

	void _PrevOrder(BinaryTreeNode<T>* root)
	{
		if (root == NULL)
			return;

		cout<<root->_data<<" ";
		_PrevOrder(root->_left);
		_PrevOrder(root->_right);
	}

	void _InOrder(BinaryTreeNode<T>* root)
	{
		if (root == NULL)
			return;

		_InOrder(root->_left);
		cout<<root->_data<<" ";
		_InOrder(root->_right);
	}

	void _PostOrder(BinaryTreeNode<T>* root)
	{
		if (root == NULL)
			return;

		_PostOrder(root->_left);
		_PostOrder(root->_right);
		cout<<root->_data<<" ";
	}

	BinaryTreeNode<T>* _Find(BinaryTreeNode<T>* root, const T& x)
	{
		if (root == NULL)
			return  NULL;

		if (root->_data == x)
			return root;

		BinaryTreeNode<T>* ret = NULL;
		if (ret = _Find(root->_left, x))
		{
			return ret;
		}

		if (ret = _Find(root->_right, x))
		{
			return ret;
		}

		return NULL;
	}

	int _Height(BinaryTreeNode<T>* root)
	{
		if (root == NULL)
		{
			return 0;
		}

		int leftHeight = _Height(root->_left) + 1;
		int rightHeight = _Height(root->_right) + 1;

		return leftHeight > rightHeight ? leftHeight : rightHeight;
	}

	int _Size(BinaryTreeNode<T>* root)
	{
		if (root == NULL)
		{
			return 0;
		}

		return _Size(root->_left) + _Size(root->_right) + 1;
	}

	// 拷贝二叉树
	BinaryTreeNode<T>* _CopyTree(BinaryTreeNode<T>* root)
	{
		BinaryTreeNode<T>* newRoot = NULL;
		if (root)
		{
			newRoot = new BinaryTreeNode<T>(root->_data);
			newRoot->_left = _CopyTree(root->_left);
			newRoot->_right = _CopyTree(root->_right);
		}

		return newRoot;
	}


	void _Destory(BinaryTreeNode<T>* root)
	{
		if (root == NULL)
			return;
		
		_Destory(root->_left);
		_Destory(root->_right);

		delete root;
	}

private:
	BinaryTreeNode<T>* _root;	// 根节点
};

// 测试二叉树
void TestBinaryTree()
{
	cout<<"TestBinaryTree:"<<endl;

	int array[20] = {1, 2, 3, '#', '#', 4, '#', '#', 5, 6};
	BinaryTree<int> tree(array, 10);

	tree.PrevOrder();
	tree.PrevOrder_NonR();
	tree.InOrder();
	tree.InOrder_NonR();
	tree.PostOrder();
	tree.PostOrder_NonR();
	tree.LevelOrder();

	BinaryTreeNode<int>* ret = tree.Find(3);
	cout<<"Find 3?: "<<ret->_data<<endl;

	ret = tree.Find(10);
	cout<<"Find 10?: "<<ret<<endl;

	cout<<"Height:"<<tree.Height()<<endl;

	BinaryTree<int> treeCopy1 = tree;
	treeCopy1.PrevOrder();

	BinaryTree<int> treeCopy2;
	treeCopy2 = tree;
	treeCopy2.PrevOrder();
}

// 二叉树三叉链结构
template<class T>
struct BinaryTreeNode_P
{
	T _data;							// 数据
	BinaryTreeNode_P<T>* _left;		// 左孩子
	BinaryTreeNode_P<T>* _right;	// 右孩子
	BinaryTreeNode_P<T>* _parent;	// 父节点

	BinaryTreeNode_P(const T& x)
		:_data(x)
		,_left(NULL)
		,_right(NULL)
		,_parent(NULL)
	{}
};

template<class T>
class BinaryTree_P
{
public:
	BinaryTree_P(T array[], size_t size)
	{
		int index = 0;
		_CreateTree(_root, array, size, index);
	}
protected:
	// 构建二叉树
	void _CreateTree(BinaryTreeNode_P<T>*& root, T array[], size_t size, int& index)
	{
		if (index < size && array[index] != '#')
		{
			root = new BinaryTreeNode_P<T>(array[index]);
			_CreateTree(root->_left, array, size, ++index);
			// 更新父节点
			if (root->_left)
				root->_left->_parent = root;

			_CreateTree(root->_right, array, size, ++index);

			// 更新父节点
			if (root->_right)
				root->_right->_parent = root;
		}
	}
private:
	BinaryTreeNode_P<T>* _root;
};

// 测试二叉树
void TestBinaryTree_P()
{
	int array[20] = {1, 2, 3, '#', '#', 4, '#', '#', 5, 6};
	BinaryTree_P<int> tree(array, 10);
}

<think>我们被要求详细介绍二叉树(binary tree)。结合用户提供的引用内容,我们可以从以下几个方面展开: 1. 二叉树的定义和基本概念(包括节点、根、子树等) 2. 二叉树的性质(如第i层最多有2^(i-1)个节点,深度为k的二叉树最多有2^k-1个节点等) 3. 特殊类型的二叉树(满二叉树、完全二叉树、完美二叉树等,注意引用[3]中提到的术语区别) 4. 二叉树的存储结构(通常用链式存储,如引用[1][2][4]中的节点结构) 5. 二叉树的遍历(深度优先:前序、中序、后序;广度优先:层次遍历) 6. 二叉树的构建(如引用[1]中的手动构建和引用[4]中的插入构建) 7. 二叉树的应用 由于用户要求详细,我们将每个部分都进行适当的展开。 注意:用户提供的引用中,引用[3]提到了满二叉树和完全二叉树的区别,并引入了完美二叉树的概念,我们需要明确这些术语。 下面开始组织内容: </think>### 二叉树(Binary Tree)详解 二叉树是一种重要的非线性数据结构,其特点是每个节点最多有两个子节点:**左子节点**和**右子节点**。这种结构天然支持递归定义,在算法设计和数据处理中具有广泛应用。 --- #### 一、二叉树核心概念 1. **节点结构** 每个节点包含三个部分: ```java class TreeNode { int data; // 节点存储的数据 TreeNode left; // 左子节点指针 TreeNode right; // 右子节点指针 } ``` 引用示例代码:[^4] 2. **基本术语** - **根节点(Root)**:树的起始节点(如`tree.root`)[^1] - **叶子节点(Leaf)**:左右子节点均为空的节点 - **深度(Depth)**:从根节点到当前节点的路径长度 - **高度(Height)**:从当前节点到最深叶子节点的路径长度 - **度(Degree)**:节点的子节点数量(二叉树中最大为2) 3. **特殊二叉树类型** | 类型 | 定义 | 示例 | |------|------|------| | **满二叉树(Full Binary Tree)** | 每个节点有0或2个子节点 | `A(B,C)` | | **完全二叉树(Complete Binary Tree)** | 除最后一层外全满,最后一层从左向右填充 | `A(B(D,E),C(F))` | | **完美二叉树(Perfect Binary Tree)** | 所有叶子节点在同一层,且每层都被填满 | `A(B(D,E),C(F,G))` [^3] | --- #### 二、二叉树存储结构 1. **链式存储(主流方式)** - 节点通过指针链接(如上文Java代码实现)[^4] - 优点:动态内存分配,插入删除灵活 - 缺点:指针占用额外空间 2. **顺序存储(数组实现)** - 根节点索引:`i=0` - 左子节点索引:`2i+1` - 右子节点索引:`2i+2` - 适用场景:完全二叉树存储优化 --- #### 三、二叉树遍历算法 1. **深度优先遍历(DFS)** ```java // 前序遍历:根 → 左 → 右 void preOrder(TreeNode node) { if (node == null) return; System.out.print(node.data + " "); // 访问根 preOrder(node.left); // 遍历左子树 preOrder(node.right); // 遍历右子树 } ``` - **中序遍历**:左 → 根 → 右(二叉搜索树可输出有序序列)[^1] - **后序遍历**:左 → 右 → 根(常用于表达式树求值) 2. **广度优先遍历(BFS)** 使用队列实现层次遍历: ```java void levelOrder(TreeNode root) { Queue<TreeNode> queue = new LinkedList<>(); queue.add(root); while (!queue.isEmpty()) { TreeNode node = queue.poll(); System.out.print(node.data + " "); if (node.left != null) queue.add(node.left); if (node.right != null) queue.add(node.right); } } ``` --- #### 四、二叉树构建方法 1. **手动构建(静态)** 直接连接节点(适用于固定结构): ```java BinaryTree tree = new BinaryTree(); tree.root = new Node(1); tree.root.left = new Node(2); tree.root.right = new Node(3); // 引用[1]示例 ``` 2. **插入构建(动态)** 根据规则递归插入(如二叉搜索树): ```java void insert(TreeNode node) { if (root == null) root = node; else if (node.data < current.data) current.left = insert(current.left, node); else current.right = insert(current.right, node); } // 引用[4]逻辑简化版 ``` --- #### 五、二叉树关键性质 1. **节点数量关系** - 第 $i$ 层最多有 $2^{i-1}$ 个节点 - 深度为 $k$ 的树最多有 $2^k - 1$ 个节点 2. **高度与节点关系** 对于 $n$ 个节点的二叉树: - 最小高度:$\lfloor \log_2n \rfloor + 1$ - 最大高度:$n$(退化为链表) 3. **特殊性质** 在二叉搜索树中(BST): - 左子树所有节点值 $<$ 根节点值 - 右子树所有节点值 $>$ 根节点值 --- #### 六、二叉树应用场景 1. **数据检索**:二叉搜索树实现$O(\log n)$查找 2. **表达式解析**:算术表达式的语法树表示 3. **文件系统**:目录树结构建模 4. **游戏AI**:决策树实现行为选择 5. **压缩算法**:哈夫曼编码构建最优前缀树 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值