java实现二叉树以及实例
二叉树的设计与遍历
目的和要求:
(1)正确定义二叉树结点
(2)掌握定义二叉树的方法
(3)掌握采用先序创建二叉树的方法
(4)掌握二叉树的先序、中序和后序遍历算法
实验原理及内容:
(1)二叉树的定义;
(2)采用先序创建二叉树
(3)二叉树的先序、中序和后序遍历算法实现
实验步骤:
(1)二叉树的定义;
(2)采用先序创建二叉树
(3)二叉树的先序、中序和后序遍历算法实现
实验过程:
(一)实训说明
本实训给出了二叉树方法集合,即接口,同时提供了二叉树结点的定义,对于二叉树,提供了先序创建二叉树的方法,通过调用该方法,即可创建二叉树。
要求完成二叉树的先序、中序和后序遍历算法。
第二个代码纯属转载,注转载地址如下:
http://www.cnblogs.com/CherishFX/p/4617105.html
再注:
第一个为学习代码,测试的添加的图形为下面的二叉树。此为按图添加。
第二个为使用代码,添加的图形可以任意。
第一个代码测试类添加的固定代码如下:
第一个学习代码如下:
(1)二叉树结点定义
/* * 二叉树结点定义 */ public class TreeNode<E> { // 属性 private E data; // 结点元素值 private TreeNode<E> lchild; // 左孩子结点 private TreeNode<E> rchild; // 右孩子结点 // get和set方法 public E getData() { return data; } public void setData(E data) { this.data = data; } public TreeNode<E> getLchild() { return lchild; } public void setLchild(TreeNode<E> lchild) { this.lchild = lchild; } public TreeNode<E> getRchild() { return rchild; } public void setRchild(TreeNode<E> rchild) { this.rchild = rchild; } // 构造方法,三个参数 public TreeNode(E data, TreeNode<E> lchild, TreeNode<E> rchild) { this.data = data; this.lchild = lchild; this.rchild = rchild; } // 构造方法,三个参数 public TreeNode(E data) { this.data = data; this.lchild = this.rchild = null; } // 构造方法,无参数 public TreeNode() { this(null); } } }
(2)二叉树的操作接口定义
public interface IBiTree<E> { void create(E val, TreeNode<E>l, TreeNode<E> r); //以val为根节点元素,l和r为左右子树构造二叉树 void insertL(E val, TreeNode<E> p); //将元素插入p的左子树 void insertR(E val, TreeNode<E> p); //将元素插入p的右子树 TreeNode<E> deleteL(TreeNode<E> p) ; //删除p的左子树 TreeNode<E> deleteR(TreeNode<E> p); //删除p的右子树 TreeNode<E> search(TreeNode<E> root, E value) ; //在root树中查找结点元素为value的结点 void traverse(TreeNode<E> root, int i); //按某种方式i遍历root二权树 }
(3)二叉树的定义及方法实现
public class LinkBiTree<E> implements IBiTree<E> { private TreeNode<E> head; // 链表头引用指针 public TreeNode<E> getHead() { return head; } // 构造函数,生成一棵以val为根结点数据域信息,以二叉树lp和rp为左子树和右子树的二叉树。 public LinkBiTree(E val, TreeNode<E> lp, TreeNode<E> rp) { TreeNode<E> p = new TreeNode<E>(val, lp, rp); head = p; } // 构造函数,生成一棵以val为根结点数据域信息的二叉树 public LinkBiTree(E val) { this(val, null, null); } // 构造函数,生成一棵空的二叉树 public LinkBiTree() { head = null; } // 判断是否是空二叉树 public boolean isEmpty() { return head == null; } // 获取根结点 public TreeNode<E> Root() { return head; } // 获取结点的左孩子结点 public TreeNode<E> getLchild(TreeNode<E> p) { return p.getLchild(); } // 获取结点的右孩子结点 public TreeNode<E> getRchild(TreeNode<E> p) { return p.getRchild(); } // 创建二叉树 public void create(E val, TreeNode<E> l, TreeNode<E> r) { TreeNode<E> p = new TreeNode<E>(val, l, r); head = p; } // 将结点p的左子树插入值为val的新结点, // 原来的左子树成为新结点的左子树 public void insertL(E val, TreeNode<E> p) { TreeNode<E> name = new TreeNode<E>(val); TreeNode<E> item = p.getLchild(); p.setLchild(name); name.setLchild(item); } // 将结点p的右子树插入值为val的新结点, // 原来的右子树成为新结点的右子树 public void insertR(E val, TreeNode<E> p) { TreeNode<E> name = new TreeNode<E>(val); TreeNode<E> item = p.getRchild(); p.setRchild(name); name.setRchild(item); } // 若p非空,删除p的左子树 public TreeNode<E> deleteL(TreeNode<E> p) { if (p == null) return null; TreeNode<E> simulation = p.getLchild(); p.setLchild(null); return simulation; } // 若p非空,删除p的右子树 public TreeNode<E> deleteR(TreeNode<E> p) { if (p == null) return null; TreeNode<E> simulation = p.getRchild(); p.setRchild(null); return simulation; } // 编写算法,在二叉树中查找值为value的结点 public TreeNode<E> search(TreeNode<E> root, E value) { Queue<TreeNode<E>> q = new LinkedList<TreeNode<E>>(); q.add(root); while (!q.isEmpty()) { TreeNode<E> simulation = q.poll(); if (simulation.getLchild() != null) q.add(simulation.getLchild()); if (simulation.getRchild() != null) q.add(simulation.getRchild()); if (simulation.getData().equals(value)) return simulation; } return null; } // 判断是否是叶子结点 public boolean isLeaf(TreeNode<E> p) { Queue<TreeNode<E>> q = new LinkedList<TreeNode<E>>(); q.add(head); while (!q.isEmpty()) { TreeNode<E> simulation = q.poll(); if (simulation.getLchild() != null) q.add(simulation.getLchild()); if (simulation.getRchild() != null) q.add(simulation.getRchild()); if (simulation.getData().equals(p.getData()) && simulation.getLchild() == null && simulation.getRchild() == null) return true; } return false; } // 中序遍历 public void inorder(TreeNode<E> p) { if (p != null) { inorder(p.getLchild()); System.out.print(p.getData() + " "); inorder(p.getRchild()); } return; } // 先序遍历 public void preorder(TreeNode<E> p) { if (p != null) { System.out.print(p.getData() + " "); preorder(p.getLchild()); preorder(p.getRchild()); } return; } // 后序列遍历 public void postorder(TreeNode<E> p) { if (p != null) { postorder(p.getLchild()); postorder(p.getRchild()); System.out.print(p.getData() + " "); } return; } // 层次遍历 public void levelOrder(TreeNode<E> p) { if (p == null) return; Queue<TreeNode<E>> q = new LinkedList<TreeNode<E>>(); q.add(head); while (!q.isEmpty()) { TreeNode<E> simulation = q.poll(); System.out.print(simulation.getData() + " "); if (simulation.getLchild() != null) q.add(simulation.getLchild()); if (simulation.getRchild() != null) q.add(simulation.getRchild()); } } // 遍历二叉树 public void traverse(TreeNode<E> root, int i) { switch (i) { case 1: preorder(root); break; case 2: inorder(root); break; case 3: postorder(root); break; case 4: levelOrder(root); break; } } }
(4)二叉树测试类
import jsj.hhtc.ds.tree.LinkBiTree; import jsj.hhtc.ds.tree.TreeNode; public class TestLinkBiTree { public static void main(String[] args) { //构造如图6.5(b)所示二叉树 //以A为根结点的二叉树 LinkBiTree<Character> bt = new LinkBiTree<Character>('A'); TreeNode<Character> root = bt.getHead(); //插入A的左结点B bt.insertL('B', root); TreeNode<Character> b = root.getLchild(); //插入B的左结点D bt.insertL('D', b); TreeNode<Character> d = b.getLchild(); //插入B的右结点G bt.insertR('G', d); //构造A的右子树 bt.insertR('C', root); TreeNode<Character> c = root.getRchild(); bt.insertL('E', c); bt.insertR('F', c); System.out.print("\n先序遍历:"); bt.preorder(root); System.out.print("\n中序遍历:"); bt.inorder(root); System.out.print("\n后序遍历:"); bt.postorder(root); System.out.print("\n层序遍历:"); bt.levelOrder(root); } }
第二个代码如下:
(1)二叉树的定义及方法实现
import java.util.LinkedList; import java.util.List; import java.util.Queue; import java.util.Stack; /** * @author Cherish * 二叉树的链式存储结构 * @param <E> */ public class BinaryTree<E> { private TreeNode<E> root; //根节点 private List<TreeNode> nodeList = null; //二叉树节点的链式结构 public BinaryTree(){ } public BinaryTree(TreeNode<E> root){ this.root = root; } //把一个数组转化为一颗完全二叉树 public TreeNode<E> buildTree(E[] array){ nodeList = new LinkedList<TreeNode>(); //将数组中的元素依次转换为TreeNode节点,存放于链表中 for(int i=0; i< array.length; i++){ nodeList.add(new TreeNode(array[i])); } //对前(array.length / 2 - 1)个父节点,按照父节点与孩子节点的数字关系建立完全二叉树 //对完全二叉树,按从上到下,从左到右的顺序依次编号0,1,2,3....N,则i>0的节点,其左孩子为(2*i+1), //其右孩子为(2*i+2) for(int j=0; j < (array.length/2-1);j++){ //左孩子 nodeList.get(j).setLchild(nodeList.get(j*2+1)); //右孩子 nodeList.get(j).setRchild(nodeList.get(j*2+2)); } //最后一个父节点:因为最后一个父节点可能没有右孩子,所以单独处理 int index = array.length/2 -1; //左孩子 nodeList.get(index).setLchild(nodeList.get(index*2+1)); //右孩子:如果数组的长度为奇数才有右孩子 if(array.length % 2 == 1){ nodeList.get(index).setRchild(nodeList.get(index*2+2)); } root=nodeList.get(0); //设置根节点 return root; } //得到树的高度 public int height(TreeNode<E> node){ if(node == null){ return 0; }else{ int i = height(node.getLchild()); int j = height(node.getRchild()); return (i<j)?(j+1):(i+1); } } //得到节点的个数 public int size(TreeNode<E> node){ if(node == null){ return 0; }else{ return 1+ size(node.getLchild())+size(node.getRchild()); } } //递归实现先序遍历 NLR public void preOrder(TreeNode<E> node){ if(node != null){ System.out.print(node.getData() + " "); preOrder(node.getLchild()); preOrder(node.getRchild()); } } //非递归实现先序遍历 NLR public void nonRecPreOrder(TreeNode<E> node){ Stack<TreeNode<E>> nodeStack = new Stack<TreeNode<E>>(); TreeNode<E> nodeTemp = node; //nodeTemp作为遍历指针 while(nodeTemp != null || !nodeStack.isEmpty()){ //当nodeTemp非空或栈非空时循环 if(nodeTemp != null){ //根指针非空,遍历左子树 nodeStack.push(nodeTemp); //根指针进栈 System.out.print(nodeStack.peek().getData() + " "); //根指针退栈,访问根节点 nodeTemp = nodeTemp.getLchild(); //每遇到非空二叉树先向左走 }else{ //再向右子树走 nodeTemp = nodeStack.pop(); nodeTemp = nodeTemp.getRchild(); } } } //递归实现中序遍历 LNR public void inOrder(TreeNode<E> node){ if(node != null){ inOrder(node.getLchild()); System.out.print(node.getData() + " "); inOrder(node.getRchild()); } } //非递归实现中序遍历 LNR public void nonRecInOrder(TreeNode<E> node){ Stack<TreeNode<E>> nodeStack = new Stack<TreeNode<E>>(); TreeNode<E> nodeTemp = node; //nodeTemp作为遍历指针 while(nodeTemp != null || !nodeStack.isEmpty()){ //当nodeTemp非空或栈非空时循环 if(nodeTemp != null){ //根指针非空,遍历左子树 nodeStack.push(nodeTemp); //根指针进栈 nodeTemp = nodeTemp.getLchild(); //每遇到非空二叉树先向左走 }else{ nodeTemp = nodeStack.pop(); //根指针退栈,访问根节点 System.out.print(nodeTemp.getData() +" "); nodeTemp = nodeTemp.getRchild(); //再向右子树走 } } } //递归实现后序遍历 LNR public void postOrder(TreeNode<E> node){ if(node != null){ postOrder(node.getLchild()); postOrder(node.getRchild()); System.out.print(node.getData() + " "); } } //非递归实现后序遍历 LNR public void nonRecPostOrder(TreeNode<E> node){ Stack<TreeNode<E>> nodeStack = new Stack<TreeNode<E>>(); TreeNode<E> nodeTemp = node; //nodeTemp作为遍历指针 TreeNode<E> preNode = null; //表示最近一次访问的节点 while(nodeTemp != null || !nodeStack.isEmpty()){ //当nodeTemp非空或栈非空时循环 while(nodeTemp != null){ //一直向左走,遍历左子树 nodeStack.push(nodeTemp); nodeTemp = nodeTemp.getLchild(); } nodeTemp = nodeStack.peek(); if(nodeTemp.getRchild()==null || nodeTemp.getRchild() == preNode){ //右子树为空或右子树已被访问时,该节点出栈 nodeTemp = nodeStack.pop(); System.out.print(nodeTemp.getData()+" "); preNode = nodeTemp; //将该节点赋值给最近一个访问节点 nodeTemp = null; //此处很重要,将刚出栈节点设置为空,对应于while循环的条件之一,否则陷入死循环 }else{ nodeTemp = nodeTemp.getRchild(); //遍历右子树 } } } //层次遍历 public void levelOrder(TreeNode<E> root){ Queue<TreeNode<E>> nodeQueue = new LinkedList<TreeNode<E>>(); TreeNode<E> node = null; nodeQueue.add(root); //将根节点入队 while(!nodeQueue.isEmpty()){ //队列不空循环 node = nodeQueue.peek(); System.out.print(node.getData()+" "); nodeQueue.poll(); //队头元素出队 if(node.getLchild() != null){ //左子树不空,则左子树入队列 nodeQueue.add(node.getLchild()); } if(node.getRchild() != null){ //右子树不空,则右子树入队列 nodeQueue.add(node.getRchild()); } } } public static void main(String args[]){ //将一个数组转化为一颗完全二叉树 Object[] array = {1,2,3}; BinaryTree bt = new BinaryTree(); TreeNode root = bt.buildTree(array); System.out.print("树的高度:"); System.out.println(bt.height(root)); System.out.print("节点的个数:"); System.out.println(bt.size(root)); System.out.println("先序遍历:"); bt.preOrder(root); System.out.println("\n"+"非递归先序遍历:"); bt.nonRecPreOrder(root); System.out.println(); System.out.println("中序遍历:"); bt.inOrder(root); System.out.println("\n"+"非递归中序遍历:"); bt.nonRecInOrder(root); System.out.println(); System.out.println("后序遍历:"); bt.postOrder(root); System.out.println("\n"+"非递归后序遍历:"); bt.nonRecPostOrder(root); System.out.println(); System.out.println("层次遍历:"); bt.levelOrder(root); //手工构建一颗二叉树 TreeNode nodeA = new TreeNode("A"); TreeNode nodeB = new TreeNode("B"); TreeNode nodeC = new TreeNode("C"); TreeNode nodeD = new TreeNode("D"); TreeNode nodeE = new TreeNode("E"); TreeNode nodeF = new TreeNode("F"); TreeNode nodeG = new TreeNode("G"); TreeNode nodeH = new TreeNode("H"); TreeNode nodeI = new TreeNode("I"); nodeA.setLchild(nodeB); nodeA.setRchild(nodeD); nodeB.setRchild(nodeC); nodeD.setLchild(nodeE); nodeD.setRchild(nodeF); nodeF.setLchild(nodeG); nodeF.setRchild(nodeI); nodeG.setRchild(nodeH); System.out.println("\n\n"+"*****************"); System.out.print("树的高度:"); System.out.println(bt.height(nodeA)); System.out.print("节点的个数:"); System.out.println(bt.size(nodeA)); System.out.println("先序遍历:"); bt.preOrder(nodeA); System.out.println(); System.out.println("中序遍历:"); bt.inOrder(nodeA); System.out.println(); System.out.println("后序遍历:"); bt.postOrder(nodeA); System.out.println(); System.out.println("层次遍历:"); bt.levelOrder(nodeA); } }(2)二叉树结点
public class TreeNode<E> { private E data; //数据域 private TreeNode<E> lchild; //左孩子 private TreeNode<E> rchild; //右孩子 TreeNode(){} TreeNode(E e){ this.data = e; } TreeNode(E data,TreeNode<E> lchild, TreeNode<E> rchild){ this.data = data; this.lchild = lchild; this.rchild = rchild; } public void setData(E data){ this.data = data; } public E getData(){ return this.data; } public void setLchild(TreeNode<E> lchild){ this.lchild = lchild; } public TreeNode<E> getLchild(){ return this.lchild; } public void setRchild(TreeNode<E> rchild){ this.rchild = rchild; } public TreeNode<E> getRchild(){ return this.rchild; } }