二叉树相关操作(遍历、路径、最近公共父节点、重构)

本文总结了二叉树的相关操作,并在最后附上所有操作的实现。还有不足之处,以后会及时更新~

 

相关操作包括:

1、插入:InsertBTree

2、遍历

1)前序遍历(递归):PreOrderTraverse

2)前序遍历(非递归):PreOrderTraverseNoRec

3)中序遍历(递归):InOrderTraverse

4)中序遍历(非递归):InOrderTraverseNoRec

5)后序遍历(递归):PostOrderTraverse

6)后序遍历(非递归):PostOrderTraverseNoRec

7)层序遍历:LevelOrderTraverse

3、寻找从根节点到某一节点的路径:FindNodePath

4、寻找两个节点的最近公共父节点:FindNearestParent

5、重构二叉树

1)根据前序和中序遍历结果重构:RebuildFromPreAndInOrder

2)根据后序和中序遍历结果重构:RebuildFromPostAndInOrder

 

程序如下:

 

#include 
#include 
#include 
#include 

using namespace std;

// 将节点保存的数据类型设为整型
typedef int ElemType;

struct BTreeNode
{
	ElemType elem;		// 当前节点元素
	BTreeNode *left;	// 左孩子结点
	BTreeNode *right;	// 右孩子节点
};

// 往二叉树中插入节点,该方法实际上最后生成的是二叉查找树
void InsertBTree(BTreeNode **root, ElemType elem)
{
	// 如果树为空,则创建
	if (*root == NULL)
	{
		*root = new BTreeNode;
		(*root)->elem  = elem;
		(*root)->left  = NULL;
		(*root)->right = NULL;
		return ;
	}

	BTreeNode *node = *root;
	while (node != NULL)
	{
		if (elem < node->elem)
		{
			if (node->left == NULL)
			{
				BTreeNode *temp = new BTreeNode;
				temp->elem  = elem;
				temp->left  = NULL;
				temp->right = NULL;
				node->left  = temp;
				return ;
			} 
			else
			{
				node = node->left;
			}
		} 
		else
		{
			if (node->right == NULL)
			{
				BTreeNode *temp = new BTreeNode;
				temp->elem  = elem;
				temp->left  = NULL;
				temp->right = NULL;
				node->right = temp;
				return ;
			} 
			else
			{
				node = node->right;
			}
		}
	}
}


// 前序遍历(递归方式)
void PreOrderTraverse(BTreeNode *root)
{
	if (root != NULL)
	{
		cout<elem<<" ";			// 输出该节点值
		PreOrderTraverse(root->left);	// 递归遍历左子树
		PreOrderTraverse(root->right);	// 递归遍历右子树
	}
}

// 前序遍历(非递归方式)
void PreOrderTraverseNoRec(BTreeNode *root)
{
	stack s;

	while (root!=NULL || !s.empty())
	{
		if (root != NULL)
		{
			cout<elem<<" ";
			s.push(root);
			root = root->left;
		} 
		else
		{
			root = s.top()->right;
			s.pop();
		}
	}
}

// 中序遍历(递归方式)
void InOrderTraverse(BTreeNode *root)
{
	if (root != NULL)
	{
		InOrderTraverse(root->left);	// 递归遍历左子树
		cout<elem<<" ";			// 输出该节点值
		InOrderTraverse(root->right);	// 递归遍历右子树
	}
}

// 中序遍历(非递归方式)
void InOrderTraverseNoRec(BTreeNode *root)
{
	stack s;
	
	while (root!=NULL || !s.empty())
	{
		if (root != NULL)
		{
			s.push(root);
			root = root->left;
		} 
		else
		{
			cout<elem<<" ";	// 打印出当前节点值
			root = s.top()->right;		// 将root指向当前节点的右孩子节点
			s.pop();					// 弹出当前节点
		}
	}
}

// 后序遍历(递归方式)
void PostOrderTraverse(BTreeNode *root)
{
	if (root != NULL)
	{
		PostOrderTraverse(root->left);		// 递归遍历左子树
		PostOrderTraverse(root->right);		// 递归遍历右子树
		cout<elem<<" ";				// 输出该节点值
	}
}

// 后序遍历(非递归方式)
void PostOrderTraverseNoRec(BTreeNode *root)
{
	vector v;
	v.push_back(root);
	vector::iterator iter = v.end()-1;	// 此时iter指向根节点

	do 
	{
		if (root != NULL)
		{
			if (root->left != NULL)
			{
				iter = v.insert(iter, root->left) + 1;
			}
			if (root->right != NULL)
			{
				iter = v.insert(iter, root->right) + 1;
			}
		}

		iter--;
		root = *iter;

	} while (iter != v.begin()-1);

	// 输出后序遍历结果
	for (iter=v.begin(); iter!=v.end(); iter++)
	{
		cout<<(*iter)->elem<<" ";
	}

}

// 分层遍历
void LevelOrderTraverse(BTreeNode *root)
{
	queue q;

	while (root != NULL)
	{
		// 输出当前节点,并把当前节点的左右子节点放入队列中
		cout<elem<<" ";
		if (root->left != NULL)
		{
			q.push(root->left);
		} 
		if (root->right != NULL)
		{
			q.push(root->right);
		}

		if (!q.empty())
		{
			root = q.front();
			q.pop();
		} 
		else
		{
			break;
		}
		
	}
}

// 根据前序遍历结果和中序遍历结果重构二叉树
void RebuildFromPreAndInOrder(BTreeNode **root, ElemType preOrder[], ElemType inOrder[], int size)
{
	if (size <= 0)
	{
		return ;
	}

	// 为新节点申请内存空间
	*root = new BTreeNode;
	(*root)->elem  = preOrder[0];
	(*root)->left  = NULL;
	(*root)->right = NULL;

	for (int num=0; numleft), preOrder+1, inOrder, num);
	RebuildFromPreAndInOrder(&((*root)->right), preOrder+num+1, inOrder+num+1, size-num-1);
}

// 根据后序遍历结果和中序遍历结果重构二叉树
void RebuildFromPostAndInOrder(BTreeNode **root, ElemType postOrder[], ElemType inOrder[], int size)
{
	if (size <=0 )
	{
		return ;
	}

	// 为新节点申请内存空间
	*root = new BTreeNode;
	(*root)->elem  = postOrder[size-1];
	(*root)->left  = NULL;
	(*root)->right = NULL;

	for (int num=0; numleft), postOrder, inOrder, num);
	RebuildFromPostAndInOrder(&((*root)->right), postOrder+num, inOrder+num+1, size-num-1);
}


// 找出从根节点到某一节点的路径,保存到 vector path 中
bool FindNodePath(BTreeNode *root, ElemType elem, vector &path)
{
	// 在这个函数中用 vector 实现 stack 的功能

	if (root != NULL)
	{
		path.push_back(root);

		if (root->elem == elem)
		{
			// 找到该节点
			path.assign(path.begin(), path.end());
			return true;
		} 
		else
		{
			if (FindNodePath(root->left, elem, path) == true)
			{
				return true;
			}
			if (FindNodePath(root->right, elem, path) == true)
			{
				return true;
			}
			path.pop_back();
		}
	} 
	
	return false;
}

void FindNearestParent(BTreeNode *root, ElemType elem1, ElemType elem2)
{
	// 保存自根节点到elem1和elem2所在节点的路径
	vector path1, path2;
	FindNodePath(root, elem1, path1);
	FindNodePath(root, elem2, path2);

	// 从两个路径中找出最后一个相同的节点,该节点即最近公共父节点
	vector::iterator iter1 = path1.begin();
	vector::iterator iter2 = path2.begin();
	while ((*iter1)->elem == (*iter2)->elem)
	{
		iter1++;
		iter2++;
	}
	
	cout<<"节点"<elem< path;	// 保存该元素所在节点的路径
	if (FindNodePath(root, elem, path) == true)
	{
		cout<<"元素 "<::iterator iter=path.begin(); iter!=path.end(); iter++)
		{
			cout<<(*iter)->elem<<" ";
		}
		cout<


实际使用的二叉树如下:

执行结果如下:

 

你可能感兴趣的:(Algorithm,C++)