二叉查找树:Binary Search Tree
对于二叉树的任何一个节点K,左子树的任意一个节点都小于K,右子树的任意一个节点都大于或等于K,按照中序周游将各个节点打印出来会得到由小到大的排列。
节点定义的接口
/** ADT for binary tree nodes */
public interface BinNode<E> {
/** Get and set the element value */
public E element();
public void setElement(E v);
/** @return The left child */
public BinNode<E> left();
/** @return The right child */
public BinNode<E> right();
/** @return True if a leaf node, false otherwise */
public boolean isLeaf();
}
二叉树的节点定义,实现了上述接口
/**
* Binary tree node implementation: Pointers to children
*
* @param E
* The data element
* @param Key
* The associated key for the record
*/
class BSTNode<Key, E> implements BinNode<E> {
private Key key; // Key for this node
private E element; // Element for this node
private BSTNode<Key, E> left; // Pointer to left child
private BSTNode<Key, E> right; // Pointer to right child
/** Constructors */
public BSTNode() {
left = right = null;
}
public BSTNode(Key k, E val) {
left = right = null;
key = k;
element = val;
}
二叉树的实现,首先上代码,然后再详细讲解
/** Binary Search Tree */
class BST<Key extends Comparable<? super Key>, E> {
private BSTNode<Key, E> root; // Root of the BST
int nodecount; // Number of nodes in the BST
/** Constructor */
BST() {
root = null;
nodecount = 0;
}
/** Reinitialize tree */
public void clear() {
root = null;
nodecount = 0;
}
/**
* Insert a record into the tree.
*
* @param k
* Key value of the record.
* @param e
* The record to insert.
*/
public void insert(Key k, E e) {
root = inserthelp(root, k, e);
nodecount++;
}
/**
* Remove a record from the tree.
*
* @param k
* Key value of record to remove.
* @return The record removed, null if there is none.
*/
public E remove(Key k) {
E temp = findhelp(root, k); // First find it
if (temp != null) {
root = removehelp(root, k); // Now remove it
nodecount--;
}
return temp;
}
/**
* Remove and return the root node from the dictionary.
*
* @return The record removed, null if tree is empty.
*/
public E removeAny() {
if (root == null)
return null;
E temp = root.element();
root = removehelp(root, root.key());
nodecount--;
return temp;
}
/**
* @return Record with key value k, null if none exist.
* @param k
* The key value to find.
*/
public E find(Key k) {
return findhelp(root, k);
}
/** @return The number of records in the dictionary. */
public int size() {
return nodecount;
}
private E findhelp(BSTNode<Key, E> rt, Key k) {
if (rt == null)
return null;
if (rt.key().compareTo(k) > 0)
return findhelp(rt.left(), k);
else if (rt.key().compareTo(k) == 0)
return rt.element();
else
return findhelp(rt.right(), k);
}
/**
* @return The current subtree, modified to contain the new item
*/
private BSTNode<Key, E> inserthelp(BSTNode<Key, E> rt, Key k, E e) {
if (rt == null)
return new BSTNode<Key, E>(k, e);
if (rt.key().compareTo(k) > 0)
rt.setLeft(inserthelp(rt.left(), k, e));
else
rt.setRight(inserthelp(rt.right(), k, e));
return rt;
}
/**
* Remove a node with key value k
*
* @return The tree with the node removed
*/
private BSTNode<Key, E> removehelp(BSTNode<Key, E> rt, Key k) {
if (rt == null)
return null;
if (rt.key().compareTo(k) > 0)
rt.setLeft(removehelp(rt.left(), k));
else if (rt.key().compareTo(k) < 0)
rt.setRight(removehelp(rt.right(), k));
else { // Found it
if (rt.left() == null)
return rt.right();
else if (rt.right() == null)
return rt.left();
else { // Two children
BSTNode<Key, E> temp = getmin(rt.right());
rt.setElement(temp.element());
rt.setKey(temp.key());
rt.setRight(deletemin(rt.right()));
}
}
return rt;
}
private BSTNode<Key, E> getmin(BSTNode<Key, E> rt) {
if (rt.left() == null)
return rt;
return getmin(rt.left());
}
private BSTNode<Key, E> deletemin(BSTNode<Key, E> rt) {
if (rt.left() == null)
return rt.right();
rt.setLeft(deletemin(rt.left()));
return rt;
}
private void printhelp(BSTNode<Key, E> rt) {
if (rt == null)
return;
printhelp(rt.left());
printVisit(rt.element());
printhelp(rt.right());
}
private StringBuffer out;
public String toString() {
out = new StringBuffer(100);
printhelp(root);
return out.toString();
}
private void printVisit(E it) {
out.append(it + " ");
}
public static void main(String[]args){
BST<Integer, Integer> D1 = new BST<Integer, Integer>();
D1.insert(70, 70);
D1.insert(35, 35);
D1.insert(20, 20);
D1.insert(17, 17);
D1.insert(15, 15);
D1.insert(19, 19);
D1.insert(100, 110);
D1.insert(90, 90);
D1.insert(95, 95);
System.out.println(D1.toString());
System.out.println(D1.find(100));
}
}
二叉树的查找,添加,删除都是递归的典型应用
查找
首先是在二叉树中查找一个节点,首先判断根节点与要查找的元素的关键字的大小,如果等于就直接返回,大于就查找左子树,小于就查找右子树,进行递归。
private E findhelp(BSTNode<Key, E> rt, Key k) {
if (rt == null)
return null;
if (rt.key().compareTo(k) > 0)
return findhelp(rt.left(), k);
else if (rt.key().compareTo(k) == 0)
return rt.element();
else
return findhelp(rt.right(), k);
}
删除
从BST中删除值最小的节点,只需要沿着左边的链不断下移就可以找到最小的节点,删除s只需要把s父节点原来指向s的指针指向s的右节点。
private BSTNode<Key, E> deletemin(BSTNode<Key, E> rt) {
if (rt.left() == null)
return rt.right();
rt.setLeft(deletemin(rt.left()));
return rt;
}
回到根节点的路径上的各个节点的左指针都被重新赋值了
如何从bst删除任意一个位置的节点呢?
首先找到这个节点r。如果r没有子节点,将r的父节点的指向它的指针设为null,如果r有一个子节点,将R的父节点指向它的指针改为指向r的子节点。如果r有两个子节点,对右子树调用deletemin,并将函数的返回值代替被删除的值
private BSTNode<Key, E> removehelp(BSTNode<Key, E> rt, Key k) {
if (rt == null)
return null;
if (rt.key().compareTo(k) > 0)
rt.setLeft(removehelp(rt.left(), k));
else if (rt.key().compareTo(k) < 0)
rt.setRight(removehelp(rt.right(), k));
else { // Found it
if (rt.left() == null)
return rt.right();
else if (rt.right() == null)
return rt.left();
else { // Two children
BSTNode<Key, E> temp = getmin(rt.right());
rt.setElement(temp.element());
rt.setKey(temp.key());
rt.setRight(deletemin(rt.right()));
}
}
return rt;
}
插入节点
private BSTNode<Key, E> inserthelp(BSTNode<Key, E> rt, Key k, E e) {
if (rt == null)
return new BSTNode<Key, E>(k, e);
if (rt.key().compareTo(k) > 0)
rt.setLeft(inserthelp(rt.left(), k, e));
else
rt.setRight(inserthelp(rt.right(), k, e));
return rt;
}
如何按层打印二叉树
参照图的广度遍历
public void printlevel(){
Queue<BSTNode> queue = new LinkedList<BSTNode>();
System.out.println(root.element());
queue.offer(root);
while (queue.size()!=0) {
BSTNode<Key, E> temp = queue.poll();
if (temp.left()!=null) {
System.out.println(temp.left().element());
queue.offer(temp.left());
}
if (temp.right()!=null) {
System.out.println(temp.right().element());
queue.offer(temp.right());
}
}
}
测试
public static void main(String[]args){
BST<Integer, Integer> D1 = new BST<Integer, Integer>();
D1.insert(70, 70);
D1.insert(35, 35);
D1.insert(20, 20);
D1.insert(17, 17);
D1.insert(15, 15);
D1.insert(89, 89);
D1.insert(100, 100);
D1.insert(90, 90);
D1.insert(110, 110);
// System.out.println(D1.toString());
D1.printlevel();
}
获取树的高度
public int getHeight(BSTNode<Key, E> root){
if (root==null) {
return 0;
}else{
return 1+Math.max(getHeight(root.left()),getHeight(root.right()));
}
}
给定一个有序整数数组,元素各不相同且升序排列,如何创建一颗高度最小的二叉查找树
让数组中间点成为根节点
将数组左半部分插入左子树
将数组右半部分插入右子树
递归处理
public BSTNode<Key, E> createMinimalBST(Key[] key,E[] ele,int start,int end){
if(end < start){
return null;
}
int mid=(start+end)/2;
BSTNode<Key, E> temp=new BSTNode<Key, E>(key[mid],ele[mid]);
System.out.println(temp.element());
temp.setLeft(createMinimalBST(key, ele, start, mid-1));
temp.setRight(createMinimalBST(key, ele, mid+1, end));
return temp;
}
测试代码:
public static void main(String[]args){
BST<Integer, Integer> D1 = new BST<Integer, Integer>();
Integer[] key={1,2,3,4,5,6,7,8,9};
Integer[] ele={1,2,3,4,5,6,7,8,9};
D1.root=D1.createMinimalBST(key,ele, 0, key.length-1);
System.out.println(D1.toString());
System.out.println(D1.getHeight(D1.root));
}
来源:oschina
链接:https://my.oschina.net/u/81653/blog/222953