概述
本文用C++语言写了二叉树的基本操作,包括二叉树的四种遍历方式的递归和非递归写法,二叉查找树的插入,删除,构建,路径搜索,序列化和反序列化,是否镜像等操作,仅供参考。
#include<iostream>
#include<stack>
#include<queue>
#include<vector>
#include<string>
using namespace std;
struct TreeNode
{
TreeNode *left, *right;
int val;
TreeNode(int x) :val(x), left(NULL), right(NULL){}
};
//前序遍历的递归写法
void helper1(TreeNode *root, vector<int> &res)
{
if (!root) return;
res.push_back(root->val);
helper1(root->left, res);
helper1(root->right, res);
}
vector<int> preTraversalRecur(TreeNode *root)
{
vector<int> res;
helper1(root, res);
return res;
}
//前序遍历的非递归写法
vector<int> preTraversalNonrecur(TreeNode *root)
{
vector<int> res;
if (!root) return res;
stack<TreeNode *> s;
TreeNode *p = root;
while (!s.empty() || p != NULL)
{
while (p != NULL)
{
res.push_back(p->val);
s.push(p);
p = p->left;
}
if (!s.empty())
{
p = s.top();
s.pop();
p = p->right;
}
}
return res;
}
//中序遍历的递归写法
void helper2(TreeNode *root, vector<int> &res)
{
if (!root) return;
helper2(root->left, res);
res.push_back(root->val);
helper2(root->right, res);
}
vector<int> inTraversalRecur(TreeNode *root)
{
vector<int> res;
helper2(root, res);
return res;
}
vector<int> inTraversalNonrecur(TreeNode *root)
{
vector<int> res;
if (!root) return res;
TreeNode *p = root;
stack<TreeNode *> s;
while (!s.empty() || p != NULL)
{
while (p != NULL)
{
s.push(p);
p = p->left;
}
if (!s.empty())
{
p = s.top();
s.pop();
res.push_back(p->val);
p = p->right;
}
}
return res;
}
//后序遍历递归写法
void helper3(TreeNode *root, vector<int> &res)
{
if (!root) return;
helper3(root->left, res);
helper3(root->right, res);
res.push_back(root->val);
}
vector<int> postTraversalRecur(TreeNode *root)
{
vector<int> res;
helper3(root, res);
return res;
}
//后序遍历非递归写法
vector<int> postTraversalNonrecur(TreeNode *root)
{
vector<int> res;
if (!root) return res;
stack<TreeNode *> s;
TreeNode *pre=NULL, *cur;
s.push(root);
while (!s.empty())
{
cur = s.top();
//如果当前节点是叶子节点或者当前节点的左右子节点都被访问过了,可以用前驱节点是其左右子节点来判断
if ((cur->left == NULL && cur->right == NULL) || (pre != NULL && (pre == cur->left || pre == cur->right)))
{
res.push_back(cur->val); //访问该节点
pre = cur; // 使得该节点成为前驱结点
s.pop(); //将该节点从栈中弹出
}
//如果当前节点现在不能被访问,则将其右节点和左子节点依次放进栈中
else
{
if(cur->right!=NULL) s.push(cur->right);
if(cur->left!=NULL) s.push(cur->left);
}
}
return res;
}
//层序遍历,基本思想是队列,一层一层地遍历
vector<int> fromToptoBottom(TreeNode *root)
{
vector<int> res;
queue<TreeNode *> q;
if (!root) return res;
q.push(root);
while (!q.empty())
{
TreeNode *p = q.front();
q.pop();
res.push_back(p->val);
if (p->left) q.push(p->left);
if (p->right) q.push(p->right);
}
return res;
}
//二叉查找树的查找,保存路径到数组中,找到返回true,没找到就返回false
bool bstSearch(TreeNode *root, int value, vector<int> &res)
{
if (root == NULL) return false; //如果根节点为空,则返回false
res.push_back(root->val); //将根节点的值放到结果数组中
if (value == root->val) return true; //根节点的值等于该值,返回true;
else if (value < root->val)
{
return bstSearch(root->left, value, res);
}
else
{
return bstSearch(root->right, value, res);
}
}
//二叉树的查找,注意,不是二叉查找树,因此没有大小比较的关系
bool getPathFromRoot(TreeNode *root, int value, vector<int> &path)
{
if (root == NULL) return false;
path.push_back(root->val);
if (root->val == value) return true;
if (getPathFromRoot(root->left, value, path)) //如果左子树走通了,返回true;
return true;
if (getPathFromRoot(root->right, value, path)) //如果右子树走通了,返回true;
return true;
path.pop_back();
return false;
}
//二叉查找树的插入
bool bstInsert(TreeNode *&root, int value)
{
if (root == NULL)
{
root = new TreeNode(value);
return true;
}
else if (value < root->val)
{
return bstInsert(root->left, value);
}
else if (value > root->val)
{
return bstInsert(root->right, value);
}
return false;
}
//用数组构建二叉查找树
TreeNode *createBST(vector<int> &list)
{
int n = list.size();
if (n == 0) return NULL;
TreeNode *root = NULL;
for (int i = 0; i < n; i++)
{
if (!bstInsert(root, list[i]))
{
cout << list[i] << "已经存在在二叉查找树中了" << endl;
}
}
return root;
}
//二叉查找树的删除
/*
需要删除的节点下面没有子节点,则直接删除
删除节点下面有一个左子节点/右子节点:删除该节点,并将左/右子树连接在其父节点上
删除节点的左右子节点都存在:找出此节点右子树中的最小节点,替换该节点,然后删除该最小节点。
*/
TreeNode *removeBST(TreeNode *root, int value)
{
if (value < root->val)
root->left = removeBST(root->left, value);
else if (value>root->val)
root->right = removeBST(root->right, value);
else
{
if (root->left == NULL || root->right == NULL)
{
root = root->left == NULL ? root->right : root->left;
}
else //左右子树都不为空
{
TreeNode *p = root->right;
while (p->left != NULL)
{
p = p->left;
}
root->val = p->val;
root->right = removeBST(root->right, p->val);
}
}
return root;
}
//二叉树序列化,将一棵树序列化为一个字符串,先序遍历,递归来做
string treetoString(TreeNode *root)
{
string res = "";
if (root == NULL)
{
res += "#,";
return res;
}
res += to_string(root->val);
res += ',';
res += treetoString(root->left);
res += treetoString(root->right);
return res;
}
//序列化之后返回的是char * 该咋办?
char *serialize(TreeNode *root)
{
string s = treetoString(root);
char *res = new char[s.size() + 1];
strcpy(res, s.c_str()); // c_str()的方法把这个string转换成 const char*类型
return res;
}
//二叉树的反序列化
/*
atoi()和stoi()的区别----数字字符串的处理
相同点:
①都是C++的字符处理函数,把数字字符串转换成int输出
②头文件都是#include<cstring>
不同点:
①atoi()的参数是 const char* ,因此对于一个字符串str我们必须调用 c_str()的方法把这个string转换成 const char*类型的,而stoi()的参数是const string*,不需要转化为 const char*;
*/
TreeNode *stringToTree(string &s)
{
if (s.empty())
{
return NULL;
}
if (s[0] == '#') //根节点为NULL,则这棵树为空
{
s = s.substr(2); //删除两个字符#,
return NULL;
}
TreeNode *node = new TreeNode(stoi(s));//将数字字符转换为数字,遇到!停下来
s = s.substr(s.find_first_of(',') + 1); //截取!之后的字符串部分
node->left = stringToTree(s);
node->right = stringToTree(s);
return node;
}
TreeNode *Deserialize(char *str)
{
string s(str);
return stringToTree(s);
}
//判断一棵树是不是镜像对称的
bool symmetric(TreeNode *p, TreeNode *q)
{
if (p == NULL && q == NULL) return true;
if (!p || !q) return false;
return (p->val == q->val && (symmetric(p->left, q->right) && symmetric(p->right, p->left)));
}
bool isSymmetric(TreeNode *root)
{
if (root == NULL) return true;
return symmetric(root->left, root->right);
}
int main()
{
vector<int> list = { 4, 1, 5, 6, 2, 3, 8, 9 };
TreeNode *root = createBST(list);
string s = treetoString(root);
cout << s << endl;
root = stringToTree(s);
vector<int> res;
if (getPathFromRoot(root, 8, res))
{
for (int i = 0; i < res.size(); i++)
cout << res[i] << " ";
cout << endl;
}
vector<int> temp;
if (bstSearch(root, 8, temp))
{
for (int i = 0; i < temp.size(); i++)
cout <<temp[i] << " ";
cout << endl;
}
system("pause");
return 0;
}
最后
以上就是冷傲大门为你收集整理的二叉树的基本操作C++的全部内容,希望文章能够帮你解决二叉树的基本操作C++所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复