使用java实现二叉树的非递归遍历

在前面的一片博客中已经介绍了二叉树遍历的一些概念以及注意事项,如果有疑惑的可以回过头看一看。

https://blog.csdn.net/qq_41300571/article/details/83010364

这里我们主要讨论的是使用非递归的算法实现二叉树的遍历

前序遍历:

思路:

1.使用一个栈来存储元素,刚开始的时候将栈顶元素压入栈

2.当栈不为空的时候做如下操作:弹出栈顶元素并遍历,依次将出栈结点的右孩子和左孩子入栈

代码:

//非递归前序遍历二叉树
	public static void printTree1(Node root){
		SequenceStack stack=new SequenceStack();
		List list=new ArrayList();
		//首先先把根节点压栈
		stack.push(root);
		//当栈不为空的时候循环遍历
		while(!stack.isEmpty()){
			//弹出栈顶元素
			Node node=stack.pop();
			//遍历栈顶元素
			list.add(node);
			//如果栈顶元素的右孩子不为空,则进栈
			if(node.right!=null){
				stack.push(node.right);
			}
			//如果栈顶元素的左孩子不为空,则进栈
			if(node.left!=null){
				stack.push(node.left);
			}
			
		}
		System.out.println(list);
	}

中序遍历:

思路:

1.刚开始先把根节点压入栈,往后每次判断节点不为空则入栈

2.弹出栈顶元素并遍历,判断栈顶元素是否存在右孩子结点,根据结果进行相应的操作

             有:继续将右孩子结点压栈

             无:继续出栈

代码:

//采用非递归中序遍历二叉树
	public static void printTree(Node root){
		SequenceStack stack=new SequenceStack();
		List list=new ArrayList();
		Node node=root;
		//刚开始先把根节点压入栈,往后每次判断节点不为空则压栈
		do {
			while(node!=null){
				stack.push(node);
				node=node.left;
			}
			node=stack.pop();
			list.add(node);
			//如果出栈的结点存在右节点,则指向该节点
			if(node.right!=null){
				node=node.right;
			}else{//否则设置为空,下次循环继续出栈
				node=null;
			}//当栈不为空,或者当前节点引用不为空时循环
		} while (!stack.isEmpty()||node!=null);
		System.out.println(list);
	}

后序遍历:

思路:

1.将根节点以及左结点依次入栈

2.获取栈顶元素,对栈顶元素进行右孩子判断,诺为空,则遍历栈顶元素并弹出栈,否则指向右孩子结点

3.重复1-2两步

      重点:这里需要注意pre变量在遍历过程中的作用(下方代码有详细注释该变量的作用)

代码:

//非递归实现后序遍历
	public static void printTree2(Node root){
		SequenceStack stack=new SequenceStack();
		List list=new ArrayList();
		//定义两个节点变量node和pre(这里需要注意pre节点的作用,下方的注释有详细地介绍)
		Node node=root;
		Node pre=null;
		do {
			//将左结点一次压入栈
			while(node!=null){
				stack.push(node);
				node=node.left;
			}
			//获取栈顶节点
			node = stack.get();
			//如果栈顶节点的右孩子不为空,说明还得把右子树压入栈中,这里需要注意
			//node.right!=pre这个条件,因为我们在遍历的过程中,对于(子树)根节点的判断会存在两次
			//第一次是弹出左孩子节点后,对根节点进行是否有右孩子的判断,如果有,则将右孩子压栈
			//第二次是弹出右孩子节点后,这时候因为循环的原因(代码的原因),我们再次对根节点进行了右孩子判断,
			//所以这里就必须得判断该右孩子节点是否在之前的循环中已经判断过了,如果判断过了,则弹出根节点,否则压入右孩子节点。
			//总的来说,pre节点的作用是用来防止重复遍历右孩子节点的。
			if(node.right!=null&&node.right!=pre){
				//node指向右孩子节点
				node=node.right;
			}else{//只要有一个条件不满足则执行
				//弹出栈顶元素
				node=stack.pop();
				//遍历栈顶元素
				list.add(node);
				//将pre指向当前弹出的元素,用来做下次对根节点的再次判断时,右孩子不重复遍历的一个条件
				pre=node;
				//将node设置为null,防止根节点重复压入左孩子节点。
				node=null;
			}
			
		} while (node!=null||!stack.isEmpty());
		System.out.println(list);
	}

 

你可能感兴趣的:(使用java实现二叉树的非递归遍历)