本文用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++