说明
《数据结构与算法分析-java语言描述》
– 练习4.13
编写TreeSet类的实现程序,其中相关的迭代器使用二叉树查找树。
<mark>在每个节点上添加通向下一个最小节点和下一个最大节点的链。</mark>
为使所编程序更简单,<mark>添加头节点和尾节点</mark>,它们不属于二叉树的一部分,但有助于使得程序的链表部分更简单。
理解
其实就是在每个树节点上添加双向链表信息。
树种记录收尾节点
(我的)代码
package cn.edut.tree;
import java.util.Iterator;
import org.junit.Test;
public class MyTreeSet3 <T extends Comparable<? super T> > {
private BinaryNode<T> root ;
private BinaryNode<T> first ;
private BinaryNode<T> last ;
private int size;
private int modCount ;
public void insert(T e ) {
root = insert(e,root , null , null);
}
public void print() {
System.out.print("[ ");
BinaryNode<T> next = first ;
for(int index=0 ; index<size ; index++) {
System.out.print(next.elementData);
if(index<size-1) {
System.out.print(", ");
}
next = next.next ;
}
System.out.println("]");
}
public Iterator<T> iterator() {
return new Itr() ;
}
public void listAll() {
listAll_mid(root , 0);
}
public void remove(T e) {
root = remove(e, root ,null , null);
}
public int size() {
return size ;
}
public boolean isEmpty() {
return size == 0 ;
}
private BinaryNode<T> remove(T e , BinaryNode<T> currentNode ,
BinaryNode<T> prevNode , BinaryNode<T> nextNode){
if(currentNode == null) {
return null;
}
int flag = e.compareTo(currentNode.elementData);
if(flag<0) {
currentNode.left = remove(e, currentNode.left , currentNode.prev , currentNode);
}else if(flag>0) {
currentNode.right = remove(e, currentNode.right, currentNode, currentNode.next);
}else {//找到 相同的,进行删除
if(currentNode.left!=null&¤tNode.right!=null) {
BinaryNode<T> minNode = finMax(currentNode.right) ;
currentNode.elementData = minNode.elementData ;
currentNode.right = remove(minNode.elementData,currentNode.right ,
currentNode , currentNode.next);
}else {
if(prevNode!=null) {
prevNode.next = nextNode;
}
if(nextNode!=null) {
nextNode.prev = currentNode.prev ;
}
currentNode.next=null;
currentNode.prev=null;
currentNode = currentNode.left!=null?currentNode.left:currentNode.right;
modCount++;
size--;
}
}
return currentNode ;
}
private void listAll_mid(BinaryNode<T> currentNode , int depth) {
if(currentNode.right!=null) {
listAll_mid(currentNode.right , depth+1);
}
System.out.print("[");
for(int i=0 ; i<depth ; i++)
{
System.out.print("~~~ ");
}
System.out.println(currentNode.elementData+" : ");
if(currentNode.left!=null) {
listAll_mid(currentNode.left , depth+1);
}
}
private BinaryNode<T> finMax(BinaryNode<T> currentNode){
return last ;
}
private BinaryNode<T> finMin(BinaryNode<T> currentNode){
return first ;
}
/** * 添加, * 空时候,添加节点 * @param e */
private BinaryNode<T> insert(T e , BinaryNode<T> currentNode ,BinaryNode<T> prevNode , BinaryNode<T> nextNode){
//空
if(currentNode==null) {
currentNode = new BinaryNode<T>(e,null,null,prevNode,nextNode);
//链表的头
if(prevNode!=null){
prevNode.next = currentNode ;
}else {
first = currentNode ;
}
if(nextNode!=null) {
nextNode.prev = currentNode;
}else {
last = currentNode;
}
//添加成功
modCount++;
size++;
}else {
int flag = e.compareTo(currentNode.elementData);
if(flag<0) {
currentNode.left = insert(e, currentNode.left, currentNode.prev , currentNode);
}else if(flag>0) {
currentNode.right = insert(e, currentNode.right,currentNode , currentNode.next);
}else {
}
}
return currentNode ;
}
private class Itr implements Iterator<T>{
private BinaryNode<T> prevNode;
private BinaryNode<T> currentNode ;
private int expectModCount ;
private boolean isOkRemove ;
public Itr() {
expectModCount = modCount;
currentNode = first;
isOkRemove = false;
}
@Override
public boolean hasNext() {
return currentNode!=null ;
}
@Override
public T next() {
isLegal();
prevNode = currentNode ;
currentNode = currentNode.next;
isOkRemove = true;
return prevNode.elementData ;
}
@Override
public void remove() {
isLegal();
if(!isOkRemove) {
throw new RuntimeException();
}
MyTreeSet3.this.remove(prevNode.elementData);
expectModCount++;
isOkRemove=false;
}
public void isLegal() {
if(expectModCount!=modCount) {
throw new RuntimeException();
}
}
}
private static class BinaryNode<T> {
private T elementData ;
private BinaryNode<T> left ;
private BinaryNode<T> right;
private BinaryNode<T> next ;
private BinaryNode<T> prev ;
public BinaryNode(T e, BinaryNode<T> l , BinaryNode<T> r , BinaryNode<T> prev, BinaryNode<T> n ) {
elementData= e;
left = l ;
right = r ;
this.prev = prev;
next = n ;
}
}
}
测试代码
@Test
public void Test0002() {
/* * size * print */
MyTreeSet3<Integer> mt3 = new MyTreeSet3<>();
System.out.println("size="+mt3.size());
System.out.print("print:");mt3.print();
/* * insert */
mt3.insert(3);
mt3.insert(-1);
mt3.insert(2);
mt3.insert(10);
mt3.insert(5);
mt3.insert(6);
mt3.insert(4);
/* * 打印 * listAll * print */
System.out.println("添加:");
mt3.listAll();
System.out.print("print:");mt3.print();
/* * remove * listAll * print * */
System.out.println("删除:");
mt3.remove(3);
mt3.listAll();
System.out.print("print:");mt3.print();
/* * Iterator */
System.out.println("Iterator测试:");
Iterator<Integer> it = mt3.iterator() ;
while(it.hasNext()) {
System.out.println(it.next());
it.remove();
}
System.out.println("size:"+mt3.size);
System.out.println("测试成功,完结撒花!");
}
测试结果
size=0
print:[ ]
添加:
[~~~ 10 :
[~~~ ~~~ ~~~ 6 :
[~~~ ~~~ 5 :
[~~~ ~~~ ~~~ 4 :
[3 :
[~~~ ~~~ 2 :
[~~~ -1 :
print:[ -1, 2, 3, 4, 5, 6, 10]
删除:
[~~~ ~~~ 6 :
[~~~ 5 :
[~~~ ~~~ 4 :
[10 :
[~~~ ~~~ 2 :
[~~~ -1 :
print:[ -1, 2, 10, 4, 5, 6]
Iterator测试:
-1
2
10
4
5
6
10
size:0
测试成功,完结撒花!
书的答案
package cn.edut.tree;
import java.util.*;
//This solution does not use header and tail nodes.
class UnderflowException extends Exception {
};
public class MyTreeSet4<AnyType extends Comparable<? super AnyType>> {
private static class BinaryNode<AnyType> {
BinaryNode(AnyType theElement) {
this(theElement, null, null, null, null);
}
BinaryNode(AnyType theElement, BinaryNode<AnyType> lt, BinaryNode<AnyType> rt, BinaryNode<AnyType> nt,
BinaryNode<AnyType> pv) {
element = theElement;
left = lt;
right = rt;
next = nt;
prev = pv;
}
AnyType element;
BinaryNode<AnyType> left;
BinaryNode<AnyType> right;
BinaryNode<AnyType> next;
BinaryNode<AnyType> prev;
}
public java.util.Iterator<AnyType> iterator() {
return new MyTreeSet4Iterator();
}
private class MyTreeSet4Iterator implements java.util.Iterator<AnyType> {
private BinaryNode<AnyType> current = findMin(root);
private BinaryNode<AnyType> previous;
private int expectedModCount = modCount;
private boolean okToRemove = false;
private boolean atEnd = false;
public boolean hasNext() {
return !atEnd;
}
public AnyType next() {
if (modCount != expectedModCount)
throw new java.util.ConcurrentModificationException();
if (!hasNext())
throw new java.util.NoSuchElementException();
AnyType nextItem = current.element;
previous = current;
current = current.next;
if (current == null)
atEnd = true;
okToRemove = true;
return nextItem;
}
public void remove() {
if (modCount != expectedModCount)
throw new java.util.ConcurrentModificationException();
if (!okToRemove)
throw new IllegalStateException();
MyTreeSet4.this.remove(previous.element);
okToRemove = false;
}
}
public MyTreeSet4() {
root = null;
}
public void makeEmpty() {
modCount++;
root = null;
}
public boolean isEmpty() {
return root == null;
}
public boolean contains(AnyType x) {
return contains(x, root);
}
public AnyType findMin() throws UnderflowException {
if (isEmpty())
throw new UnderflowException();
else
return findMin(root).element;
}
public AnyType findMax() throws UnderflowException {
if (isEmpty())
throw new UnderflowException();
else
return findMax(root).element;
}
public void insert(AnyType x) {
root = insert(x, root, null, null);
}
public void remove(AnyType x) {
root = remove(x, root);
}
public void printTree() {
if (isEmpty())
System.out.println("Empty tree");
else
printTree(root);
}
private void printTree(BinaryNode<AnyType> t) {
if (t != null) {
printTree(t.left);
System.out.println(t.element);
printTree(t.right);
}
}
private boolean contains(AnyType x, BinaryNode<AnyType> t) {
if (t == null)
return false;
int compareResult = x.compareTo(t.element);
if (compareResult < 0)
return contains(x, t.left);
else if (compareResult > 0)
return contains(x, t.right);
else
return true; // match
}
private BinaryNode<AnyType> findMin(BinaryNode<AnyType> t) {
if (t == null)
return null;
else if (t.left == null)
return t;
return findMin(t.left);
}
private BinaryNode<AnyType> findMax(BinaryNode<AnyType> t) {
if (t == null)
return null;
else if (t.right == null)
return t;
return findMax(t.right);
}
private BinaryNode<AnyType> insert(AnyType x, BinaryNode<AnyType> t, BinaryNode<AnyType> nt,
BinaryNode<AnyType> pv) {
if (t == null) {
modCount++;
BinaryNode<AnyType> newNode = new BinaryNode<AnyType>(x, null, null, nt, pv);
if (nt != null) {
nt.prev = newNode;
}
if (pv != null) {
pv.next = newNode;
}
return newNode;
}
int compareResult = x.compareTo(t.element);
if (compareResult < 0)
t.left = insert(x, t.left, t, pv);
else if (compareResult > 0) {
t.right = insert(x, t.right, nt, t);
} else
; // duplicate
return t;
}
private BinaryNode<AnyType> remove(AnyType x, BinaryNode<AnyType> t) {
if (t == null)
return t; // not found
int compareResult = x.compareTo(t.element);
if (compareResult < 0)
t.left = remove(x, t.left);
else if (compareResult > 0)
t.right = remove(x, t.right);
else if (t.left != null && t.right != null) // two children
{
t.element = findMin(t.right).element;
t.right = remove(t.element, t.right);
} else {
modCount++;
t.prev.next = t.next; // update next and prev links
t.next.prev = t.prev;
t = (t.left != null) ? t.left : t.right;
}
return t;
}
private BinaryNode<AnyType> root;
int modCount = 0;
}