数组实现二叉查找树
2014-07-15 18:47
316 查看
1,实例变量,构造器,数组扩展
跟二叉树的数组实现差不多
2,三种迭代器方法,删除左右子树的方法跟二叉树的数组实现一样,参见清单
3,重新定义的public int find(Comparable target)方法,相对于链式实现,在数组实现中我觉得查找一个元素返回它的下标更贴切
3,二叉排序树里的重要方法
1)插入节点
数组实现插入其实跟链式思想还是一样,往下找插入节点就是往下找插入的下标,下标的关系已经在前面说过,要注意的是数组容量可能不够,需要扩展容量
2)删除节点
用数组来实现删除节点似乎不太合适(也许是我自己没有想到好的方法),当某个结点被删后,它的子树上的全部结点的下标都要调整,而且这个调整顺序还得从上网下调,否则下面的节点的可能覆盖上面的,没有想到什么好的办法,最后只有用了一个消耗最大的笨方法---将被删结点置为null后,前序遍历树(或者后序,不能中序),将前序序列依次重新插入建树。相当于删除节点后,把剩下结点取出来重新建树,实在不知道有什么简易的办法了:
3)返回/删除 最大值
删除最大值还是调用上面的remove(int index)方法,先找到最大值的index即可。
返回最大值如下:
4)清单及测试:
仍然构造链式实现的那个二叉排序树:
结果:
中序遍历结果为:
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
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)清单及测试:
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
相关文章推荐
- 二叉查找树数组表示的JavaScript实现
- c#使用数组实现二叉查找树
- 二叉查找树的数组实现
- 基于数组的二叉查找树 Binary Search Tree (Java实现)
- 用C++二级指针实现像C#一样的动态交错数组
- 【库】c实现图(数组表示法)
- 数据结构+C++_№4 抽象数组的实现 代码补充及更正
- 实现对中文字符串数组按照音序排列
- C++实战:一个轻型数组类的实现
- asp中利用数组实现数据库记录的批量录入方法
- JavaScript中实现数组的排序、乱序和搜索
- 《面向对象程序设计与VC++实现》--liwei_2_2(以递增顺序对数组排序)
- C#实现数组的排序
- 用字符串数组实现的大数运算
- vb6中用zlib.dll实现压缩/解压缩字节数组
- ZT:C++Builder中实现控件数组的功能
- 利用数组实现数据库记录的批量录入
- 【库】c实现数组
- 数组下标是字符串的实现
- C# 没有动态数组,实现动态数组 && local copy(dll)