十八 二分搜尋樹的三種遍歷方式
阿新 • • 發佈:2018-11-22
三種遍歷方式:
package com.lt.datastructure.BST; public class BST<E extends Comparable<E>> { private class Node{ public E e; Node left,right; public Node(E e) { this.e = e; this.left = left; this.right = right; } }private Node root; private int size; public BST(){ root = null; size = 0; } public int size() { return size; } public boolean isEmpty(){ return size==0; } /* * 二分搜尋樹新增元素 * 小於根結點,新增到左邊,大於則新增到右邊,等於根節點,則不作任何改變,二分搜尋樹不包含重複元素 **/ public void add(E e){ //如果根節點為空 if(root == null){ root = new Node(e); size ++; }else{ add(root,e); } } //向以root為根的二分搜尋樹中插入元素E,遞迴演算法 private Node add(Node node , E e){ //遞迴的出口,找到子樹為null,則必然新增,完成操作 if(node == null){ size++; return new Node(e); } if(e.compareTo(node.e)<0){ //如果左子樹為null,則node.left = new Node(e);如果不為空,繼續遞迴 node.left = add(node.left,e); } else if(e.compareTo(node.e)>0){ ////如果右子樹為null,則node.right = new Node(e);如果不為空,繼續遞迴 node.right = add(node.right,e); } //其他情況,比如元素相等,則返回傳進來的根節點,不做操作 return node; } //查詢二分搜尋樹中是否包含元素e public boolean contains(E e){ return contains(root,e); } //看以node為根的二分搜尋樹中是否含有元素e,遞迴實現 private boolean contains(Node node , E e){ if(node == null){ return false; } if(e.compareTo(node.e)==0){ return true; } else if(e.compareTo(node.e)<0){ return contains(node.left,e); }else{ return contains(node.right,e); } } /* * 二分搜尋樹的前序遍歷(先訪問結點,再訪問左,右子樹),最自然,最常用的遍歷方式 * * */ public void preOrder(){ preOrder(root); } private void preOrder(Node node){ //遞迴終止 if(node==null){ return; } //遞迴呼叫 System.out.println(node.e);//首先列印根節點 preOrder(node.left);//然後遞迴left,直到left為空,回溯,列印left由深到淺 preOrder(node.right);//最後遞迴完了left,遞迴right,right列印由淺到深 } //遍歷的展示 @Override public String toString() { StringBuilder res = new StringBuilder(); BSTString(root,0,res); return res.toString(); } //生成以node為根節點,深度為depth描述的字串 private void BSTString(Node node, int depth, StringBuilder res) { if(node==null){ res.append(DepthString(depth)+"null\n"); return; } res.append(DepthString(depth)+node.e+"\n"); BSTString(node.left,depth+1,res); BSTString(node.right, depth+1, res); } private String DepthString(int depth) { StringBuilder res = new StringBuilder(); for(int i=0; i<depth ; i++){ res.append("--"); } return res.toString(); } /* * 二分搜尋樹的中序遍歷(訪問左子樹,結點,右子樹),順序由小到大,最自然,最常用的遍歷方式 * */ public void inOrder(){ inOrder(root); } //中序遍歷以node為根的二分搜尋樹,遞迴演算法 private void inOrder(Node node){ if(node==null){ return; } inOrder(node.left);//由深到淺列印left System.out.println(node.e);//每遞迴一次,列印當前根節點 inOrder(node.right);//由淺到深列印right } /* * 二分搜尋樹的後序遍歷(訪問右子樹,左子樹,結點),最自然,最常用的遍歷方式 * */ public void postOrder(){ postOrder(root); } private void postOrder(Node node) { //遞迴的終點 if(node == null){ return; } postOrder(node.left);//列印right由深到淺 postOrder(node.right);//列印left由深到淺 System.out.println(node.e);//最後列印根節點 } /* * 先序中序後序遍歷的列印特點: * 對於每個結點,都有三次訪問,可以用三個點代表三次操作。 * 先序遍歷:打印發生在第一此訪問。 * 中序遍歷:打印發生在第二次訪問。 * 後序遍歷:打印發生在第三次訪問。 */ }
測試程式碼:
package com.lt.datastructure.BST; /* * Binary Search Tree */ public class Main { public static void main(String[] args) { BST<Integer> bst = new BST<>(); int[] nums = {5,3,6,8,4,2}; for(int num : nums){ bst.add(num); } bst.postOrder(); System.out.println(); bst.preOrder(); System.out.println(); bst.inOrder(); System.out.println(); } }
三種遍歷的輸出結果:
先序遍歷:
中序遍歷:
後序遍歷:
三種遍歷的列印順序:
先序中序後序遍歷的列印特點:
- 對於每個結點,都有三次訪問,可以用三個點代表三次操作。
- 先序遍歷:打印發生在第一此訪問。
- 中序遍歷:打印發生在第二次訪問。
- 後序遍歷:打印發生在第三次訪問。