zoukankan      html  css  js  c++  java
  • java实现二叉排序树

    在计算机科学中,树是一种非常重要的数据结构,而且有非常广泛的应用,例如linux下的目录结构就可以看成是一棵树,另外树也是存储大量的数据一种解决方法,二叉排序树是树的一种特殊情形,它的每个节点之多只能有两个子节点,同时左子树的节点都小于它的父节点,右子树中的节点都大于它的父节点,二叉排序树在搜索中的应用非常广泛,同时二叉排序树的一个变种(红黑树)是java中TreeMap和TreeSet的实现基础。下边是二叉排序树的定义,其中用到了两个类,一个是Node类,代表树中的节点,另外一个是Name类,表示节点的数据,Name类实现Comparable接口,这样才可以比较节点的大小。

    public class BinarySearchTree{
    	private Node root;
    	private int size;
    	
    	public BinarySearchTree(Node root){
    		this.root=root;
    		size++;
    	}
    	
    	public int getSize(){
    		return this.size;
    	}
    	
    	public boolean contains(Name name){
    		return contains(name,this.root);
    		//return false;
    	}
    	
    	private boolean contains(Name n,Node root){
    		if(root==null){
    			return false;
    		}
    		int compare=n.compareTo(root.element);
    		if(compare>0){
    			if(root.right!=null){
    				return contains(n,root.right);
    			}else{
    				return false;
    			}
    		}else if(compare<0){
    			if(root.left!=null){
    				return contains(n,root.left);
    			}else{
    				return false;
    			}
    		}else{
    			return true;
    		}
    	}
    	
    	public boolean insert(Name n){
    		boolean flag = insert(n,this.root);
    		if(flag) size++;
    		return flag;
    	}
    	
    	private boolean insert(Name n,Node root){
    		if(root==null){
    			this.root=new Node(n);
    			return true;
    		}else if(root.element.compareTo(n)>0){
    			if(root.left!=null){
    				return insert(n,root.left);
    			}else{
    				root.left=new Node(n);
    				return true;
    			}
    		}else if(root.element.compareTo(n)<0){
    			if(root.right!=null){
    				return insert(n,root.right);
    			}else{
    				root.right=new Node(n);
    				return true;
    			}
    		}else{
    			root.frequency++;
    			return true;
    		}
    	}
    
    	public boolean remove(Name name){
    		root = remove(name,this.root);
    		if(root != null){
    			size--;
    			return true;
    		}
    		return false;
    	}
    	
    	private Node remove(Name name,Node root){
    		int compare = root.element.compareTo(name);
    		if(compare == 0){
    			if(root.frequency>1){
    				root.frequency--;
    			}else{
    				/**根据删除节点的类型,分成以下几种情况
    				**①如果被删除的节点是叶子节点,直接删除
    				**②如果被删除的节点含有一个子节点,让指向该节点的指针指向他的儿子节点
    				**③如果被删除的节点含有两个子节点,找到左字数的最大节点,并替换该节点
    				**/
    				if(root.left == null && root.right == null){
    					root = null;
    				}else if(root.left !=null && root.right == null){
    					root = root.left;
    				}else if(root.left == null && root.right != null){
    					root = root.right;
    				}else{
    					//被删除的节点含有两个子节点
    					Node newRoot = root.left;
    					while (newRoot.left != null){
    						newRoot = newRoot.left;//找到左子树的最大节点
    					}
    					root.element = newRoot.element;
    					root.left = remove(root.element,root.left);
    				}
    			}
    		}else if(compare > 0){
    			if(root.left != null){
    				root.left = remove(name,root.left);
    			}else{
    				return null;
    			}
    		}else{
    			if(root.right != null){
    				root.right = remove(name,root.right);
    			}else{
    				return null;
    			}
    		}
    		return root;
    	}
    
    	public String toString(){
    		//中序遍历就可以输出树中节点的顺序
    		return toString(root);
    	}
    	
    	private String toString(Node n){
    		String result = "";
    		if(n != null){
    			if(n.left != null){
    				result += toString(n.left);
    			}
    			result += n.element + " ";
    			if(n.right != null){
    				result += toString(n.right);
    			}
    		}
    		return result;
    	}
    	
    }
    

    在二叉排序树的操作中,节点的删除时最难处理的,要分成很多种情况分别进行处理,下边是Node类和Name类的定义:

    class Node{
    	public Name element;
    	public Node left;
    	public Node right; 
    	public int frequency = 1;
    	
    	public Node(Name n){
    		this.element=n;
    	}
    }
    
    class Name implements Comparable<Name>{
    	private String firstName;
    	private String lastName;
    	
    	public Name(String firstName,String lastName){
    		this.firstName=firstName;
    		this.lastName=lastName;
    	}
    	
    	public int compareTo(Name n) {
    		int result = this.firstName.compareTo(n.firstName);
    		return result==0?this.lastName.compareTo(n.lastName):result;
    	}
    	
    	public String toString(){
    		return firstName + "-" +lastName;
    	}
    }
    

    最后是二叉排序树的测试:

    public static void main(String[] args){
    		//System.out.println("sunzhenxing");
    		Node root = new Node(new Name("sun","zhenxing5"));
    		BinarySearchTree bst =new BinarySearchTree(root);
    		bst.insert(new Name("sun","zhenxing3"));
    		bst.insert(new Name("sun","zhenxing7"));
    		bst.insert(new Name("sun","zhenxing2"));
    		bst.insert(new Name("sun","zhenxing4"));
    		bst.insert(new Name("sun","zhenxing6"));
    		bst.insert(new Name("sun","zhenxing8"));
    		System.out.println(bst);
    		bst.remove(new Name("sun","zhenxing2"));
    		System.out.println(bst);
    		bst.remove(new Name("sun","zhenxing7"));
    		System.out.println(bst);
    }
    

    测试输出是:

    sun-zhenxing2 sun-zhenxing3 sun-zhenxing4 sun-zhenxing5 sun-zhenxing6 sun-zhenxing7 sun-zhenxing8
    sun-zhenxing3 sun-zhenxing4 sun-zhenxing5 sun-zhenxing6 sun-zhenxing7 sun-zhenxing8
    sun-zhenxing3 sun-zhenxing4 sun-zhenxing5 sun-zhenxing6 sun-zhenxing8

  • 相关阅读:
    Linux 进程终止后自动重启
    (转) Android中ViewStub组件使用
    (转)android UI进阶之用ViewPager实现欢迎引导页面
    (转)android UI进阶之实现listview的分页加载
    (转)android UI进阶之实现listview的下拉加载
    (转)android UI进阶之弹窗的使用(2)实现通讯录的弹窗效果
    学习网址
    (转)android UI进阶之实现listview中checkbox的多选与记录
    (转)android UI进阶之自定义组合控件
    (转)Android里merge和include标签的使用
  • 原文地址:https://www.cnblogs.com/sunzhenxing19860608/p/1972222.html
Copyright © 2011-2022 走看看