树状结构和线性结构不一样,它没有办法从头开始依次向后遍历,如果按照根结点什么时候被访问,我们可以把二叉树的遍历分为以下三种方式:
1、前序遍历:先访问根结点,再访问左子树,最后访问右子树;
2、中序遍历(进行排序的):先访问左子树,中间访问根结点,最后访问右子树
3、后序遍历:先访问左子树,再访问右子树,最后访问根结点
备注:代码中写用的Queue类,附在文章最后
前序遍历的API:
//使用前序遍历,把指定树x中的所有键放入到key队列中
private void preErgodic(Node x,Queue keys){
if(x==null){
return ;
}
//把x结点的Key放到队列keys中
keys.enqueue(x.key);
//递归调用x结点的左子树
if(x.left!=null){
preErgodic(x.left,keys);
}
//递归调用x结点的右子树
if(x.right!=null){
preErgodic(x.right,keys);
}
}
中序遍历的API:
//使用中序遍历,获取整个树中所有的键(先获取左子树,再获取根结点,再获取右子树)
public Queue midErgodic(){
Queue keys = new Queue <>();
midErgodic(root,keys);
return keys;
}
//使用中序遍历,把指定树x中的所有键放入到key队列中
private void midErgodic(Node x, Queue keys) {
if(x==null){
return;
}
//先递归,把左子树的键放到Keys中
if (x.left!=null){
midErgodic(x.left,keys);
}
//把当前结点X的键发到keys中
keys.enqueue(x.key);
//再递归,把右子树的键放到keys中
if(x.right!=null){
midErgodic(x.right,keys);
}
}
后序遍历:
//使用后序遍历,获取整个树中所有的键(先获取左子树,再获取右子树,再获取根结点)
public Queue laterErgodic(){
Queue keys = new Queue <>();
laterErgodic(root,keys);
return keys;
}
//使用后序遍历,把指定树x中的所有键放入到key队列中
private void laterErgodic(Node x, Queue keys) {
if(x==null){
return;
}
//先递归,把左子树的键放到Keys中
if (x.left!=null){
laterErgodic(x.left,keys);
}
//再递归,把右子树的键放到keys中
if(x.right!=null){
laterErgodic(x.right,keys);
}
//把当前结点X的键发到keys中
keys.enqueue(x.key);
}
层序遍历:
实现步骤:
1.创建队列,存储每一层的结点;
2.使用循环从队列中弹出一个结点:
2.1获取当前结点的key;
2.2如果当前结点的左子结点不为空,则把左子结点放入到队列中
2.3如果当前结点的右子结点不为空,则把右子结点放入到队列中
//使用层序遍历,获取整个树中所有的键(先获取根结点,在获取左子树,再获取右子树)
public Queue layerErgodic(){
//定义一个队列,存储树中的键
Queue keys = new Queue <>();
//定义一个队列,存储树中的结点
Queue nodes = new Queue <>();
//默认,往队列中放入根结点
nodes.enqueue(root);
//如果结点队列不为空的话,则进行下续的操作
while(!nodes.isEmpty()){
//从队列中弹出一个结点,把key放入到keys中
Node node = nodes.dequeue();
keys.enqueue(node.key);
//判断当前结点还有没有左子结点,如果有,则放入到Nodes中
if(node.left!=null){
nodes.enqueue(node.left);
}
//判断当前结点还有没有左子结点,如果有,则放入到Nodes中
if(node.right!=null){
nodes.enqueue(node.right);
}
}
return keys;
}
测试代码:
package test;
import com.yyy.BinaryTree;
import com.yyy.Queue;
public class BinaryTreeTest {
public static void main(String[] args) {
BinaryTree binaryTree = new BinaryTree <>();
binaryTree.put(2,"张三");
binaryTree.put(1,"王二");
binaryTree.put(3,"李四");
binaryTree.put(4,"王五");
System.out.println(binaryTree.minKey());
System.out.println(binaryTree.get(3)+"==========="+binaryTree.size());
//前序遍历测试
Queue queue = binaryTree.preErgodic();
for (Integer item:
queue ) {
System.out.println(item+"===前序遍历=="+binaryTree.get(item));
}
//中序遍历测试
Queue midQueue = binaryTree.midErgodic();
for (Integer midItem:
midQueue ) {
System.out.println(midItem+"===中序遍历=="+binaryTree.get(midItem));
}
//后序遍历测试
Queue laterQueue = binaryTree.laterErgodic();
for (Integer laterItem:
laterQueue ) {
System.out.println(laterItem+"===后序遍历=="+binaryTree.get(laterItem));
}
//层序遍历测试
Queue layerErgodic = binaryTree.layerErgodic();
for (Integer layerItem:
layerErgodic ) {
System.out.println(layerItem+"===层序遍历=="+binaryTree.get(layerItem));
}
}
}
Queue类:
package com.yyy;
import java.util.Iterator;
public class Queue implements Iterable{
//记录首结点
private Node head;
//当前栈的元素的个数
private int N;
//记录最后一个结点
private Node last;
//内部类---结点类
private class Node{
public T item;
public Node next;
public Node(T item,Node next){
this.item=item;
this.next=next;
}
}
//队列的初始化
public Queue(){
this.head=new Node(null,null);
this.N=0;
this.last=null;
}
//判断队列是否为空,是返回true ,否返回false
public boolean isEmpty(){
return N==0;
}
//获取队列中元素的个数
public int size(){
return N;
}
//从队列中拿出一个元素
public T dequeue(){
if(isEmpty()){
return null;
}
Node oldFirst=head.next;
head.next=oldFirst.next;
N--;
//因为出队列其实是在删除元素,因此如果队列中的元素被删除完了,需要重置Last=null
if(isEmpty()){
last=null;
}
return oldFirst.item;
}
//往队列里面插入一个元素
public void enqueue(T t){
if(last==null){//说明是第一次插入
last=new Node(t,null);
head.next=last;
}else{//说明不是第一次插入
Node oldLast=last;
last=new Node(t,null);
oldLast.next=last;
}
N++;
}
@Override
//给队列提供外部的遍历方式,实现Iterable接口
public Iterator iterator() {
return new QIterator();
}
private class QIterator implements Iterator{
private Node n;
public QIterator(){
this.n=head;
}
@Override
public boolean hasNext() {
return n.next!=null;
}
@Override
public Object next() {
n=n.next;
return n.item;
}
}
}