就如图所示的二叉树进行遍历:
(1)前序遍历:A B D G H C E I F
(2)中序遍历:G D H B A E I C F
(3)后序遍历:G H D B I E F C A
递归前序遍历算法:
private void preOrderTraverse(Node rootNode){
if(null != rootNode){
System.out.print(rootNode.data+" ");
preOrderTraverse1(rootNode.leftNode);
preOrderTraverse1(rootNode.rightNode);
}
}
递归中序遍历算法:
private void inOrderTraverse(Node rootNode){ //线索二叉树的时候定义一个变量,
//始终指向刚刚访问过的结点
if(null != rootNode){
inOrderTraverse1(rootNode.leftNode);
System.out.print(rootNode.data + " ");
inOrderTraverse1(rootNode.rightNode);
}
}
递归后序遍历算法:
private void postOrderTraverse(Node rootNode){
if(null != rootNode){
postOrderTraverse1(rootNode.leftNode);
postOrderTraverse1(rootNode.rightNode);
System.out.print(rootNode.data + " ");
}
}
以上三种递归遍历算法比较容易理解,要求能快速编写出来
其他递归遍历算法
前序遍历除了用递归遍历外,可以用非递归遍历,在非递归遍历中有两种方式;一种是利用栈实现循环先序遍历二叉树
,另一种是利用栈模拟递归过程实现循环中序遍历二叉树
(1)利用栈实现循环先序遍历二叉树
/**
* 先序遍历非递归
* 利用栈实现循环先序遍历二叉树
* 这种实现类似于图的深度优先遍历(DFS)
* 维护一个栈,将根节点入栈,然后只要栈不为空,出栈并访问,接着依次将访问节点的右节点、左节点入栈。
* 这种方式应该是对先序遍历的一种特殊实现(看上去简单明了),但是不具备很好的扩展性,在中序和后序方式中不适用
* @param root
*/
private void preOrderTraverse_circul1(Node root){
if(root == null){
return;
}
MyLinkedStack<Node> myStack = new MyLinkedStack<Node>();
myStack.push(root);
while(!myStack.isEmpty()){ //当不为空的时候
Node tmpNode = myStack.pop();
System.out.print(tmpNode.data+" ");
if(tmpNode.rightNode != null){
myStack.push(tmpNode.rightNode);
}
if(tmpNode.leftNode != null){
myStack.push(tmpNode.leftNode);
}
}
}
学习这段代码要自己手执行一遍,才能理解
二、利用栈模拟递归过程实现循环中序遍历二叉树
/**
* * @param root 树的根节点
* 利用栈模拟递归过程实现循环先序遍历二叉树
* 这种方式具备扩展性,它模拟递归的过程,
* 将左子树点不断的压入栈,直到null,然后处理栈顶节点的右子树
* @param root
*/
private void preOrderTraverse_stack1(Node root){
if(root == null){
return;
}
MyLinkedStack<Node> myStack = new MyLinkedStack<Node>();
while(root != null || !myStack.isEmpty()){
while(root != null){
System.out.print(root.data+" "); //先访问数据
myStack.push(root); //push进去是为了能pop出来右孩子
root = root.leftNode; //将左子树不断压入栈,直到null,然后处理栈顶结点的
//右子树
}
root = myStack.pop();
root = root.rightNode;
}
}
中序遍历,利用栈模拟递归过程实现循环中序遍历二叉树
利用栈模拟递归过程实现循环中序遍历二叉树 :
/**
* @param root 树根节点
* 利用栈模拟递归过程实现循环中序遍历二叉树
* 思想和上面的preOrderTraverse_stack2相同,
* 只是访问的时间是在左子树都处理完直到null的时候出栈并访问。
*/
private void inOrderTraverse_stack1(Node root){
if(null == root){
return;
}
MyLinkedStack<Node> myStack = new MyLinkedStack<Node>();
while(root != null || !myStack.isEmpty()){
while(root != null){
myStack.push(root);
root = root.leftNode;
}
root = myStack.pop();
System.out.print(root.data + " ");
root = root.rightNode;
}
}
注意与“利用栈模拟递归过程实现循环中序遍历二叉树”的代码做比较
层序遍历的算法;层序遍历充分利用队列的先入先出特性
层序遍历算法:
/**
* 层序遍历,使用队列
* @param root
*/
private void levelTraverse1(Node root){
if(null == root){
return;
}
MyLinkedQueue<Node> myQueue = new MyLinkedQueue<Node>();
myQueue.insert(root);
while(!myQueue.isEmpty()){
Node tmp = myQueue.delete();
System.out.print(tmp.data+" ");
if(tmp.leftNode != null) myQueue.insert(tmp.leftNode);
if(tmp.rightNode != null) myQueue.insert(tmp.rightNode);
}
}
根据二叉树的结点的数据查找是否存在该节点
private Node findNode1(Node node, String data){
// System.out.println(node.data);
if(null == node || null == data || "".equals(data)){
return null;
}else{
if(node.data.equals(data)){
return node;
} //递归出口
//以下代码可以优化,这样写比较容易理解
Node retNode1;Node retNode2;
retNode1 = findNode1(node.leftNode, data);
if(retNode1 != null){
return retNode1;
}
retNode2 = findNode1(node.rightNode, data);
if(retNode2 != null){
return retNode2;
}
}
return null;
}
其实这段代码是根据先序递归遍历的顺序查找的