前序 中序 后序 遍历 递归 非递归算法 java实现

这篇博客详细介绍了二叉树的前序、中序和后序遍历的递归与非递归算法实现,包括前序遍历的非递归方法、前序遍历的递归方法、中序遍历的非递归和递归方法,以及后序遍历的非递归和递归策略,全部使用Java语言进行编程实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前序遍历 非递归

 

	public void preordernorec(TreeNode root){
		//System.out.println("先序遍历(非递归):");
		//用数组模拟栈,假设有节点个数不超过32个
		TreeNode[] stack = new TreeNode[32];
		for(int i =0;i<32;i++){
			stack[i] = null;
		}
		int index =0;
		TreeNode pnode = root;
		while(pnode!=null||index>0){
			while(pnode!=null){
				System.out.print(pnode.getKey()+",");
				stack[index++] = pnode;				
				pnode = pnode.getLeftchlid();
			}
			pnode = stack[--index];
			pnode = pnode.getRightchild();
		}
		//System.out.println("");
	}


 

前序遍历 递归

public void preorder(TreeNode root){
		
		if(root!=null){
			System.out.print(root.getKey()+",");
			preorder(root.getLeftchlid());
			preorder(root.getRightchild());
		}
	}


 

中序遍历 非递归

	public void inordernorec(TreeNode root){
		TreeNode[] stack = new TreeNode[32];
		int index=0;
		for(int i =0;i<32;i++){
			stack[i] = null;
		}
		TreeNode pnode = root;
		while(pnode!=null||index>0){
			while(pnode!=null){
				stack[index++] = pnode;
				pnode = pnode.getLeftchlid();
			}
			pnode = stack[--index];
			System.out.print(pnode.getKey()+",");
			pnode = pnode.getRightchild();
		}
		
		//System.out.println("");
	}


 

中序遍历 递归

 

public void inorder(TreeNode root){
		
		if(root!=null){
			
			inorder(root.getLeftchlid());
			System.out.print(root.getKey()+",");
			inorder(root.getRightchild());
		}
	}


 

后序遍历 非递归

 

public void postordernorec(TreeNode root){
	TreeNode[] stack = new TreeNode[32];
	int index=0;
	for(int i =0;i<32;i++){
		stack[i] = null;
	}
	TreeNode pnode = root;
	TreeNode LastVisit = null;
	while(pnode!=null||index>0){
		while(pnode!=null){
			stack[index++] = pnode;
			pnode = pnode.getLeftchlid();
		} 
		pnode=stack[index-1];
		if(pnode.getRightchild()==null||pnode.getRightchild()==LastVisit){
			System.out.print(pnode.getKey()+",");
			LastVisit = pnode;
			index--;
			pnode = null;
		}
		else
		{
			pnode = pnode.getRightchild();
		}
	}
}


 

后序遍历 递归

public void postorder(TreeNode root){
	if(root!=null){
		postorder(root.getLeftchlid());
		postorder(root.getRightchild());
		System.out.print(root.getKey()+",");
	}
}


 

 

### 使用栈实现二叉树非递归遍历 #### 数据结构定义 为了实现二叉树的非递归遍历,首先需要定义二叉树节点的数据结构。通常情况下,一个简单的二叉树节点可以表示如下: ```java class TreeNode { int val; TreeNode left; TreeNode right; public TreeNode(int x) { this.val = x; this.left = null; this.right = null; } } ``` 此数据结构用于保存每个节点的信息及其左右子节点指针。 #### 前序遍历 (Preorder Traversal) 前序遍历遵循访问根节点—左子树—右子树的原则。通过使用显式的栈来模拟函数调用的过程,可以在不依赖于递归的情况下完成这一操作[^1]。 ```java public List<Integer> preorderTraversal(TreeNode root) { Stack<TreeNode> stack = new Stack<>(); List<Integer> result = new ArrayList<>(); if (root == null) return result; TreeNode current = root; while (!stack.isEmpty() || current != null) { while (current != null) { // 访问当前节点并压入其左孩子到栈中 result.add(current.val); // 处理当前节点 stack.push(current); current = current.left; } current = stack.pop(); // 当左边走不通时回溯至最近的一个未处理过的节点 current = current.right; // 转向右边继续探索 } return result; } ``` 这段代码展示了如何利用栈来进行前序遍历,并记录下每次遇到的新节点值。 #### 中遍历 (Inorder Traversal) 中遍历则按照左子树—根节点—右子树这样的顺进行。同样地,这里也采用了一个辅助性的栈来帮助追踪待处理的节点位置[^2]。 ```java public List<Integer> inorderTraversal(TreeNode root) { Stack<TreeNode> stack = new Stack<>(); List<Integer> result = new ArrayList<>(); TreeNode currentNode = root; while (!stack.isEmpty() || currentNode != null) { while (currentNode != null) { // 不断深入左侧分支直至最底部 stack.push(currentNode); currentNode = currentNode.left; } currentNode = stack.pop(); // 取出最后一个被压入栈内的元素作为下一个要处理的对象 result.add(currentNode.val); // 对该对象执行相应的动作(比如打印) currentNode = currentNode.right;// 接着转向右侧寻找新的起点 } return result; } ``` 上述实现了中遍历时所需的逻辑控制流程。 #### 后序遍历 (Postorder Traversal) 后序遍历要求最后才访问根节点,即先遍历左子树再遍历右子树之后才能访问根节点。由于这种特性,在实际编码过程中会稍微复杂一些,因为当返回上层时无法立即知道是否已经完成了左右两侧的操作[^3]。 一种常见的做法是在第一次到达某个节点时不马上对其进行任何处理而是将其再次放入栈底等待后续确认;只有在第二次遇见它并且确实发现它的所有子节点都已经被完全处理过后才会真正输出这个节点的内容。 ```java public List<Integer> postorderTraversal(TreeNode root) { LinkedList<Integer> result = new LinkedList<>(); // 用来存储最终的结果列表 Deque<TreeNode> deque = new ArrayDeque<>(); // 辅助队列/栈 if (root == null) return result; TreeNode prev = null, curr = root; while(!deque.isEmpty() || curr != null){ while(curr!=null){ // 将整条路径上的所有节点依次加入栈内 deque.offerFirst(curr); curr=curr.left; } curr = deque.peekFirst(); if((curr.right==null)||(prev!=null && prev==curr.right)){ result.add(deque.pollFirst().val); // 如果不存在右子树 或者 刚刚是从右子树回来,则可安全移除并添加结果集中 prev = curr; curr=null; }else{ curr=curr.right; // 存在右子树且尚未访问过的情况转而去考察这条支路 } } return result; } ``` 这种方法有效地解决了后序遍历中延迟访问根节点的需求,同时也保持了整个算法的时间效率不变。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值