一个比较详细的二叉查找树
2018-01-22 21:35
253 查看
刚学了二叉树,老师布置了很多题,全部用代码实现了。
这里有没有你需要的,先看这个二叉树查找树的API吧
二叉查找树与普通二叉树的区别就是二叉查找树中父结点的左子结点比父结点小,右子结点比父结点大
相应UML
几个简单的方法简介:
1.preorder先序遍历(中左右 ),inorder中序遍历(左中右),postorder后序遍历(左右中)
2.getNodeNum获得结点数量(PS,直接返回size,不就行了,但是这是老师要求的,不能直接返回size)
3.printLeaf输出所有子结点
4.getNodeLevel获得结点所在层数
5.getLevelNodeNum得到指定层数的结点个数
6.isLike判断两棵二叉树是否相似(除结点里的值不同以外,结点分布一样)
7.printPrent输出 指定结点的所有父节点
8.postOrderInLoop非递归方式,后序遍历所有结点
继承关系:接口Tree,抽象类AbsractTree,具体类BinaryTree
AbstractTree实现了Tree,BinaryTree扩展AbstractTree
贴代码
这里有没有你需要的,先看这个二叉树查找树的API吧
二叉查找树与普通二叉树的区别就是二叉查找树中父结点的左子结点比父结点小,右子结点比父结点大
相应UML
几个简单的方法简介:
1.preorder先序遍历(中左右 ),inorder中序遍历(左中右),postorder后序遍历(左右中)
2.getNodeNum获得结点数量(PS,直接返回size,不就行了,但是这是老师要求的,不能直接返回size)
3.printLeaf输出所有子结点
4.getNodeLevel获得结点所在层数
5.getLevelNodeNum得到指定层数的结点个数
6.isLike判断两棵二叉树是否相似(除结点里的值不同以外,结点分布一样)
7.printPrent输出 指定结点的所有父节点
8.postOrderInLoop非递归方式,后序遍历所有结点
继承关系:接口Tree,抽象类AbsractTree,具体类BinaryTree
AbstractTree实现了Tree,BinaryTree扩展AbstractTree
贴代码
<--------------------------------------接口Tree-----------------------------------------> public interface Tree<E extends Comparable<E>> { /**如果该元素在该树上,那么返回真**/ public boolean search(E e); /**向树中插入一个元素,插入成功则返回true**/ public boolean insert(E e); /**从树中删除一个元素,删除成功则返回true**/ public boolean delete(E e); /**中序遍历该树**/ public void inorder(); /**后序遍历该树**/ public void postorder(); /**前序遍历该树**/ public void preorder(); /**得到树的大小**/ public int getSize(); /**判断该树是否为空**/ public boolean isEmpty(); /**返回一个迭代器去浏览该树中的所有元素**/ @SuppressWarnings("rawtypes") public java.util.Iterator iterator(); } <------------------------------------抽象类AbstractTree-----------------------------------------> package unit_26_programList; @SuppressWarnings("rawtypes") public abstract class AbstractTree<E extends Comparable<E>> implements Tree<E> { /**中序遍历该树**/ public void inorder(){ } /**后序遍历该树**/ public void postorder(){ } /**前序遍历该树**/ public void preorder(){ } /**判断该树是否为空**/ public boolean isEmpty(){ return getSize() == 0; } /**返回一个遍历该树的迭代器**/ @SuppressWarnings("rawtypes") public java.util.Iterator iterator(){ return null; } } <-------------------------------------具体类BinaryTree------------------------------------------> package unit_26_programList; import java.util.ArrayList; import java.util.Iterator; import java.util.Stack; public class BinaryTree<E extends Comparable<E>> extends AbstractTree<E>{ protected TreeNode<E> root; protected int size = 0; /**创建一个默认的二叉树**/ public BinaryTree(){ } /**创建一个有数组构成的二叉树**/ public BinaryTree(E[] objects){ for(int i = 0; i < objects.length; i++){ insert(objects[i]); } } /**如果该元素在该树中则返回真**/ @Override public boolean search(E e) { TreeNode<E> current = root;//从根节点开始 while(current != null){ if(e.compareTo(current.element) < 0){ current = current.left; } else if(e.compareTo(current.element) > 0){ current = current.right; } else return true; } return false; } /**将一个元素插入该树,如果插入成功则返回true**/ @Override public boolean insert(E e) { if(root == null){ root = createNewNode(e); } else{ TreeNode<E> parent = null; TreeNode<E> current = root; while(current != null) if(e.compareTo(current.element) < 0){ parent = current; current = current.left; } else if(e.compareTo(current.element) > 0){ parent = current; current = current.right; } else return false; /**创建一个新的结点,并加入到父节点上**/ if(e.compareTo(parent.element) < 0){ parent.left = createNewNode(e); } else parent.right = createNewNode(e); } size++; return true; } protected TreeNode<E> createNewNode(E e){ return new TreeNode<E>(e); } /**中序遍历该树**/ public void inorder(){ inorder(root); } /**中序遍历子树**/ protected void inorder(TreeNode<E> root){ if(root == null) return; inorder(root.left); System.out.print(root.element + " "); inorder(root.right); } /**后序遍历该树**/ public void postorder(){ postorder(root); } /**后序遍历子树**/ protected void postorder(TreeNode<E> root){ if(root == null) return; postorder(root.left); postorder(root.right); System.out.print(root.element + " "); } /**前序遍历该树**/ public void preorder(){ preorder(root); } /**前序遍历子树**/ protected void preorder(TreeNode<E> root){ if(root == null) return; System.out.print(root.element + " "); preorder(root.left); preorder(root.right); } /** * 从该二叉树中删除一个元素 * 删除成功则返回真 * 如果该树中没有指定元素,则返回假 */ @Override public boolean delete(E e) { //定位删除的结点,并定位其父节点 TreeNode<E> parent = null; TreeNode<E> current = root; while(current != null){ if(e.compareTo(current.element) < 0){ parent = current; current = current.left; } else if(e.compareTo(current.element) > 0){ parent = current; current = current.right; } else break; } if(current == null) return false;//如果这个元素不在这个二叉树中 //第一种情况,当没有左子树时 if(current.left == null){ //将父节点连接到当前节点的正确子节点 if(parent == null){ root = current.right; } else{ if(e.compareTo(parent.element) < 0) parent.left = current.right; else parent.right = current.right; } } //第二种情况:当前节点有一个左子节点,它在当前节点的左子树中找到最右边的节点,以及它的父节点。 else{ TreeNode<E> parentOfRightMost = current; TreeNode<E> rightMost = current.left; while(rightMost != null){ parentOfRightMost = rightMost; rightMost = rightMost.right;//一直向右走 } //用最右边的元素替换当前元素 current.element = rightMost.element; //消除右边的结点 if(parentOfRightMost.right == rightMost){ parentOfRightMost.right = rightMost.left; } else{ //特殊情况:最右的父节点等于current parentOfRightMost = rightMost.left; } } size--; return true; } /**得到该树的大小**/ @Override public int getSize() { return size; } /**得到该树的根节点**/ public TreeNode getRoot(){ return root; } /**返回从根节点指定结点的路径**/ public ArrayList<TreeNode<E>> b490 path(E e){ ArrayList<TreeNode<E>> list = new ArrayList<TreeNode<E>>(); TreeNode<E> current = root; while(current != null){ list.add(current);//添加一个结点到这个线性表 if(e.compareTo(current.element) < 0){ current = current.left; } else if(e.compareTo(current.element) > 0){ current = current.right; } else break; } return list;//返回一个结点的线性表 } /**获得指定结点所在层数**/ public int getNodeLevel(E e){ return getNodeLevel(root,e, 1); } /**获得指定结点所在层数**/ private int getNodeLevel(TreeNode<E> root,E e,int level){ if(root != null){ if(root.element.equals(e)){//查找成功 return level; } else{ level++; int temp = getNodeLevel(root.left,e, level);//判断所查找值是否在左边 if(temp == 0){ return getNodeLevel(root.right, e,level);//判断查找的值是否在右边 } else { return temp; } } } return 0; } /**得到指定层数的结点个数**/ public int getLevelNodeNum(int level){ return getLevelNodeNum(root, level, 0); } /**得到指定层数的结点个数**/ private int getLevelNodeNum(TreeNode<E> root,int level, int sum){ if(root == null){ return sum; } if(level == 0){//找到了该层 return ++sum; } level--;//进入下一层 sum = getLevelNodeNum(root.left, level, sum);//遍历左树 sum = getLevelNodeNum(root.right, level, sum);//遍历右树 return sum; } /**输出指定结点的父节点**/ public void printPrent(E e){ System.out.println(root.element); printPrent(e, root); } /**输出指定结点的父节点**/ private boolean printPrent(E e, TreeNode<E> root){ if(root == null||root.left == null||root.right == null){ return false; } else if(root.left.element.equals(e)||root.right.element.equals(e)){ System.out.println(root.element); return true; } else if(printPrent(e, root.left)||printPrent(e, root.right)){ System.out.println(root.element); return true; } return false; } /**判断两棵二叉树是否相似**/ public boolean isLike(BinaryTree<E> tree){ return (tree.size == this.size)&&isLike(tree.getRoot(),this.root); } /**判断两棵二叉树是否相似**/ private boolean isLike(TreeNode<E> e1, TreeNode<E> e2){ if(e1 == null && e2 == null){//当有一个二叉树的一条支路遍历完时,另一个也应该遍历完 return true; } else if(e1 == null|| e2 == null){//否则,只要有一个二叉树的一个支路遍历完而另一个没有,说明不相似 return false; } return (isLike(e1.left, e2.left)&&isLike(e1.right,e2.right)); } /**获得二叉树结点数量**/ public int getNodeNum(){ return getNodeNum(root); } /**获得二叉树结点数量**/ private int getNodeNum(TreeNode<E> e){ if(e == null){ return 0; } return getNodeNum(e.left) + getNodeNum(e.right) + 1; } /**输出叶子结点**/ public void printLeaf(){ printLeaf(root); } /**输出叶子结点**/ private void printLeaf(TreeNode<E> e){ if(e != null){ if(e.left == null && e.right == null){ System.out.println(e.element); } printLeaf(e.left); printLeaf(e.right); } } /**非递归方式后续遍历输出**/ public void postOrderInLoop(){ Stack<TreeNode<E>> stack = new Stack<TreeNode<E>>();//为了避免结点所存值相同而无法判别的问题,这里采用通过结点来判断 Stack<TreeNode<E>> tempStack = new Stack<TreeNode<E>>(); boolean isChanged = false; TreeNode<E> current = root; while(current != null){ stack.push(current); if(current.right != null){//如果左子节点为空,但右子节点不为空,将其存入stack栈中 if(current.left == null){ current = current.right; stack.push(current); } else {//如果左右结点都不为空,将该结点存入tempStack栈中 tempStack.push(current); } } if(current.left == null && current.right == null){ while(!stack.isEmpty()){ if(!tempStack.isEmpty()){ if(stack.peek() == tempStack.peek()){ current = tempStack.pop(); isChanged = true; break; } else { System.out.println(stack.pop().element); } } else { System.out.println(stack.pop().element); } } } if(!isChanged){ current = current.left; } else { isChanged = false; current = current.right; } } } /**获得一个中序遍历的迭代器**/ public Iterator inorderIterator(){ return new InorderIterator(); } /**InorderIterator内部类**/ class InorderIterator implements Iterator{ //存储元素的线性表 private ArrayList<E> list = new ArrayList<E>(); private int current = 0;//指向线性表的指针 public InorderIterator(){ inorder();//中序遍历该树并将其各个元素储存到线性表中 } /**从根节点开始,中序遍历该树**/ private void inorder(){ inorder(root); } /**中序遍历子树**/ private void inorder(TreeNode<E> root){ if(root == null){ return; } inorder(root.left); list.add(root.element); inorder(root.right); } /**判断继续遍历是否还存在元素**/ @Override public boolean hasNext() { if(current < list.size()) return true; return false; } /**得到下一个元素**/ @Override public Object next() { return list.get(current++); } /**删除当前元素并刷新列表**/ public void remove(){ delete(list.get(current));//删除当前元素 list.clear();//清空线性表 inorder();//重建线性表 } } /**清空该树**/ public void clear(){ root = null; size = 0; } public static class TreeNode<E>{ @SuppressWarnings("unused") public E element; public TreeNode<E> left; public TreeNode<E> right; public TreeNode(E element){ this.element = element; } } }
相关文章推荐
- 内部服务器错误,HTTP 500的一个比较详细的解释(转帖)
- tcpdump 一个比较详细的用法
- 写一个个人认为比较详细的adaboost算法
- 一个写的比较详细的mapreduce介绍
- 其实,我对一个php站点,比较有印象的,详细分享下
- 找到一个比较详细的批处理命令的介绍
- 发现一个比较详细的vim介绍
- Activity的生命周期模型在Google提供的官方文档上有比较详细的一个图示
- 找到一个比较详细的批处理命令的介绍
- Spring单例与线程安全小结--一个比较详细思路清晰很多对术语解释的贴
- 针对这一段时间ASP.NET版中比较集中突出的问题,我写了一个完整的页面,包含显示/修改/删除/添加/排序/合并/写文件/显示图片或文档,有详细代码注释
- 内部服务器错误,HTTP 500的一个比较详细的解释
- def文件一个比较详细的例子
- 一个学习数据库索引的比较详细和深入的教程,的确不错。
- 转的一个比较详细的侧滑效果
- struts2和springMVC的比较(超详细)
- IOS学习 非ARC工程转ARC工程以及其内部对应(比较详细的记录的主要问题)
- 一个比较综合的Java语言基础试题
- 看一个比较各种语言的帖子的一点看法
- 比较实用的一个服务器性能跟踪方法