本文总结了二叉树的相关操作,并在最后附上所有操作的实现。还有不足之处,以后会及时更新~
相关操作包括:
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 <iostream>
#include <stack>
#include <queue>
#include <vector>
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<<root->elem<<" "; // 输出该节点值
PreOrderTraverse(root->left); // 递归遍历左子树
PreOrderTraverse(root->right); // 递归遍历右子树
}
}
// 前序遍历(非递归方式)
void PreOrderTraverseNoRec(BTreeNode *root)
{
stack<BTreeNode *> s;
while (root!=NULL || !s.empty())
{
if (root != NULL)
{
cout<<root->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<<root->elem<<" "; // 输出该节点值
InOrderTraverse(root->right); // 递归遍历右子树
}
}
// 中序遍历(非递归方式)
void InOrderTraverseNoRec(BTreeNode *root)
{
stack<BTreeNode *> s;
while (root!=NULL || !s.empty())
{
if (root != NULL)
{
s.push(root);
root = root->left;
}
else
{
cout<<s.top()->elem<<" "; // 打印出当前节点值
root = s.top()->right; // 将root指向当前节点的右孩子节点
s.pop(); // 弹出当前节点
}
}
}
// 后序遍历(递归方式)
void PostOrderTraverse(BTreeNode *root)
{
if (root != NULL)
{
PostOrderTraverse(root->left); // 递归遍历左子树
PostOrderTraverse(root->right); // 递归遍历右子树
cout<<root->elem<<" "; // 输出该节点值
}
}
// 后序遍历(非递归方式)
void PostOrderTraverseNoRec(BTreeNode *root)
{
vector<BTreeNode *> v;
v.push_back(root);
vector<BTreeNode *>::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<BTreeNode *> q;
while (root != NULL)
{
// 输出当前节点,并把当前节点的左右子节点放入队列中
cout<<root->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; num<size; num++)
{
if (inOrder[num] == preOrder[0])
{
break;
}
}
RebuildFromPreAndInOrder(&((*root)->left), 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; num<size; num++)
{
if (inOrder[num] == postOrder[size-1])
{
break;
}
}
RebuildFromPostAndInOrder(&((*root)->left), postOrder, inOrder, num);
RebuildFromPostAndInOrder(&((*root)->right), postOrder+num, inOrder+num+1, size-num-1);
}
// 找出从根节点到某一节点的路径,保存到 vector<BTreeNode *> path 中
bool FindNodePath(BTreeNode *root, ElemType elem, vector<BTreeNode *> &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<BTreeNode *> path1, path2;
FindNodePath(root, elem1, path1);
FindNodePath(root, elem2, path2);
// 从两个路径中找出最后一个相同的节点,该节点即最近公共父节点
vector<BTreeNode *>::iterator iter1 = path1.begin();
vector<BTreeNode *>::iterator iter2 = path2.begin();
while ((*iter1)->elem == (*iter2)->elem)
{
iter1++;
iter2++;
}
cout<<"节点"<<elem1<<"和"<<elem2<<"的最近公共父节点是:"<<(*(iter1-1))->elem<<endl;
}
// 测试上述函数
void main()
{
// 定义树的根节点
BTreeNode *root = NULL;
// 初始化树
int tree[] = {36, 25, 57, 11, 30, 27};
for (int i=0; i<sizeof(tree)/sizeof(int); i++)
{
InsertBTree(&root, tree[i]);
}
/************************************************************************/
/* 遍历二叉树 */
/************************************************************************/
cout<<"前序遍历(递归):\t";
PreOrderTraverse(root);
cout<<endl;
cout<<"前序遍历(非递归):\t";
PreOrderTraverseNoRec(root);
cout<<endl;
cout<<"中序遍历(递归):\t";
InOrderTraverse(root);
cout<<endl;
cout<<"中序遍历(非递归):\t";
InOrderTraverseNoRec(root);
cout<<endl;
cout<<"后序遍历(递归):\t";
PostOrderTraverse(root);
cout<<endl;
cout<<"后序遍历(非递归):\t";
PostOrderTraverseNoRec(root);
cout<<endl;
cout<<"层序遍历:\t";
LevelOrderTraverse(root);
cout<<endl;
/************************************************************************/
/* 重构二叉树 */
/************************************************************************/
BTreeNode *root1 = NULL;
BTreeNode *root2 = NULL;
ElemType preOrder[] = {36, 25, 11, 30, 27, 57};
ElemType inOrder[] = {11, 25, 27, 30, 36, 57};
ElemType postOrder[] = {11, 27, 30, 25, 57, 36};
RebuildFromPreAndInOrder(&root1, preOrder, inOrder, 6);
RebuildFromPostAndInOrder(&root2, postOrder, inOrder, 6);
// 前序遍历,已验证重建的正确性
cout<<"根据前序和中序便利结果,重构后的二叉树前序遍历结果是:";
PreOrderTraverse(root1);
cout<<endl;
cout<<"根据后序和中序便利结果,重构后的二叉树前序遍历结果是:";
PreOrderTraverse(root2);
cout<<endl;
/************************************************************************/
/* 查找某一元素是否在二叉树中,如果在打印自根节点到该节点的路径 */
/************************************************************************/
ElemType elem = 27; // 假设要查找的元素是27
vector<BTreeNode *> path; // 保存该元素所在节点的路径
if (FindNodePath(root, elem, path) == true)
{
cout<<"元素 "<<elem<<" 所在节点的路径是:";
for (vector<BTreeNode *>::iterator iter=path.begin(); iter!=path.end(); iter++)
{
cout<<(*iter)->elem<<" ";
}
cout<<endl;
}
else
{
cout<<"元素 "<<elem<<" 不在该二叉树中"<<endl;
}
/************************************************************************/
/* 查找某两个节点的最近公共父节点 */
/************************************************************************/
ElemType elem1 = 57, elem2 = 27;
FindNearestParent(root, elem1, elem2);
}
实际使用的二叉树如下:
执行结果如下: