最常用的三种遍历方法:前序(preorder)、中序(inorder)和后序(postorder),二叉搜索树最常用的是中序遍历。
中序遍历
中序遍历二叉搜索树会使所有的节点按关键字升序被访问到。如果希望在二叉树中创建有序的数据序列,这是一种方法。
遍历树最简单的方法是递归。用递归方法遍历整棵树要用一个节点做参数。初始化时这个节点是根。步骤如下:
-
- 调用自身来遍历节点的左子树;
-
- 访问此节点
-
- 调用自身来遍历节点的右子树。
遍历可以应用于任何二叉树,而不只是二叉搜索树。遍历原理不关心节点的关键字值;它只看节点是否有子节点。
中序遍历代码如下:
- 调用自身来遍历节点的右子树。
private void inOrder(nodes localRoot){
if(localRoot != null){
inOrder(localRoot.leftChild);
System.out.print(localRoot.data + " ");
inOrder(localRoot.rightChild);
}
}
开始时,用根作为参数来调用方法:
inOrder(root);
前序和后序遍历
前序遍历代码如下:
private void preOrder(nodes localRoot){
if(localRoot != null){
System.out.print(localRoot.data + " ");
preOrder(localRoot.leftChild);
preOrder(localRoot.rightChild);
}
}
后序遍历代码如下:
private void postOrder(nodes localRoot){
if(localRoot != null){
postOrder(localRoot.leftChild);
postOrder(localRoot.rightChild);
System.out.print(localRoot.data + " ");
}
}
应用
树的节点定义
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
Tree类的基本方法:
class Tree{
private Node root;
public void find(int key){
}
public void insert(int id, double data){
}
public void delete(int id){
}
}
find()例程:
public Node find(int key){
Node current = root;
while(current.data != key){
if(key < current.data)
current = currnet.leftChild;
else
current = current.rightChild;
if(current == null) return null;
}
return current;
}
效率:查找节点的时间取决于这个节点所在的层数,其时间复杂度为O(logN).
insert()例程
public void insert(double data){
Node newNode = new Node();
newNode.data = data;
if(root == null)
root = new Node;
else{
Node current = root;
Node parrent;
while(true){
parrent = current;
if(data < current.data){
current = current.leftChild;
if(current == null){
parent.leftChild = newNode;
return;
}
}
else{
current = current.rightChild;
if(current == null){
parent.rightChild = newNode;
return;
}
}
}
}
}
查找最大值最小值
public Node minimum(){
Node current,last;
current = root;
while(current != null){
last = current;
current = current.leftChild;
}
return last;
}
删除节点
public boolean delete(int key){
Node current = root;
Node parent = root;
boolean isLeftChild = true;
while(current.data != key){
parent = current;
if(key < current.data){
isleftChild = true;
current = current.leftChild;
}
else{
isLeftChild = false;
current = current.rightChild;
}
if(current == null) return false;
}
//1.删除没有子节点的节点
if(current.leftChild == null && current.rightChildren = null){
if(current == root) root = null;
else if(isleftChildren) parent.leftChildren = null;
else parent.rightChildren = null;
}
//2.删除有一个子节点的节点
//如果没有右孩子,用左子树替代
else if(current.rightChild == null)
if(current == root)
root = current.leftChild;
else if(isLeftChild)
parent.leftChild = current.leftChild;
else parent.rightChild = current.leftChild;
//如果没有左孩子,用右子树替代
else if(current.leftChild == null)
if(current == root)
root = current.rightChild;
else(isLeftChild)
parent.leftChild = current.rightChild;
else parent.right = current.rightChild;
//3.删除有两个孩子的节点
else{// two children, so replace with inorder successor
//get the successor of node to delete(current)
Node succesor = getSuccessor(current);
//connect parent of current to successor instead
if(current == root)
root = successor;
else if(isLeftChild)
parent.leftChild = successor;
else parent.rightChild = successor;
//connect successor to current.leftChild
successor.leftChild = current.leftChild;
}
//successor cannot have a left child
return true;
}
private node getSuccessor(node delNode){
Node successorParent = delNode;
Node successor = delNode;
Node current = delNode.rightChild;
while(current != null){
sussessorParent = successor;;
successor = current;
current = current.leftChild;
}
if(successor != delNode.rightChild){
successorParrent.leftChild = successor.rightChild;
successor.rightChild = delNode.rightChild;
}
return successor;
}