二叉排序樹的構造、深度優先遍歷、廣度優先遍歷
阿新 • • 發佈:2018-12-21
之前面試官總是會問到二叉樹的遍歷,自己回答的很不好。甚至可以說想都想不起來。真的應了老師應常說的那句話,你們學的東西都還給老師了啊。。。這兩天在看mysql優化的時候看到了B樹,然後去查閱B樹的知識,又知道B樹又跟二叉排序樹脫不了關係。於是就整理了這篇關於二叉排序樹的相關知識。
首先我們知道,二叉排序樹的特徵有:(1)如果一個節點的左子樹不空,那麼左子樹的所有節點的值均小於該節點的值; (2)如果一個節點的右子樹不空,那麼右子樹的所有節點的值均大於該節點的值;1.構造排序二叉樹的基本思想為(使用前序插入)
(1)首先定義一個根節點,初始化為null (2)將插入的第一個元素通過節點類打包給根節點 (3)將根節點賦給currentNode這個節點 (4)繼續插入元素,如果該元素大於currentNode.value,那麼就將該元素賦給currentNode.right,把currentNode.right當作currentNode;否則將該元素賦給currentNode.left,把currentNode.left當作currentNode2.二叉樹的遍歷有兩種方式:深度優先遍歷、廣度優先遍歷
2.1深度優先遍歷
沿著樹的深度遍歷二叉樹。可以使用前序遍歷(遞迴、非遞迴)、中序遍歷(遞迴、非遞迴)、後續遍歷(遞迴、非遞迴)
2.2廣度優先遍歷
一層一層的遍歷,先訪問一個節點,再訪問該節點的鄰接節點
3.具體程式碼實現(參考文章http://blog.csdn.net/fantasy_lin_/article/details/52751559)
package Tree;
import java.util.LinkedList;
import java.util.Queue;
/*
Created By guolujie in 2017年9月15日
*/
public class MyTree {
public static void main(String[] args) {
// TODO Auto-generated method stub
BinaryOrderTree<Integer> tree = new BinaryOrderTree<Integer>();
tree.insertTreeNode(2);
tree.insertTreeNode(1);
tree.insertTreeNode(0);
tree.insertTreeNode(9);
tree.insertTreeNode(6);
tree.insertTreeNode(7);
tree.insertTreeNode(5);
tree.insertTreeNode(8);
tree.insertTreeNode(3);
tree.insertTreeNode(4);
System.out.print("前序遍歷(遞迴):");
tree.preOrderTraverse(tree.getRoot());
System.out.println();
System.out.print("中序遍歷(遞迴):");
tree.midOrderTraverse(tree.getRoot());
System.out.println();
System.out.print("後序遍歷(遞迴):");
tree.postOrderTraverse(tree.getRoot());
System.out.println();
System.out.print("前序遍歷(非遞迴):");
tree.preOrderTraverseNo(tree.getRoot());
System.out.println();
System.out.print("中序遍歷(非遞迴):");
tree.midOrderTraverseNo(tree.getRoot());
System.out.println();
System.out.print("後序遍歷(非遞迴):");
tree.postOrderTraverseNo(tree.getRoot());
System.out.println();
System.out.print("廣度優先遍歷:");
tree.breadthFirstTraverse(tree.getRoot());
}
}
//首先定義節點類
class TreeNode<E extends Comparable<E>>{
E value;
TreeNode<E> left;
TreeNode<E> right;
TreeNode(E value){
this.value = value;
left = null;
right = null;
}
}
//通過前序插入節點,構造二叉排序樹
class BinaryOrderTree<E extends Comparable<E>>{
private TreeNode<E> root;
BinaryOrderTree() {
root=null;
}
public void insertTreeNode(E value){
if(root==null)
{
root = new TreeNode<E>(value);
return;
}
TreeNode<E> currentNode = root;
while(true){
if(value.compareTo(currentNode.value)>0){
if(currentNode.right==null){
currentNode.right = new TreeNode<E>(value);
break;
}
currentNode = currentNode.right;
}
else{
if(currentNode.left==null){
currentNode.left = new TreeNode<E>(value);
break;
}
currentNode = currentNode.left;
}
}
}
public TreeNode<E> getRoot(){
return root;
}
//前序遍歷(遞迴)
public void preOrderTraverse(TreeNode<E> node){
System.out.print(node.value+" ");
if(node.left!=null)
preOrderTraverse(node.left);
if(node.right!=null)
preOrderTraverse(node.right);
}
//中序遍歷(遞迴)
public void midOrderTraverse(TreeNode<E> node){
if(node.left!=null)
midOrderTraverse(node.left);
System.out.print(node.value+" ");
if(node.right!=null)
midOrderTraverse(node.right);
}
//後序遍歷(遞迴)
public void postOrderTraverse(TreeNode<E> node){
if(node.left!=null)
postOrderTraverse(node.left);
if(node.right!=null)
postOrderTraverse(node.right);
System.out.print(node.value+" ");
}
//前序遍歷(非遞迴)
public void preOrderTraverseNo(TreeNode<E> root){
LinkedList<TreeNode<E>> list = new LinkedList<TreeNode<E>>();
TreeNode<E> currentNode = null;
list.push(root);
while(!list.isEmpty()){
currentNode = list.pop();
System.out.print(currentNode.value+" ");
if(currentNode.right!=null)
list.push(currentNode.right);
if(currentNode.left!=null)
list.push(currentNode.left);
}
}
public void midOrderTraverseNo(TreeNode<E> root){
LinkedList<TreeNode<E>> list = new LinkedList<TreeNode<E>>();
TreeNode<E> currentNode = root;
while(currentNode!=null||!list.isEmpty()){
while(currentNode!=null){
list.push(currentNode);
currentNode = currentNode.left;
}
currentNode = list.pop();
System.out.print(currentNode.value+" ");
currentNode = currentNode.right;
}
}
public void postOrderTraverseNo(TreeNode<E> root){
LinkedList<TreeNode<E>> list = new LinkedList<TreeNode<E>>();
TreeNode<E> currentNode = root;
TreeNode<E> rightNode = null;
while(currentNode!=null||!list.isEmpty()){
while(currentNode!=null){
list.push(currentNode);
currentNode = currentNode.left;
}
currentNode = list.pop();
while (currentNode.right == null || currentNode.right == rightNode) {
System.out.print(currentNode.value + " ");
rightNode = currentNode;
if (list.isEmpty()) {
return; //root以輸出,則遍歷結束
}
currentNode = list.pop();
}
list.push(currentNode); //還有右結點沒有遍歷
currentNode = currentNode.right;
}
}
//廣度優先遍歷,使用佇列
public void breadthFirstTraverse(TreeNode<E> root){
Queue<TreeNode<E>> queue = new LinkedList<TreeNode<E>>();
TreeNode<E> currentNode = null;
queue.offer(root);
while(!queue.isEmpty()){
currentNode=queue.poll();
System.out.print(currentNode.value+" ");
if(currentNode.left!=null)
queue.offer(currentNode.left);
if(currentNode.right!=null)
queue.offer(currentNode.right);
}
}
}