package com.test.tree;

import java.util.Iterator;

/**
* 编写TreeSet类的实现程序,其中相关的迭代器使用二叉查找树。
* 在每个节点上添加一个指向其父节点的链
* @author wyl
* @param <T>
*/
public class MyTreeSet<T extends Comparable<? super T>> { private BinaryNode<T> root; //根节点
int modCount = 0; //记录调整树结构的次数 public MyTreeSet(){
root = null;
}
/**
* 定义二叉查找树的节点
*/
private class BinaryNode<T>{
T data; //节点的值
BinaryNode<T> left; //节点的左节点
BinaryNode<T> right; //节点右节点
BinaryNode<T> parent; //节点的父节点 public BinaryNode(T data){
this(data, null, null, null);
} public BinaryNode(T data, BinaryNode<T> lt, BinaryNode<T> rt, BinaryNode<T> pt) {
this.data = data;
this.left = lt;
this.right = rt;
this.parent = pt;
}
} /**
* 定义TreeSet的迭代器
* @return
*/
public Iterator iterator(){
return new MyTreeSetIterator();
} private class MyTreeSetIterator implements Iterator { private BinaryNode<T> current = findMin(root);
private BinaryNode<T> previous;
private int expectedModCount = modCount;
private boolean okToRemove = false;
private boolean atEnd = false;
@Override
public boolean hasNext() {
// TODO Auto-generated method stub
return !atEnd;
} @Override
public T next() {
// TODO Auto-generated method stub
if(modCount != expectedModCount){
try {
throw new CurrentModificationException();
} catch (CurrentModificationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(!hasNext()){
try {
throw new NoSuchElementException();
} catch (NoSuchElementException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} T nextItem = current.data;
previous = current;
if(current.right != null){
current = findMin(current.right);
}else{
BinaryNode<T> child = current;
current = current.parent;
while(current != null && current.left != child){
child = current;
current = current.parent;
}
if(current == null){
atEnd = true;
}
}
okToRemove = true;
return nextItem;
} @Override
public void remove(){
// TODO Auto-generated method stub
if(modCount != expectedModCount){
try {
throw new CurrentModificationException();
} catch (CurrentModificationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(!okToRemove){
throw new IllegalStateException();
} try {
MyTreeSet.this.remove(previous.data);
} catch (UnderflowException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
okToRemove = false;
}
} public void makeEmpty(){
modCount++ ;
root = null;
} public boolean isEmpty(){
return root == null;
}
public boolean contains(T x){
return contains(x, root);
} public boolean contains(T x, BinaryNode<T> t){
if(t == null){
return false;
}
int compareResult = x.compareTo(t.data);
if(compareResult < 0){
return contains(x, t.left);
}else if(compareResult > 0){
return contains(x, t.right);
}else{
return true;
}
} public T findMin(){
if(isEmpty()){
try {
throw new UnderflowException();
} catch (UnderflowException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return findMin(root).data;
} public T findMax(){
if(isEmpty()){
try {
throw new UnderflowException();
} catch (UnderflowException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return findMax(root).data;
} public void insert(T x){
root = insert(x, root, null);
} public void remove(T x) throws UnderflowException{
root = remove(x, root);
} public void printTree(){
if(isEmpty()){
System.out.println("Empty tree");
}else{
printTree(root);
}
} public void printTree(BinaryNode<T> t){
if(t != null){
printTree(t.left);
System.out.println(t.data);
printTree(t.right);
}
} public BinaryNode<T> remove(T x, BinaryNode<T> t){
if(t == null){
try {
throw new UnderflowException();
} catch (UnderflowException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
int compareResult = x.compareTo(t.data);
if(compareResult < 0){
t = remove(x, t.left);
}else if(compareResult > 0){
t = remove(x, t.right);
}else if(t.left != null && t.right != null){
//要删除的节点是含有左右子树的节点
t.data = findMin(t.right).data;//将右子树的最小值作为根节点
t.right = remove(t.data, t.right);
}else{
modCount++ ;
BinaryNode<T> oneChild;
oneChild = (t.left == null)?t.left:t.right;
oneChild.parent = t.parent;
t = oneChild;
}
return t;
} public BinaryNode<T> insert(T x, BinaryNode<T> t, BinaryNode<T> parent){
if(t == null){
modCount++ ;
//空树
return new BinaryNode(x, null, null, parent);
}
int compareResult = x.compareTo(t.data);
if(compareResult < 0){
//要插入的数小于节点值,插入到左子树
t.left = insert(x, t.left, t);
}else if(compareResult > 0){
//要插入的数小于节点值,插入到左子树
t.right = insert(x, t.right, t);
}else{ }
return t;
} public BinaryNode<T> findMin(BinaryNode<T> t){
// TODO Auto-generated method stub
if(t == null){
try {
throw new UnderflowException();
} catch (UnderflowException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else if(t.left == null){
return t;
}
return findMin(t.left);
} public BinaryNode<T> findMax(BinaryNode<T> t){
// TODO Auto-generated method stub
if(t == null){
try {
throw new UnderflowException();
} catch (UnderflowException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else if(t.right == null){
return t;
}
return findMax(t.right);
} public static void main(String[] args) {
MyTreeSet<Integer> myTreeSet = new MyTreeSet<Integer>();
myTreeSet.insert(24);
myTreeSet.insert(23);
myTreeSet.insert(16);
myTreeSet.insert(20);
myTreeSet.insert(28);
myTreeSet.insert(29);
System.out.println("最小值: "+ myTreeSet.findMin());
System.out.println("最大值: "+ myTreeSet.findMax());
Iterator iter = myTreeSet.iterator();
while(iter.hasNext()){
System.out.print(iter.next() + "、");
} }
}
class UnderflowException extends Exception{}
class CurrentModificationException extends Exception{}
class NoSuchElementException extends Exception{}

编写TreeSet类的实现程序,其中相关的迭代器使用二叉查找树的更多相关文章

  1. 35.按要求编写Java程序: (1)编写一个接口:InterfaceA,只含有一个方法int method(int n); (2)编写一个类:ClassA来实现接口InterfaceA,实现int method(int n)接口方 法时,要求计算1到n的和; (3)编写另一个类:ClassB来实现接口InterfaceA,实现int method(int n)接口 方法时,要求计算n的阶乘(n

      35.按要求编写Java程序: (1)编写一个接口:InterfaceA,只含有一个方法int method(int n): (2)编写一个类:ClassA来实现接口InterfaceA,实现in ...

  2. 程序员自己编写的类和JDK类是一种合作关系。

    封装类: JAVA为每一个简单数据类型提供了一个封装类,使每个简单数据类型可以被Object来装载. 除了int和char,其余类型首字母大写即成封装类. 转换字符的方式: int I=10; Str ...

  3. 程序员自己编写的类和JDK类是一种合作关系

    封装类: JAVA为每一个简单数据类型提供了一个封装类,使每个简单数据类型可以被Object来装载. 除了int和char,其余类型首字母大写即成封装类. 转换字符的方式: int I=10; Str ...

  4. 编写一个简单的C++程序

    编写一个简单的C++程序 每个C++程序都包含一个或多个函数(function),其中一个必须命名为main.操作系统通过调用main来运行C++程序.下面是一个非常简单的main函数,它什么也不干, ...

  5. Java API —— TreeSet类

    1.TreeSet类    1)TreeSet类概述         使用元素的自然顺序对元素进行排序         或者根据创建 set 时提供的 Comparator 进行排序          ...

  6. Swift互用性: 使用Objective-C特性编写Swift类(Swift 2.0版)-b

    本节包括内容: 继承Objective-C的类(Inheriting from Objective-C Classes) 采用协议(Adopting Protocols) 编写构造器和析构器(Writ ...

  7. SLAM+语音机器人DIY系列:(二)ROS入门——4.如何编写ROS的第一个程序hello_world

    摘要 ROS机器人操作系统在机器人应用领域很流行,依托代码开源和模块间协作等特性,给机器人开发者带来了很大的方便.我们的机器人“miiboo”中的大部分程序也采用ROS进行开发,所以本文就重点对ROS ...

  8. [渣译文] 使用 MVC 5 的 EF6 Code First 入门 系列:为ASP.NET MVC应用程序读取相关数据

    这是微软官方教程Getting Started with Entity Framework 6 Code First using MVC 5 系列的翻译,这里是第七篇:为ASP.NET MVC应用程序 ...

  9. [渣译文] 使用 MVC 5 的 EF6 Code First 入门 系列:为ASP.NET MVC应用程序更新相关数据

    这是微软官方教程Getting Started with Entity Framework 6 Code First using MVC 5 系列的翻译,这里是第八篇:为ASP.NET MVC应用程序 ...

随机推荐

  1. 新提交审核app保留检查更新入口将被拒绝

    3月起要求关闭所有App内的检查更新功能,苹果App Store将向用户自动提示更新,新提交审核版本如果保留检查更新入口审核时将被拒绝,请各产品团队重点关注. 10.6 - Apple and our ...

  2. mixin 在传参中可以出现 参数 在类内部可以定义 作用域

    mixin 在传参中可以出现 参数  在类内部可以定义

  3. Centos7安装zookeeper

    1.进入/opt cd /opt 2.下载 zookeeper-3.4.10.tar.gz: wget https://mirrors.tuna.tsinghua.edu.cn/apache/zook ...

  4. Java的默认构造函数调用

    // 注意,这里不能是 public class OOO,否则编译无法通过,需把文件命名成 OOO.java class OOO { // 注意:如果不定义OOO(),那么Shapes(int i)编 ...

  5. JavaWeb—Servlet

    1.什么是Servlet 用来扩展web服务器功能的组件——早期的web服务器只能处理静态资源的请求,即需要事先将html文件准备好,并存放到web服务器上面.不能够处理动态资源的请求(需要计算,动态 ...

  6. 使用Compute Engine工具连接Linux VM

    Links: Connecting to Linux Instances 内容: 要连接Linux VM实例,必须要有一个SSH(Secure Shell)秘钥.无论何时连接一个LinuxVM实例(通 ...

  7. etl接口测试总结

    刚做完一个项目接触到了etl接口,趁还热乎做个总结. etl接口功能测试点总结:1.数据量的检查:目标表与源表数据量是否一致2.字段正确性:拉取源表字段是否为目标表所需要字段(会出现拉错字段情况)3. ...

  8. document.documentElement和document.body区别以及获取浏览器的宽高

    原文:http://www.jb51.net/article/41410.htm 1.区别: body是DOM对象里的body子节点,即 <body> 标签: documentElemen ...

  9. time函数计算时间

    学过C语言的都知道有个time函数可以计算时间, 也好像知道time(NULL)返回的是一个距离1970年1月1日0时0分0秒的秒数. #include <stdio.h> #includ ...

  10. RHEL 5 安装gcc

    rpm -ivh kernel-headers... rpm -ivh glibc-headers... rpm -ivh glibc-devel... rpm -ivh libgomp.. rpm ...