您的位置:首页 > 编程语言 > Java开发

一个比较详细的二叉查找树

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

贴代码

<--------------------------------------接口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;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息