二叉查找树的数组实现

1,实例变量,构造器,数组扩展

  
   private
    Object[] contents;
private int count;

public ArrayBinarySearchTree(Object root)
{
// Object[] contents = new Object[10]; 悲剧啊!!!!局部变量覆盖了类成员变量
contents = new Object[ 10 ];
contents[
0 ] = root;
count
= 1 ;
}

public void expand()
{
// Object[] larger = new Object[size()*3];
Object[] larger = new Object[contents.length * 3 ];
for ( int i = 0 ;i < contents.length;i ++ )
larger[i]
= contents[i];
contents
= larger;
}

跟二叉树的数组实现差不多

2,三种迭代器方法,删除左右子树的方法跟二叉树的数组实现一样,参见清单

3,重新定义的public int find(Comparable target)方法,相对于链式实现,在数组实现中我觉得查找一个元素返回它的下标更贴切

  
   //
   改了一下,返回找到的元素的下标,觉得这样对数组来说更有意义把
   
public int find(Comparable target) {

if (isEmpty())
{
System.out.println(
" 树为空! " );
return - 1 ;
}

int index = 0 ;

while (index < contents.length && contents[index] != null )
{
if (contents[index].equals(target))
return index;
else if (target.compareTo(contents[index]) < 0 )
index
= 2 * index + 1 ;
else index = 2 * index + 2 ;
}
return - 1 ;
}

3,二叉排序树里的重要方法

1)插入节点

数组实现插入其实跟链式思想还是一样,往下找插入节点就是往下找插入的下标,下标的关系已经在前面说过,要注意的是数组容量可能不够,需要扩展容量

  
   public
    
   void
    addElement(Comparable element) {
int index = 0 ;
if (size() == 0 )
{
contents[index]
= element;
count
++ ;
return ;
}

while (index < contents.length)
{
if (element.compareTo(contents[index]) < 0 )
{
int lindex = 2 * index + 1 ;
if (lindex >= contents.length)
expand();

if (contents[lindex] == null )
contents[lindex]
= element;
else index = lindex;
}
else
{
int rindex = 2 * index + 2 ;
if (rindex >= contents.length)
expand();

if (contents[rindex] == null )
contents[rindex]
= element;
else index = rindex;
}
}
count
++ ;
}

2)删除节点

用数组来实现删除节点似乎不太合适(也许是我自己没有想到好的方法),当某个结点被删后,它的子树上的全部结点的下标都要调整,而且这个调整顺序还得从上网下调,否则下面的节点的可能覆盖上面的,没有想到什么好的办法,最后只有用了一个消耗最大的笨方法—将被删结点置为null后,前序遍历树(或者后序,不能中序),将前序序列依次重新插入建树。相当于删除节点后,把剩下结点取出来重新建树,实在不知道有什么简易的办法了:

  
   public
    Comparable removeElement(Comparable element) {

Comparable result
= null ;

int index = find(element); // 找到指定删除元素在数组中的下标
if (index != - 1 )
{
result
= (Comparable) contents[index];
remove(index);
// count--;在remove里已经实现了
}
return result;
}


private void remove( int index){ // 删除指定下标处的元素,并得到删除后的树(调整位置)

Iterator it
= PreInorder(); // 得到前序遍历的迭代器
for ( int i = 0 ;i < contents.length;i ++ ) // 将树清空
contents[i] = null ;
count
= 0 ;
while (it.hasNext())
{
addElement((Comparable) it.next());
}
}

3)返回/删除 最大值

删除最大值还是调用上面的remove(int index)方法,先找到最大值的index即可。

返回最大值如下:

  
   public
    Comparable findMax() {
int index = 0 ;
while (( 2 * index + 2 < contents.length) && (contents[ 2 * index + 2 ] != null ))
index
= 2 * index + 2 ;
return (Comparable) contents[index];
}

4)清单及测试:

《二叉查找树的数组实现》
《二叉查找树的数组实现》
ArrayBinarySearchTree{

   
    package
     Tree;

import java.util.Iterator;

import Queue.LinkedQueue;

public class ArrayBinarySearchTree{

private Object[] contents;
private int count;

public ArrayBinarySearchTree(Object root)
{
// Object[] contents = new Object[10]; 悲剧啊!!!!局部变量覆盖了类成员变量
contents = new Object[ 10 ];
contents[
0 ] = root;
count
= 1 ;
}

public void expand()
{
// Object[] larger = new Object[size()*3];
Object[] larger = new Object[contents.length * 3 ];
for ( int i = 0 ;i < contents.length;i ++ )
larger[i]
= contents[i];
contents
= larger;
}


public int size() {
return count;
}

public boolean isEmpty() {
return (size() == 0 );
}

public Iterator iteratorInorder() {
LinkedQueue queue
= new LinkedQueue();
inorder(
0 ,queue);
return queue.iterator();
}

private void inorder( int index,LinkedQueue queue){
if (index < contents.length && contents[index] != null )
{
int lindex = 2 * index + 1 ;
int rindex = 2 * index + 2 ;

if (lindex < contents.length && contents[lindex] != null )
inorder(lindex,queue);

queue.enqueue(contents[index]);

if (rindex < contents.length && contents[rindex] != null )
inorder(rindex,queue);
}
}


public Iterator PreInorder() {
LinkedQueue queue
= new LinkedQueue();
preorder(
0 ,queue);
return queue.iterator();
}

private void preorder( int index,LinkedQueue queue){
if (index < contents.length && contents[index] != null )
{
int lindex = 2 * index + 1 ;
int rindex = 2 * index + 2 ;

queue.enqueue(contents[index]);

if (lindex < contents.length && contents[lindex] != null )
preorder(lindex,queue);

if (rindex < contents.length && contents[rindex] != null )
preorder(rindex,queue);
}
}

public Iterator PostInorder() {
LinkedQueue queue
= new LinkedQueue();
postorder(
0 ,queue);
return queue.iterator();
}

private void postorder( int index,LinkedQueue queue){
if (index < contents.length && contents[index] != null )
{
int lindex = 2 * index + 1 ;
int rindex = 2 * index + 2 ;

if (lindex < contents.length && contents[lindex] != null )
postorder(lindex,queue);

if (rindex < contents.length && contents[rindex] != null )
postorder(rindex,queue);

queue.enqueue(contents[index]);
}
}


// 改了一下,返回找到的元素的下标,觉得这样对数组来说更有意义把
public int find(Comparable target) {

if (isEmpty())
{
System.out.println(
" 树为空! " );
return - 1 ;
}

int index = 0 ;

while (index < contents.length && contents[index] != null )
{
if (contents[index].equals(target))
return index;
else if (target.compareTo(contents[index]) < 0 )
index
= 2 * index + 1 ;
else index = 2 * index + 2 ;
}
return - 1 ;
}


public boolean contains(Comparable element) {
return (find(element) != - 1 );
}


public void removeLeftSubtree() {

if (contents[ 1 ] == null )
{
System.out.println(
" 没有左子树 " );
return ;
}
else
{
contents[
1 ] = null ;
count
-- ;
removeSubtree(
1 );
}
}

public void removeRightSubtree() {

if (contents[ 2 ] == null )
{
System.out.println(
" 没有右子树 " );
return ;
}
else
{
contents[
2 ] = null ;
count
-- ;
removeSubtree(
2 );
}
}


private void removeSubtree( int index){ // 删除contents[index]的左右子树(递归)

int lindex = 2 * index + 1 ;
int rindex = 2 * index + 2 ;


if (lindex < contents.length && contents[lindex] != null )
{
contents[lindex]
= null ;
count
-- ;
removeSubtree(lindex);
}

// if(contents[rindex] != null) !!!可能数组越界
if (rindex < contents.length && contents[rindex] != null )
{
contents[rindex]
= null ;
count
-- ;
removeSubtree(rindex);
}
}


public void addElement(Comparable element) {
int index = 0 ;
if (size() == 0 )
{
contents[index]
= element;
count
++ ;
return ;
}

while (index < contents.length)
{
if (element.compareTo(contents[index]) < 0 )
{
int lindex = 2 * index + 1 ;
if (lindex >= contents.length)
expand();

if (contents[lindex] == null )
contents[lindex]
= element;
else index = lindex;
}
else
{
int rindex = 2 * index + 2 ;
if (rindex >= contents.length)
expand();

if (contents[rindex] == null )
contents[rindex]
= element;
else index = rindex;
}
}
count
++ ;
}


public Comparable removeElement(Comparable element) {

Comparable result
= null ;

int index = find(element); // 找到指定删除元素在数组中的下标
if (index != - 1 )
{
result
= (Comparable) contents[index];
remove(index);
// count--;在remove里已经实现了
}
return result;
}


private void remove( int index){ // 删除指定下标处的元素,并得到删除后的树(调整位置)

Iterator it
= PreInorder(); // 得到前序遍历的迭代器
for ( int i = 0 ;i < contents.length;i ++ ) // 将树清空
contents[i] = null ;
count
= 0 ;
while (it.hasNext())
{
addElement((Comparable) it.next());
}
}

public Comparable findMax() {
int index = 0 ;
while (( 2 * index + 2 < contents.length) && (contents[ 2 * index + 2 ] != null ))
index
= 2 * index + 2 ;
return (Comparable) contents[index];
}

public Comparable findMin() {
int index = 0 ;
while (( 2 * index + 1 < contents.length) && (contents[index * 2 + 1 ] != null ))
index
= index * 2 + 1 ;
return (Comparable) contents[index];
}

public Comparable removeMax() {
int index = 0 ;
while (( 2 * index + 2 < contents.length) && (contents[ 2 * index + 2 ] != null ))
index
= 2 * index + 2 ;
Comparable result
= (Comparable) contents[index];
remove(index);
return result;
}

public Comparable removeMin() {
int index = 0 ;
while (( 2 * index + 1 < contents.length) && (contents[ 2 * index + 1 ] != null ))
index
= 2 * index + 1 ;
Comparable result
= (Comparable) contents[index];
remove(index);
return result;
}

public static void main(String[] args) {

BinarySearchTree tree
= new BinarySearchTree();

// 二叉排序树的形状跟插入顺序有关,中序序列总是不变(有序)
tree.addElement( 10 );
tree.addElement(
5 );
tree.addElement(
3 );
tree.addElement(
7 );
tree.addElement(
6 );
tree.addElement(
9 );
tree.addElement(
8 );
tree.addElement(
13 );
tree.addElement(
11 );
tree.addElement(
20 );
tree.addElement(
25 );
tree.addElement(
16 );

System.out.println(
" \n中序遍历结果为: " );
Iterator it
= tree.iteratorInorder();
while (it.hasNext())
System.out.print(it.next()
+ " " );

System.out.println(
" \n前序遍历结果为: " );
it
= tree.PreInorder();
while (it.hasNext())
System.out.print(it.next()
+ " " );

System.out.println(
" \n后序遍历结果为: " );
it
= tree.PostInorder();
while (it.hasNext())
System.out.print(it.next()
+ " " );
System.out.println(
" \n\n " + " 最小元素为: " + tree.findMin());
System.out.println(
" \n " + " 最大元素为: " + tree.findMax());

/*
tree.removeMin();

System.out.println("\n删除最小元素3后的前序序列: ");
it = tree.PreInorder();
while(it.hasNext())
System.out.print(it.next() + " ");


tree.removeMin();

System.out.println("\n\n接着删除最小元素5后的前序序列: ");
it = tree.PreInorder();
while(it.hasNext())
System.out.print(it.next() + " ");

*/

tree.removeElement(
10 );
tree.removeElement(
9 );
tree.removeElement(
13 );
tree.removeElement(
5 );

System.out.println(
" \n\n删除节点后前序遍历结果为: " );
it
= tree.PreInorder();
while (it.hasNext())
System.out.print(it.next()
+ " " );
}


}

仍然构造链式实现的那个二叉排序树:

《二叉查找树的数组实现》

结果:

中序遍历结果为:

3 5 6 7 8 9 10 11 13 16 20 25

前序遍历结果为:

10 5 3 7 6 9 8 13 11 20 16 25

后序遍历结果为:

3 6 8 9 7 5 11 16 25 20 13 10

最小元素为: 3

最大元素为: 25

删除节点后前序遍历结果为:

8 3 7 6 11 20 16 25

    原文作者:jinmengzhe
    原文地址: https://www.cnblogs.com/jmzz/archive/2011/05/15/2047228.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞