二叉树的前中后遍历,递归与非递归
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode (int x):val(x),left(NULL),right(NULL){}
};
递归
先序遍历:
void PreOrderTraversal(TreeNode* root) {
if (!root) {
return;
}
cout << root->val << " ";
PreOrderTraversal(root->left);
PreOrderTraversal(root->right);
}
中序遍历
void InOrderTraversal(TreeNode* root) {
if (!root) {
return;
}
InOrderTraversal(root->left);
cout << root->val << " ";
InOrderTraversal(root->right);
}
后序遍历
void PostOrderTraversal(TreeNode* root) {
if (!root) {
return;
}
PostOrderTraversal(root->left);
PostOrderTraversal(root->right);
cout << root->val << " ";
}
这三个遍历大同小异,仅仅只是输出的位置不同而已。
对于新手如果做牛客或者力扣上面的题的话,你除了把函数与变量名字改了之外,在函数中定义一个 vector result, 然后将所有的输出换成 result.push_back(root->val),再加上return result;即可。
非递归方式
非递归的方式遍历主要是依靠栈实现:
先序遍历:
vector<int> PreOrderTra(TreeNode* root) {
vector<int>result;
if (root == NULL) return result;
stack<TreeNode*>s;
TreeNode* p = root;
while (p != NULL || !s.empty()) {
while (p != NULL) { //遍历左子树
result.push_back(p->val);
s.push(p); //把遍历的节点全部压栈。
p = p->left;
}
if (!s.empty()) {
p = s.top(); //得到栈顶内容
s.pop(); //出栈
p = p->right; //指向右子节点,下一次循环时,就会先续遍历左子树
}
}
return result;
}
中序遍历
vector<int> InOrderTra(TreeNode* root) {
vector<int>result;
if (root == NULL) return result;
stack<TreeNode*>s;
TreeNode* p = root;
while (p != NULL || !s.empty()) {
while (p != NULL) { //遍历左子树
s.push(p); //把遍历的节点全部压栈。
p = p->left;
}
if (!s.empty()) {
p = s.top(); //得到栈顶内容
s.pop(); //出栈
result.push_back(p->val);
p = p->right; //指向右子节点,下一次循环时,就会先续遍历左子树
}
}
return result;
}
后序遍历
后序遍历和前面有所不同
后序遍历需要在遍历完左右子树之后再访问根节点。因此需要判断根节点的左右子树是否均被遍历过
可采用标记法,节点入栈时,配一个标志tag一同入栈(tag为0表示遍历左子树前的现场保护,tag为1表示遍历右子树前的现场保护)
首先将T和tag(为0)入栈,遍历左子树;返回后,修改栈顶tag为1,遍历右子树;最后访问根节点
struct TreeNode {
int val;
int tag;
TreeNode* left;
TreeNode* right;
TreeNode (int x):val(x),tag(0),left(NULL),right(NULL){}
};
vector<int> PostOrderTra(TreeNode* root) {
vector<int>result;
if (root == NULL) return result;
stack<TreeNode*>s;
TreeNode* p = root;
while (p != NULL || !s.empty()) {
while (p != NULL) { //遍历左子树
s.push(p); //把遍历的节点全部压栈。
p = p->left;
}
if (!s.empty()) {
p = s.top(); //得到栈顶内容
if (p->tag) { //tag为1时
result.push_back(p->val);
s.pop(); //出栈
p = NULL; //第二次访问标志其柚子树已经遍历
}
else {
p->tag = 1; //修改tag为1
p = p->right; //指向右节点,下次遍历其左子树
}
}
}
return result;
}
//层次遍历
vector<int> LeveOrderTra(TreeNode* root) {
vector<int>result;
queue<TreeNode*>q;
TreeNode* ptr = NULL;
q.push(root); //根节点入队
while (!q.empty()) {
ptr = q.front(); //得到头结点
q.pop();
result.push_back(ptr->val);
if (ptr->left != NULL) { //当前节点存在左节点则左节点入队
q.push(ptr->left);
}
if (ptr->right != NULL) { //当前节点存在右节点则右节点入队
q.push(ptr->right);
}
}
return result;
}