二叉树的前中后序的遍历
链接:
144.二叉树的前序遍历 . - 力扣(LeetCode)
94.二叉树的中序遍历 . - 力扣(LeetCode)
145.二叉树的后序遍历 . - 力扣(LeetCode)
递归遍历
使用递归的方法来进行解决
递归函数的实现注意事项:
1.注意递归函数的参数和返回值类型
2.注意递归函数的终止条件
3.确定每一次递归需要处理的东西
代码实现:
/** * Definition for a binary tree node. * struct TreeNode { * int val; * struct TreeNode *left; * struct TreeNode *right; * }; */ /** * Note: The returned array must be malloced, assume caller calls free(). */ //前序遍历 void previous(struct TreeNode *root, int *res, int *returnSize) { if(root == NULL) return ; res[(*returnSize)++] = root->val; previous(root->left,res,returnSize); previous(root->right,res,returnSize); } //中序遍历 void middle(struct TreeNode* root,int *res, int* returnSize) { if(!root) return; middle(root->left,res,returnSize); res[(*returnSize)++] = root->val; middle(root->right,res,returnSize); } //后序遍历 void behind(struct TreeNode* root, int *res, int* returnSize) { if(root == NULL) return ; behind(root->left,res,returnSize); behind(root->right,res,returnSize); res[(*returnSize)++] = root->val; } //将遍历的结果存放到数组中 int* preorderTraversal(struct TreeNode* root, int* returnSize) { int *res = malloc(sizeof(int)*200); *returnSize = 0; previous(root,res,returnSize); return res; }
迭代法遍历
前序遍历
前序遍历是先访问根节点,再依次遍历左子树,最后遍历右子树,即中左右
我们要使用迭代来进遍历,可以使用栈的结构来进行模拟
我们先进行找到根节点的位置,存入数组中,并进行入栈操作,依次访问其左子树,并将其左子树作为新的根节点继续访问其左子树,直到该结点为叶子节点,找到该节点的父结点,再通过父节点去遍历其右子树,这个栈是用来记录当前节点的父节点的位置的
代码实现:
/** * Definition for a binary tree node. * struct TreeNode { * int val; * struct TreeNode *left; * struct TreeNode *right; * }; */ /** * Note: The returned array must be malloced, assume caller calls free(). */ int* preorderTraversal(struct TreeNode* root, int* returnSize) { int *res = (int *)malloc(sizeof(int)*100); *returnSize = 0; if(!root) return res; struct TreeNode *stack[100];//显式定义了一个栈,用来存储数的节点 struct TreeNode *node = root; //指向要访问的节点 int top = 0; //栈顶指针 //只要栈不为空或者节点不为空 while(top > 0 || node) { while(node) { //将当前结点的值存入要返回的数组中并入栈,更新当前的结点 res[(*returnSize)++] = node->val; stack[top++] = node; node = node->left; } //让当前节点返回到其父节点,再查找到它的右子树 node = stack[--top]; node = node->right; } return res; }
后序遍历
后序遍历是先遍历左子树,再遍历右子树,最后访问根节点
使用一个结点来记录左右节点都为空或者已经访问的节点
/** * Definition for a binary tree node. * struct TreeNode { * int val; * struct TreeNode *left; * struct TreeNode *right; * }; */ /** * Note: The returned array must be malloced, assume caller calls free(). */ int* postorderTraversal(struct TreeNode* root, int* returnSize) { //定义数组存储遍历出的结果 int *res = malloc(sizeof(int) *100); *returnSize = 0; //使用栈来存储二叉树的节点 struct TreeNode *stack[100]; int top = 0; //当节点的右子树为空,记录该节点 struct TreeNode *node = NULL; if(!root) return res; while( root!=NULL || top > 0) { //遍历左子树,并存入栈中 while(root!=NULL) { stack[top++] = root; root = root->left; } //如果当前结点为空,进行出栈,返回当前节点的上一个节点 root = stack[--top]; //右子树为空,或者当前结点的右子树已经被访问过,存储该节点到数组中 if(root->right == NULL|| root->right == node) { res[(*returnSize)++] = root->val; node = root; //记录当前节点的位置 root = NULL; } else { //遍历该结点的右子树,实现入栈存储 stack[top++] = root; root = root->right; } } return res; }
中序遍历
栈实现:记录遍历过的元素
先遍历根节点的左子树,只要当前节点的左孩子不为空,就将当前访问的元素加入到栈里,只要当前访问的节点为空,则出栈栈顶元素并存入数组中,此时再访问栈顶元素的右孩子,如果右孩子也为空,那么就依次弹出元素,加入数组里,如果右孩子不为空,则右孩子加入到栈里,再遍历该右孩子的左孩子和右孩子
/** * Definition for a binary tree node. * struct TreeNode { * int val; * struct TreeNode *left; * struct TreeNode *right; * }; */ /** * Note: The returned array must be malloced, assume caller calls free(). */ int* inorderTraversal(struct TreeNode* root, int* returnSize) { int *res = (int *)malloc(sizeof(int)*100); *returnSize = 0; if(!root) return res; struct TreeNode *stack[100]; int top = 0; struct TreeNode *node = root; //遍历二叉树 while(node || top > 0) { //先访问完左子树 if(node) { stack[top++] = node; node = node->left; } else { //左子树为空,退回父节点,出栈,访问其右孩子 node = stack[--top]; res[(*returnSize)++] = node->val; node = node->right; } } return res; }
实现过程如下图