二叉查找树 (转载)
来源:互联网 发布:知达常青藤中学校简介 编辑:程序博客网 时间:2024/06/02 03:23
二叉查找树(Binary Search Tree),或者是一颗空树,或者是具有下列性质的二叉树:
1、若它的左子树不空,则其左子树上的所有结点的值均小于它根结点的值;
2、若它的右子树不空,则其右子树上的所有结点的值均大于它根结点的值;
3、它的左、右子树也分别为二叉查找树。
二叉查找树是基于二叉树的,其结点数据结构定义为如下:
- /**结点数据结构*/
- static class BinaryNode<T>
- {
- T data;
- BinaryNode<T> left;
- BinaryNode<T> right;
- public BinaryNode(T data) {
- this(data,null,null);
- }
- public BinaryNode( T data, BinaryNode<T> left, BinaryNode<T> right) {
- this.data =data;
- this.left = left;
- this.right =right;
- }
- public BinaryNode()
- {
- data =null;
- this.left = left;
- this.right =right;
- }
- }
/**结点数据结构*/ static class BinaryNode<T>{T data;BinaryNode<T> left;BinaryNode<T> right;public BinaryNode(T data) {this(data,null,null);}public BinaryNode( T data, BinaryNode<T> left, BinaryNode<T> right) {this.data =data;this.left = left;this.right =right;}public BinaryNode(){data =null;this.left = left;this.right =right;}}
现在明白了什么是二叉查找树,那么二叉查找书的基本操作又是如何来实现的呢?
查找操作
在二叉查找树中查找x的过程如下:
1、若二叉树是空树,则查找失败。
2、若x等于根结点的数据,则查找成功,否则。
3、若x小于根结点的数据,则递归查找其左子树,否则。
4、递归查找其右子树。
根据上述的步骤,写出其查找操作的代码:
- /**查找指定的元素,默认从
- * 根结点出开始查询*/
- public boolean contains(T t)
- {
- return contains(t, rootTree);
- }
- /**从某个结点出开始查找元素*/
- public boolean contains(T t, BinaryNode<T> node)
- {
- if(node==null)
- return false;//结点为空,查找失败
- int result = t.compareTo(node.data);
- if(result>0)
- return contains(t,node.right);//递归查询右子树
- else if(result<0)
- return contains(t, node.left);//递归查询左子树
- else
- return true;
- }
- /**
- 这里我提供一个对二叉树最大值
- 最小值的搜索*/
- /**找到二叉查找树中的最小值*/
- public T findMin()
- {
- if(isEmpty())
- {
- System.out.println("二叉树为空");
- return null;
- }else
- return findMin(rootTree).data;
- }
- /**找到二叉查找树中的最大值*/
- public T findMax()
- {
- if(isEmpty())
- {
- System.out.println("二叉树为空");
- return null;
- }else
- return findMax(rootTree).data;
- }
- /**查询出最小元素所在的结点*/
- public BinaryNode<T> findMin(BinaryNode<T> node)
- {
- if(node==null)
- return null;
- else if(node.left==null)
- return node;
- return findMin(node.left);//递归查找
- }
- /**查询出最大元素所在的结点*/
- public BinaryNode<T> findMax(BinaryNode<T> node)
- {
- if(node!=null)
- {
- while(node.right!=null)
- node=node.right;
- }
- return node;
- }
/**查找指定的元素,默认从 * 根结点出开始查询*/ public boolean contains(T t) { return contains(t, rootTree); } /**从某个结点出开始查找元素*/ public boolean contains(T t, BinaryNode<T> node) { if(node==null) return false;//结点为空,查找失败 int result = t.compareTo(node.data); if(result>0) return contains(t,node.right);//递归查询右子树 else if(result<0) return contains(t, node.left);//递归查询左子树 else return true; } /** 这里我提供一个对二叉树最大值 最小值的搜索*/ /**找到二叉查找树中的最小值*/ public T findMin() { if(isEmpty()) { System.out.println("二叉树为空"); return null; }else return findMin(rootTree).data; } /**找到二叉查找树中的最大值*/ public T findMax() { if(isEmpty()) { System.out.println("二叉树为空"); return null; }else return findMax(rootTree).data; }/**查询出最小元素所在的结点*/ public BinaryNode<T> findMin(BinaryNode<T> node) { if(node==null) return null; else if(node.left==null) return node; return findMin(node.left);//递归查找 } /**查询出最大元素所在的结点*/ public BinaryNode<T> findMax(BinaryNode<T> node) { if(node!=null) { while(node.right!=null) node=node.right; } return node; }
插入操作
二叉树查找树b插入操作x的过程如下:
1、若b是空树,则直接将插入的结点作为根结点插入。
2、x等于b的根结点的数据的值,则直接返回,否则。
3、若x小于b的根结点的数据的值,则将x要插入的结点的位置改变为b的左子树,否则。
4、将x要出入的结点的位置改变为b的右子树。
代码实现如下:
- /**插入元素*/
- public void insert(T t)
- {
- rootTree = insert(t, rootTree);
- }
- /**在某个位置开始判断插入元素*/
- public BinaryNode<T> insert(T t,BinaryNode<T> node)
- {
- if(node==null)
- {
- //新构造一个二叉查找树
- return new BinaryNode<T>(t, null, null);
- }
- int result = t.compareTo(node.data);
- if(result<0)
- node.left= insert(t,node.left);
- else if(result>0)
- node.right= insert(t,node.right);
- else
- ;//doNothing
- return node;
- }
/**插入元素*/ public void insert(T t) { rootTree = insert(t, rootTree); }/**在某个位置开始判断插入元素*/ public BinaryNode<T> insert(T t,BinaryNode<T> node) { if(node==null) { //新构造一个二叉查找树 return new BinaryNode<T>(t, null, null); } int result = t.compareTo(node.data); if(result<0) node.left= insert(t,node.left); else if(result>0) node.right= insert(t,node.right); else ;//doNothing return node; }
删除操作
对于二叉查找树的删除操作(这里根据值删除,而非结点)分三种情况:
不过在此之前,我们应该确保根据给定的值找到了要删除的结点,如若没找到该结点
不会执行删除操作!
下面三种情况假设已经找到了要删除的结点。
1、如果结点为叶子结点(没有左、右子树),此时删除该结点不会玻化树的结构
直接删除即可,并修改其父结点指向它的引用为null.如下图:
2、如果其结点只包含左子树,或者右子树的话,此时直接删除该结点,并将其左子树
或者右子树设置为其父结点的左子树或者右子树即可,此操作不会破坏树结构。
3、 当结点的左右子树都不空的时候,一般的删除策略是用其右子树的最小数据
(容易找到)代替要删除的结点数据并递归删除该结点(此时为null),因为
右子树的最小结点不可能有左孩子,所以第二次删除较为容易。
z的左子树和右子树均不空。找到z的后继y,因为y一定没有左子树,所以可以删除y,
并让y的父亲节点成为y的右子树的父亲节点,并用y的值代替z的值.如图:
删除操作源码:
- /**删除元素*/
- public void remove(T t)
- {
- rootTree = remove(t,rootTree);
- } /**在某个位置开始判断删除某个结点*/
- public BinaryNode<T> remove(T t,BinaryNode<T> node)
- {
- if(node == null)
- return node;//没有找到,doNothing
- int result = t.compareTo(node.data);
- if(result>0)
- node.right = remove(t,node.right);
- else if(result<0)
- node.left = remove(t,node.left);
- else if(node.left!=null&&node.right!=null)
- {
- node.data = findMin(node.right).data;
- node.right = remove(node.data,node.right);
- }
- else
- node = (node.left!=null)?node.left:node.right;
- return node;
- }
/**删除元素*/ public void remove(T t) { rootTree = remove(t,rootTree); } /**在某个位置开始判断删除某个结点*/ public BinaryNode<T> remove(T t,BinaryNode<T> node) { if(node == null) return node;//没有找到,doNothing int result = t.compareTo(node.data); if(result>0) node.right = remove(t,node.right); else if(result<0) node.left = remove(t,node.left); else if(node.left!=null&&node.right!=null) { node.data = findMin(node.right).data; node.right = remove(node.data,node.right); } else node = (node.left!=null)?node.left:node.right; return node; }
完整源码
- <P></P><PRE class=java name="code">package com.kiritor;
- /**
- * Java实现二叉查找树
- * @author Kiritor
- * @param <T>*/
- public class BinarySearchTree<T extends Comparable<? super T>> {
- /**结点数据结构*/
- static class BinaryNode<T>
- {
- T data;
- BinaryNode<T> left;
- BinaryNode<T> right;
- public BinaryNode(T data) {
- this(data,null,null);
- }
- public BinaryNode( T data, BinaryNode<T> left, BinaryNode<T> right) {
- this.data =data;
- this.left = left;
- this.right =right;
- }
- public BinaryNode()
- {
- data =null;
- this.left = left;
- this.right =right;
- }
- }
- private BinaryNode<T> rootTree;
- /**构造一颗空的二叉查找树*/
- public BinarySearchTree()
- {
- rootTree = null;
- }
- /**清空二叉查找树*/
- public void clear()
- {
- rootTree = null;
- }
- /**判断是否为空*/
- public boolean isEmpty()
- {
- return rootTree == null;
- }
- /**查找指定的元素,默认从
- * 根结点出开始查询*/
- public boolean contains(T t)
- {
- return contains(t, rootTree);
- }
- /**找到二叉查找树中的最小值*/
- public T findMin()
- {
- if(isEmpty())
- {
- System.out.println("二叉树为空");
- return null;
- }else
- return findMin(rootTree).data;
- }
- /**找到二叉查找树中的最大值*/
- public T findMax()
- {
- if(isEmpty())
- {
- System.out.println("二叉树为空");
- return null;
- }else
- return findMax(rootTree).data;
- }
- /**插入元素*/
- public void insert(T t)
- {
- rootTree = insert(t, rootTree);
- }
- /**删除元素*/
- public void remove(T t)
- {
- rootTree = remove(t,rootTree);
- }
- /**打印二叉查找树*/
- public void printTree()
- {
- }
- /**从某个结点出开始查找元素*/
- public boolean contains(T t, BinaryNode<T> node)
- {
- if(node==null)
- return false;
- int result = t.compareTo(node.data);
- if(result>0)
- return contains(t,node.right);
- else if(result<0)
- return contains(t, node.left);
- else
- return true;
- }
- /**查询出最小元素所在的结点*/
- public BinaryNode<T> findMin(BinaryNode<T> node)
- {
- if(node==null)
- return null;
- else if(node.left==null)
- return node;
- return findMin(node.left);//递归查找
- }
- /**查询出最大元素所在的结点*/
- public BinaryNode<T> findMax(BinaryNode<T> node)
- {
- if(node!=null)
- {
- while(node.right!=null)
- node=node.right;
- }
- return node;
- }
- /**在某个位置开始判断插入元素*/
- public BinaryNode<T> insert(T t,BinaryNode<T> node)
- {
- if(node==null)
- {
- //新构造一个二叉查找树
- return new BinaryNode<T>(t, null, null);
- }
- int result = t.compareTo(node.data);
- if(result<0)
- node.left= insert(t,node.left);
- else if(result>0)
- node.right= insert(t,node.right);
- else
- ;//doNothing
- return node;
- }
- /**在某个位置开始判断删除某个结点*/
- public BinaryNode<T> remove(T t,BinaryNode<T> node)
- {
- if(node == null)
- return node;//没有找到,doNothing
- int result = t.compareTo(node.data);
- if(result>0)
- node.right = remove(t,node.right);
- else if(result<0)
- node.left = remove(t,node.left);
- else if(node.left!=null&&node.right!=null)
- {
- node.data = findMin(node.right).data;
- node.right = remove(node.data,node.right);
- }
- else
- node = (node.left!=null)?node.left:node.right;
- return node;
- }
- public BinaryNode<Integer> init()
- {
- BinaryNode<Integer> node3 = new BinaryNode<Integer>(3);
- BinaryNode<Integer> node1 = new BinaryNode<Integer>(1);
- BinaryNode<Integer> node4 = new BinaryNode<Integer>(4,node3,null);
- BinaryNode<Integer> node2 = new BinaryNode<Integer>(2,node1,node4);
- BinaryNode<Integer> node8 = new BinaryNode<Integer>(8);
- BinaryNode<Integer> root = new BinaryNode<Integer>(6,node2,node8);
- return root;
- }
- public void preOrder(BinaryNode node) {
- if (node != null) {
- System.out.print(node.data);
- preOrder(node.left);
- preOrder(node.right);
- }
- }
- /*简单测试*/
- public static void main(String[] args) {
- BinarySearchTree searchTree = new BinarySearchTree<>();
- BinaryNode<Integer> node= searchTree.init();
- searchTree.rootTree=node;
- searchTree.preOrder(searchTree.rootTree);
- searchTree.remove(4);
- searchTree.preOrder(searchTree.rootTree);
- }
- } </PRE>
- <PRE></PRE>
- <PRE></PRE>
- <PRE></PRE>
- <PRE></PRE>
- 二叉查找树 (转载)
- 查找--二叉查找树
- 转载:二叉查找树原理分析及查找、插入、删除、遍历实现
- 二叉树、二叉查找树
- 二叉树 & 二叉查找树
- 【查找结构】二叉查找树
- 查找之二叉树查找
- 查找之二叉树查找
- 查找:二叉查找树总结
- 二叉树查找树...
- 二叉树查找树
- 查找--遍历二叉树
- 二叉查找树
- 二叉查找树实现
- 二叉查找树
- 动态二叉查找树
- 最优二叉查找树
- 二叉查找树
- jQuery实现表格全选、反选、删除一行或多行、增加一行
- Ecmall购物流程解析
- Dijkstra求解单源点最短路径
- hdu 2188 悼念512汶川大地震遇难同胞——选拔志愿者
- 第 4 章 多例模式【Multition Pattern】
- 二叉查找树 (转载)
- ALV的参数
- Web前端开发规范文档(更新于2013-01-13)
- VECTOR容器总结
- 重新组织数据之二 :Replace Data Value with Object(以对象取代数据值)
- 不同的应用场景推介使用的OpenCL Paths
- android 二维码总结
- TabGroup中两个Activity之间的传值
- 项目管理软件