所用代码 java
前序遍历:根 => 左 => 右
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
preorder(root, list);
return list;
}
public void preorder(TreeNode root, List<Integer> list){
if (root == null) {
return ;
}
// 根
list.add(root.val);
// 左
preorder(root.left, list);
// 右
preorder(root.right, list);
}
中序遍历: 左 => 根 => 右
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
inorder(root, list);
return list;
}
public void inorder(TreeNode root, List<Integer> list){
if (root == null) {
return ;
}
// 左
inorder(root.left, list);
// 根
list.add(root.val);
// 右
inorder(root.right, list);
}
后序遍历: 左 => 右 => 根
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
postorder(root, list);
return list;
}
public void postorder(TreeNode root, List<Integer> list){
if (root == null) {
return ;
}
// 左
postorder(root.left, list);
// 右
postorder(root.right, list);
// 根
list.add(root.val);
}
其实java实现递归是用栈,所以我们可以利用栈的特性来完成非递归的遍历
前序遍历:根 => 左 => 右
public List<Integer> preorderTraversal(TreeNode root) {
// 迭代法
List<Integer> list = new ArrayList<>();
if (root == null){
return list;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()){
// 每次把压入栈的元素取出来(根)以右左的方式压入,取就是左右
TreeNode node = stack.pop();
list.add(node.val);
// 先加右结点
if (node.right != null){
stack.push(node.right);
}
if (node.left != null){
stack.push(node.left);
}
}
return list;
}
后序遍历: 左 => 右 => 根
由于前序是 根左右,然后我们可以在前序的基础上使得输入为 根右左,再把链表反转,就变成了左右根
public List<Integer> postorderTraversal(TreeNode root) {
// 迭代法
List<Integer> list = new ArrayList<>();
if (root == null){
return list;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()){
// 每次以左右压出栈,取出时便是 根右左
TreeNode node = stack.pop();
list.add(node.val);
// 先加入左结点
if (node.left != null){
stack.push(node.left);
}
if (node.right != null){
stack.push(node.right);
}
}
// 链表反转:根右左 => 左右根
Collections.reverse(list);
return list;
}
中序遍历: 左 => 根 => 右
中序遍历和前后不同,因为每次根结点需要记录,但不是第一个输出,所以我们需要一个辅助的指针来记录遍历的位置。当指针为null时,证明该结点的左孩子为null了,就把栈顶元素弹出(若该结点是叶子结点,就是二叉树的左,否则就为中),然后往右搜索(相当于 右),然后按顺序加入list。
public List<Integer> inorderTraversal(TreeNode root) {
// 迭代法
List<Integer> list = new ArrayList<>();
if (root == null){
return list;
}
Stack<TreeNode> stack = new Stack<>();
// 定义一个指针进行辅助位置指向
TreeNode cur = root;
while (cur != null || !stack.isEmpty()){
if (cur != null){
// cur所指的结点不为空就直接加入栈
stack.push(cur);
// 然后继续向左搜索( 左 )
cur = cur.left;
}else {
// 为空就弹出栈里面结点( 中 )
cur = stack.pop();
// 并加入列表
list.add(cur.val);
// 搜索完左孩子后往右搜索 ( 右 )
cur = cur.right;
}
}
return list;
}
前序遍历:根 => 左 => 右
public List<Integer> preorderTraversal(TreeNode root) {
// 迭代法
List<Integer> list = new ArrayList<>();
if (root == null){
return list;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()){
TreeNode node = stack.peek();
if (node != null){
// 先弹出栈顶的结点
stack.pop();
// 再以 右左 的顺序加入
if (node.right != null){
stack.push(node.right);
}
if (node.left != null){
stack.push(node.left);
}
// 再加入 根 结点
stack.push(node);
// 加入根结点后添加一个标识符 null
stack.push(null);
}else {
// 遇到标志符null,证明下一个结点是根结点(叶子结点也可以看成根结点)
// 先弹出null
stack.pop();
// 再把该结点的值加入列表
int num = stack.pop().val;
list.add(num);
}
}
return list;
}
中序遍历: 左 => 根 => 右
public List<Integer> inorderTraversal(TreeNode root) {
// 迭代法
List<Integer> list = new ArrayList<>();
if (root == null){
return list;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()){
TreeNode node = stack.peek();
if (node != null){
// 先弹出栈顶的结点
stack.pop();
// 以 右 中 左 的顺序加入
if (node.right != null){
stack.push(node.right);
}
// 加入 根 结点
stack.push(node);
// 加入根结点后添加一个标识符 null
stack.push(null);
if (node.left != null){
stack.push(node.left);
}
}else {
// 遇到标志符null,证明下一个结点是根结点(叶子结点也可以看成根结点)
// 先弹出null
stack.pop();
// 再把该结点的值加入列表
int num = stack.pop().val;
list.add(num);
}
}
return list;
}
后序遍历: 左 => 右 => 根
public List<Integer> postorderTraversal(TreeNode root) {
// 迭代法
List<Integer> list = new ArrayList<>();
if (root == null){
return list;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()){
TreeNode node = stack.peek();
if (node != null){
// 先弹出栈顶的结点
stack.pop();
// 再以 中 右 左 的顺序加入
// 加入 根 结点
stack.push(node);
// 加入根结点后添加一个标识符 null
stack.push(null);
// 右
if (node.right != null){
stack.push(node.right);
}
// 左
if (node.left != null){
stack.push(node.left);
}
}else {
// 遇到标志符null,证明下一个结点是根结点(叶子结点也可以看成根结点)
// 先弹出null
stack.pop();
// 再把该结点的值加入列表
int num = stack.pop().val;
list.add(num);
}
}
return list;
}
public List<Integer> postorderTraversal(TreeNode root) {
// 迭代法
List<Integer> list = new ArrayList<>();
if (root == null){
return list;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()){
TreeNode node = stack.peek();
if (node != null){
// 先弹出栈顶的结点
stack.pop();
// 加入顺序: 若前序(根左右)就 根右左 加入
stack.push(node);
// 加入根结点再加入一个标志符,第一个弹出(因为叶子结点也是根结点,不管左还是右)
stack.push(null);
// 加入右节点
if (node.right != null){
stack.push(node.right);
}
// 加入左节点
if (node.left != null){
stack.push(node.left);
}
}else {
// 遇到标志符null,证明下一个结点是根结点(叶子结点也可以看成根结点)
// 先弹出null
stack.pop();
// 再把该结点的值加入列表
int num = stack.pop().val;
list.add(num);
}
}
return list;
}