二叉树的七种遍历及部分操作

1. 二叉树结构体。

struct BinaryTreeNode
{
	char m_cValue;
	BinaryTreeNode *  m_pLeft;
	BinaryTreeNode *  m_pRight;
};
typedef  BinaryTreeNode*  BiTree;

2. 先序创建二叉树。

void  CreateBTree(BiTree &T)  //前序顺序创建二叉树, 如果不加这个引用&,指针出来后就没有了。。。。。。。
{
	char c;

	cin >> c;
	if (c == '#')
		T = nullptr;
	else
	{
		T = new BinaryTreeNode;
		T->m_cValue = c;
		CreateBTree(T->m_pLeft);
		CreateBTree(T->m_pRight);
	}
}

3. 先序中序后序,递归遍历二叉树。

void PreTraverse(BiTree T)
{
	if (T)
	{
		cout << T->m_cValue << " ";
		PreTraverse(T->m_pLeft);
		PreTraverse(T->m_pRight);
	}
}
void MidTraverse(BiTree T)
{
	if (T)
	{
		MidTraverse(T->m_pLeft);
		cout << T->m_cValue << " ";
		MidTraverse(T->m_pRight);
	}
}
void PostTraverse(BiTree T)
{
	if (T)
	{
		PostTraverse(T->m_pLeft);
		PostTraverse(T->m_pRight);
		cout << T->m_cValue << " ";
	}
}

4. 先序非递归遍历二叉树。

void PreTraverseNoRecur(BiTree T)
{
	if (T)
	{
		stack<BinaryTreeNode *> m_stack;
		m_stack.push(T);

		BinaryTreeNode * pNode = nullptr;
		while( !m_stack.empty() )
		{
			pNode = m_stack.top();
			m_stack.pop();
			cout << pNode->m_cValue << " ";

			if (pNode->m_pRight)
				m_stack.push(pNode->m_pRight);

			if (pNode->m_pLeft)
				m_stack.push(pNode->m_pLeft);
		}
	}
}

5. 中序非递归遍历二叉树。

void MidTraverseNoRecur(BiTree T)
{
	if (T==nullptr)
		return;

	stack<BiTree> s1;
	BinaryTreeNode * pNode = T;

	while (pNode || !s1.empty())
	{
		if(pNode)
		{
			s1.push(pNode);
			pNode = pNode->m_pLeft;
		}
		else   //这里的栈是没有push的
		{
			pNode = s1.top();
			cout << pNode->m_cValue << " ";
			s1.pop();
			pNode = pNode->m_pRight;
		}
	}

}

6. 后序非递归遍历二叉树。

void PostTraverseNoRecur(BiTree T)
{
	if(T == nullptr)
		return;

	stack<BiTree> s1;
	vector<char>  v1;
	s1.push(T);
	BinaryTreeNode *pNode = nullptr;

	while (!s1.empty())
	{
		pNode = s1.top();
		s1.pop();
		v1.insert(v1.begin(), pNode->m_cValue);   //这是指每次都在这个位置插入。

		if (pNode->m_pLeft)
			s1.push(pNode->m_pLeft);
		if (pNode->m_pRight)
			s1.push(pNode->m_pRight);
	}

	for (int ii=0; ii<v1.size(); ++ii)
		cout << v1[ii] << " ";

}

方法二

void PostTraverTree(BiTree& pHead)
{
	if (pHead == nullptr)
		return;

	stack<BiTree>  stack1;
	stack<BiTree>  stack2;
	BiTree pNode = pHead;
	stack1.push(pNode);
	while (!stack1.empty())
	{
		pNode = stack1.top();
		stack1.pop();
		stack2.push(pNode);

		if (pNode->m_pLeft)
			stack1.push(pNode->m_pLeft);

		if (pNode->m_pRight)
			stack1.push(pNode->m_pRight);
	}

	while (!stack2.empty())
	{
		cout << stack2.top << " ";
		stack2.pop();
	}

	return;
}

7. 层序遍历二叉树(与先序遍历只是用的容器不同,语句几乎一样)。

void LayerTraverseBST(BiTree T)
{
	if (T == nullptr)
		return;

	deque<BiTree> q1;
	q1.push_back(T);
	BinaryTreeNode *pNode = nullptr;

	while (! q1.empty() )
	{
		pNode = q1.front();
		q1.pop_front();
		cout << pNode->m_cValue << " ";

		if (pNode->m_pLeft)
			q1.push_back(pNode->m_pLeft);
		if (pNode->m_pRight)
			q1.push_back(pNode->m_pRight);
	}
}

8. 二叉树的重建。给出前序与中序遍历的结果,重建二叉树。

int GetPos(string inOrder, char c)
{
	if (inOrder.empty())
		return -1;

	int ret = -1;
	for (int ii=0; ii!=inOrder.size(); ++ii)
	{
		if (inOrder[ii] == c)
			ret = ii;
	}

	return ret;
}
void ReBuild(string preOrder, string inOrder, BiTree &T)
{
	if (preOrder.empty() )
	{
		T = nullptr;
		return ;
	}
	if ( (preOrder.size() != inOrder.size() ))
	{
		cout << "Invalid input. " << endl;
		return ;
	}

	T = new BinaryTreeNode;
	T->m_cValue = preOrder[0];
	if (preOrder.size() == 1)
	{
		T->m_pLeft = nullptr;
		T->m_pRight = nullptr;
		return ;
	}

	int pos = GetPos(inOrder, preOrder[0]);

	if (pos == 0)
	{
		T->m_pLeft = nullptr;
		string preTmp2 = preOrder.substr(pos+1, preOrder.size());
		string inTmp2 = inOrder.substr(pos+1, inOrder.size());
		ReBuild(preTmp2, inTmp2, T->m_pRight);
	}
	else if (pos == inOrder.size()-1)
	{
		T->m_pRight = nullptr;
		string preTmp2 = preOrder.substr(1, pos);
		string inTmp2 = inOrder.substr(0, pos);
		ReBuild(preTmp2, inTmp2, T->m_pLeft);
	}
	else if (pos>0 && pos<inOrder.size()-1)
	{
		string preTmp1 = preOrder.substr(1, pos);
		string preTmp2 = preOrder.substr(pos+1, preOrder.size());
		string inTmp1 = inOrder.substr(0, pos);
		string inTmp2 = inOrder.substr(pos+1, inOrder.size());
		ReBuild(preTmp1, inTmp1, T->m_pLeft);
		ReBuild(preTmp2, inTmp2, T->m_pRight);
	}
	else
	{
		cout << "Cannot rebuild a binary tree ." << endl;
	}

	return ;
}

二叉树的重建,使用STL容器。

struct TreeNode 
{
	int val;
	TreeNode *left;
	TreeNode *right;
	TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 };

int GetPos(vector<int> v1, int val)
{
	if (v1.empty())
		return -1;

	int pos = -1;
	for (int ii=0; ii != v1.size(); ++ii)
	{
		if (v1[ii] == val)
			pos = ii;
	}

	return pos;
}

TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) 
{
	if (pre.size() != vin.size())
		return nullptr;

	if (pre.empty() && vin.empty())
		return nullptr;

	int val = pre[0];
	int pos = GetPos(vin, val);
	if (pos == -1)
		return nullptr;

	vector<int>  preLeft(pre.begin()+1, pre.begin()+pos+1);
	vector<int>  preRight(pre.begin()+pos+1, pre.end());
	vector<int>  vinLeft(vin.begin(), vin.begin()+pos);
	vector<int>  vinRight(vin.begin()+pos+1, vin.end());

	TreeNode * root = new TreeNode(val);
	root->left = reConstructBinaryTree(preLeft, vinLeft);
	root->right = reConstructBinaryTree(preRight, vinRight);

	return root;
}

9. 获取二叉树的深度。

int  GetTreeDepth(BiTree T)
{
	if (T == nullptr)
		return 0;

	int lDepth = 0, rDepth = 0;
	if (T->m_pLeft)
		lDepth = GetTreeDepth(T->m_pLeft);

	if (T->m_pRight)
		rDepth = GetTreeDepth(T->m_pRight);

	return ( (lDepth>rDepth)?lDepth:rDepth ) + 1;
}

10. 求二叉树相距最大的两个节点的距离。(这里距离指的是边的个数)【注:方法有待改进】

void GetBiTreeLagPath(BiTree T, int &maxLen)
{
	if (T == nullptr)
		return ;

	int lDepth = GetTreeDepth(T->m_pLeft);
	int rDepth = GetTreeDepth(T->m_pRight);
	
	maxLen = max( (lDepth + rDepth), maxLen);

	GetBiTreeLagPath (T->m_pLeft, maxLen);
	GetBiTreeLagPath (T->m_pRight, maxLen);

	return ;
}

11. 求二叉树宽度。

int GetBiTreeWidth(BiTree T)
{
	if (T == nullptr)
		return 0;

	queue<BiTree> Q1;
	Q1.push(T);
	BiTree pNode = new BinaryTreeNode;
	
	int maxWidth = 1;
	int frontWidth = 1;
	int curWidth = 0;
	while ( !Q1.empty() )
	{
		pNode = Q1.front();
		Q1.pop();

		if (pNode->m_pLeft)
		{
			Q1.push(pNode->m_pLeft);
			++curWidth;
		}
		if (pNode->m_pRight)
		{
			Q1.push(pNode->m_pRight);
			++curWidth;
		}

		if ( ! --frontWidth )
		{
			frontWidth = curWidth;
			maxWidth = (maxWidth>curWidth)? maxWidth:curWidth;
			curWidth = 0;
		}
	}

	return maxWidth;
}

12. 树的子结构。(判断B是不是A的子结构)

bool IsTreeEqual(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2)
{
	if (pRoot1 == nullptr && pRoot2 == nullptr)
		return true;
	else if(pRoot1 == nullptr && pRoot2 != nullptr)
		return false;
	else if(pRoot1 != nullptr && pRoot2 == nullptr)
		return true;

	bool ret = (pRoot1->val == pRoot2->val);
	if ( !ret )
		return false;

	bool lRet = IsTreeEqual(pRoot1->left, pRoot2->left);
	bool rRet = IsTreeEqual(pRoot1->right, pRoot2->right);

	return (lRet && rRet);
}
bool HasSubtree(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2)
{		
	bool ret = false;

	if (pRoot1 != nullptr && pRoot2 != nullptr)
	{
		ret = IsTreeEqual(pRoot1, pRoot2);
		if ( !ret )
			ret = HasSubtree(pRoot1->left, pRoot2);
		if ( !ret )
			ret = HasSubtree(pRoot1->right, pRoot2);
	}

	return ret;
}

13. 二叉树镜像。

 struct TreeNode
 {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
void Mirror(TreeNode *pRoot) 
{
	if (pRoot == nullptr)
		return ;

	swap(pRoot->left, pRoot->right);

	if (pRoot->left)
		Mirror(pRoot->left);

	if (pRoot->right)
		Mirror(pRoot->right);

	return;
}

14、判断一组数是否为二叉搜索树的后序遍历序列。

bool JudgePostOrderSeq(vector<int> &sequence, int sIdx, int eIdx, int root)
{
	if (sIdx == eIdx  && sequence[sIdx]==root)
		return true;
	else if(sIdx == eIdx  && sequence[sIdx]!=root)
		return false;

	int ret = false;
	int pos = 0;
	for (int ii=0; ii<sequence.size(); ++ii)
	{
		if (sequence[ii] >= root)
		{
			pos = ii;break;
		}
	}
	for (int ii=pos; ii<=eIdx; ++ii)
	{
		if (sequence[ii]<root)
		{
			return false;
		}
	}

	bool lRet = true, rRet = true;
	if (pos >= 1)
		lRet = JudgePostOrderSeq(sequence, 0, pos-1, sequence[pos-1]);
	if (pos <= eIdx-1)
		rRet = JudgePostOrderSeq(sequence, pos, eIdx-1, sequence[eIdx-1]);

	ret = rRet && lRet;

	return ret;
}
bool VerifySquenceOfBST(vector<int> &sequence) 
{
	if (sequence.empty())
		return false;
	if ( sequence.size() == 1 )
		return true;

	bool ret = JudgePostOrderSeq(sequence, 0, sequence.size()-1, sequence[sequence.size()-1]);

	return ret;
}

15. 求二叉树所有和为某值的路径。

void  DFSFindPath(TreeNode* root, int tarNum, int lastSum, vector<vector<int> > &v1, vector<int> &tmp)
{
	/*
		深度优先遍历算法:看起来形式比较像先序遍历。
		用到的思想是:一直向下递归,直到叶子节点,期间所有的节点都保存下来,然后判断这条路径是否是需要的
					     如果是,整条路径保存;如果不是,依次弹出最后面的节点,并寻找最近的不同路径压入。
	*/
	int rootValue = root->val;
	tmp.push_back(rootValue);   // 用以保存单条路径。

	if (lastSum+rootValue == tarNum && !root->left && !root->right)
		v1.push_back(tmp);    // 二维数组添加可以一次添加一维的数据,这样就可以将路径整体存下来!
	else
	{
		if (root->left)
			DFSFindPath(root->left, tarNum, lastSum+rootValue, v1, tmp) ;
		if (root->right)
			DFSFindPath(root->right, tarNum, lastSum+rootValue, v1, tmp) ;
	}
	
	tmp.pop_back();
	return ;
}
vector<vector<int> > FindPath(TreeNode* root,int expectNumber) 
{
	if (root == nullptr)
		return vector<vector<int> >();

	vector<vector<int> > v1;
	vector<int> tmp;

	DFSFindPath(root, expectNumber, 0, v1, tmp);

    	return v1;
}

16. 将二叉搜索树转为单调排序的链表。

// -----------------实现二叉树转链表--------中序遍历+保存前节点的指针  ------------
TreeNode* Convert(TreeNode* pRootOfTree)
{
	if (pRootOfTree==nullptr)
		return nullptr;

	int flag = 1;
	stack<TreeNode*> s1;

	TreeNode* pHead = nullptr;
	TreeNode* pLastNode = nullptr;
	TreeNode * pCurNode = pRootOfTree;

	while (pCurNode || !s1.empty())
	{
		if(pCurNode)
		{
			s1.push(pCurNode);
			pCurNode = pCurNode->left;
		}
		else 
		{
			pCurNode = s1.top();
			if (flag)
			{
				pHead = pCurNode;
				flag = 0;
			}

			pCurNode->left = pLastNode;
			if ( pLastNode )
				pLastNode->right = pCurNode;
			pLastNode = pCurNode;
			pCurNode = pCurNode->right;
			
			s1.pop();
		}
	}

	return pHead;
}

递归版本

void InOrderConvert(TreeNode* pRootOfTree, TreeNode* &pLast)
{
	if (pRootOfTree == nullptr)
		return;

	if (pRootOfTree)
		InOrderConvert(pRootOfTree->left, pLast);

	pRootOfTree->left = pLast;
	if (pLast)
		pLast->right = pRootOfTree;

	pLast = pRootOfTree;
	InOrderConvert(pRootOfTree->right, pLast);

	return;
}
TreeNode* Convert(TreeNode* pRootOfTree)
{
	if (pRootOfTree==nullptr)
		return nullptr;

	TreeNode* pLast = nullptr;
	InOrderConvert( pRootOfTree, pLast);

	while(pLast->left)
		pLast = pLast->left;

	return pLast;
}

17. 判断二叉树是否为平衡二叉树。

// -------方法一:从上到下遍历,每个节点遍历多次-----------
int TreeDepth(TreeNode* pRoot)
{
	if (pRoot == nullptr)
		return 0;

	int lefDepth = TreeDepth(pRoot->left);
	int rigDepth = TreeDepth(pRoot->right);

	return (lefDepth>rigDepth)?lefDepth+1 : rigDepth+1;
}

bool IsBalanced_Solution(TreeNode* pRoot) 
{
	if (pRoot == nullptr)
		return true;

	int lefDepth = TreeDepth(pRoot->left);
	int rigDepth = TreeDepth(pRoot->right);
	bool ret = ( abs(lefDepth-rigDepth) <= 1 );

	return ret && (IsBalanced_Solution(pRoot->left)) && (IsBalanced_Solution(pRoot->right));	
}
// -------方法二:从下往上判断,各个节点只遍历一遍,但是需要加一个全局变量--------
bool JudgeRet = true;
int TreeDepth(TreeNode* pRoot)
{
	if (pRoot == nullptr)
		return 0;

	int lefDepth = TreeDepth(pRoot->left);
	int rigDepth = TreeDepth(pRoot->right);

	if ( abs(lefDepth-rigDepth) > 1)
		JudgeRet = false;

	return (lefDepth>rigDepth)?lefDepth+1 : rigDepth+1;
}

bool IsBalanced_Solution(TreeNode* pRoot) 
{
	if (pRoot == nullptr)
		return true;

	TreeDepth(pRoot);

	return JudgeRet;	
}
// -------方法三:每个节点至多遍历一次+剪枝策略-------------
int Max(int a, int b)
{
	return (a>b)?a:b;
}

int TreeDepth(TreeNode* pRoot)
{
	if (pRoot == nullptr)
		return 0;

	int lefDepth = TreeDepth(pRoot->left);
	if (lefDepth == -1)
		return -1;  // 剪枝策略

	int rigDepth = TreeDepth(pRoot->right);
	if (rigDepth == -1)
		return -1;

	return  abs(lefDepth-rigDepth) > 1 ? -1 : Max(lefDepth, rigDepth)+1;
}

bool IsBalanced_Solution(TreeNode* pRoot) 
{
	if (pRoot == nullptr)
		return true;

	return TreeDepth(pRoot) != -1;
}

18. 主函数。

int main(int argc, char **argv)
{
	BiTree T;
	CreateBTree(T);

	cout << "先序递归遍历:  "; PreTraverse(T);

	cout << endl;
	cout << "中序递归遍历:  "; MidTraverse(T);

	cout << endl;
	cout << "后序递归遍历:  "; PostTraverse(T);
	
	cout << endl;
	cout << "先序非递归遍历:"; PreTraverseNoRecur(T);

	cout << endl;
	cout << "中序非递归遍历:"; MidTraverseNoRecur(T);

	cout << endl;
	cout << "后序非递归遍历:"; PostTraverseNoRecur(T);

	cout << endl;
	cout << "层序遍历:      ";  LayerTraverseBST(T);
	////Print(T);
	//cout << endl;
	//PrintZigzag(T);


	getchar();getchar();
	return 0;
}

19. 测试结果。

猜你喜欢

转载自blog.csdn.net/weixin_38984102/article/details/79675439
今日推荐