二叉樹的遍歷
二叉樹的遍歷常分先序遍歷、中序遍歷、後序遍歷
- 先序遍歷:先訪問根節點,再訪問左子節點,最後訪問右子節點
- 中序遍歷:先訪問左子節點,再訪問跟節點,最後訪問右子節點
- 後序遍歷:先訪問左子節點,再訪問右子節點,最好訪問根節點
實現的邏輯分爲遞歸、非遞歸的邏輯;
#TreeNode結構
public class TreeNode {
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int x) {
val = x;
}
}
遞歸實現
public void visit(TreeNode node){
System.out.print(node.val+" ");
}
/**
* 遞歸先序遍歷
**/
public void preOrderRecursion(TreeNode node){
if(node==null) //如果結點爲空則返回
return;
visit(node);//訪問根節點
preOrderRecursion(node.left);//訪問左孩子
preOrderRecursion(node.right);//訪問右孩子
}
/**
* 遞歸中序遍歷
**/
public void preOrderRecursion(TreeNode node){
if(node==null) //如果結點爲空則返回
return;
preOrderRecursion(node.left);//訪問左孩子
visit(node);//訪問根節點
preOrderRecursion(node.right);//訪問右孩子
}
/**
* 遞歸後序遍歷
**/
public void preOrderRecursion(TreeNode node){
if(node==null) //如果結點爲空則返回
return;
preOrderRecursion(node.left);//訪問左孩子
preOrderRecursion(node.right);//訪問右孩子
visit(node);//訪問根節點
}
非遞歸實現:
- 先序遍歷
- 假設cur=head,將cur入棧
- 不斷從棧中彈出棧頂節點,然後把右子節點和左子節點放入棧中
(因爲先訪問左子節點,棧爲先進後出的數據結構,所以先放左子節點) - 當棧不爲空,不斷重複上一步驟
public List<Integer> preorderTraversal(TreeNode node) {
List<Integer> rt = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
if (node == null) {
return rt;
}
stack.push(node);
while (!stack.empty()) {
TreeNode curNode = stack.pop();
rt.add(curNode.val);
if (curNode.right != null) {
stack.push(curNode.right);
}
if (curNode.left != null) {
stack.push(curNode.left);
}
}
return rt;
}
- 中序遍歷
- 初始化cur=head
- 將cur入棧,不斷將cur=cur.left(不斷取左子節點),重複當前過程
- 如果cur爲空,則已經訪問到“最左“節點,出棧並打印當前節點的值,將其右子節點賦值給cur,重複上一步
public List<Integer> inorderTraversal(TreeNode node) {
List<Integer> rt = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
if (node == null) {
return rt;
}
while (!stack.empty() || node != null) {
if (node != null) {
stack.push(node);
node = node.left;
} else {
node = stack.pop();
rt.add(node.val);
node = node.right;
}
}
return rt;
}
- 後序遍歷
- 申請兩個棧s1,s2,將頭節點壓入s1
- 從s1中彈出節點cur依次將cur的左孩子右孩子壓入s1,同時將cur壓入棧s2中
- 最後s2的棧即爲訪問順序,不斷彈出打印即可
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> rt = new ArrayList<>();
Stack<TreeNode> stack1 = new Stack<>();
Stack<TreeNode> stack2 = new Stack<>();
if (root == null){
return rt;
}
stack1.push(root);
while (!stack1.empty()){
TreeNode node = stack1.pop();
stack2.push(node);
if (node.left != null){
stack1.push(node.left);
}
if (node.right != null){
stack1.push(node.right);
}
}
while (!stack2.empty()){
rt.add(stack2.pop().val);
}
return rt;
}