`
baby69yy2000
  • 浏览: 187803 次
  • 性别: Icon_minigender_1
  • 来自: 自己输入城市...
社区版块
存档分类
最新评论

二叉排序树的TreeMap类设计

    博客分类:
  • Util
阅读更多
Iterable接口
package MyInterface;

public interface Iterable<T>{
	Iterator<T> iterator();
}


Iterator接口
package MyInterface;

public interface Iterator<T> {
	boolean hasNext();
	T next();
	void remove();
}


Map接口
package MyInterface;

import MyInterface.Set;

public interface Map<K, V> {

	int size();

	boolean isEmpty();

	boolean containsKey(Object key);

	V get(Object key);

	V put(K key, V value);

	V remove(Object key);

	void clear();

	Set<K> keySet();

	Set<Map.Entry<K, V>> entrySet();

	/** 内部接口 */
	interface Entry<K, V> {
		K getKey();

		V getValue();

		V setValue(V value);
	}
}


OrderedMap接口
package MyInterface;
public interface OrderedMap<K, V> extends Map<K, V> {
	K firstKey();
	K lastKey();
}


Set接口
package MyInterface;
import MyInterface.Iterable;
public interface Set<T> extends Iterable<T> {
	int size();
	boolean isEmpty();
	boolean contains(Object item);
	Iterator<T> iterator();
	Object[] toArray();
	boolean add(T item);
	boolean remove(Object item);
	void clear();
}


TreeMap类
package Map;
import java.util.ConcurrentModificationException;
import java.util.NoSuchElementException;

import MyInterface.Set;
import MyInterface.Map;
import MyInterface.OrderedMap;
import MyInterface.Iterator;

/**
 * TreeMap类的设计
 * @author baby69yy2000
 */
public class TreeMap<K, V> implements OrderedMap<K, V> {
	
	/*====================TreeMap结点内部类Entry====================*/
	private static class Entry<K, V> implements Map.Entry<K, V> {
		// Entry类实例变量
		K key;
		V value;
		Entry<K, V> left, right, parent;
		
		// Entry结点类构造函数
		public Entry(K key, V value, Entry<K, V> parent) {
			this.key = key;
			this.value = value;
			this.left = null;
			this.right = null;
			this.parent = parent;
		}
		
		// 取键
		public K getKey() {
			return key;
		}

		// 取值
		public V getValue() {
			return value;
		}

		// 更新值
		// 返回被更新的值
		public V setValue(V value) {
			V oldValue = this.value;
			this.value = value;
			return oldValue;
		}
		
		public String toString() {
			return key + "=" + value;
		}

	}
	/*===============================================================*/
	
	/*=========================TreeMap类的设计=========================*/
	
	// TreeMap类实例变量
	private Entry<K, V> root;
	private int mapSize;
	private int modCount;
	
	// TreeMap类构造函数
	public TreeMap() {
		root = null;
		mapSize = 0;
		modCount = 0;
	}
	
	// 判断二叉排序树是否为空
	public boolean isEmpty() {
		return mapSize == 0;
	}

	// 返回此映射中的键-值映射关系数
	public int size() {
		return mapSize;
	}
	
	public void clear() {
		 modCount++;
	     mapSize = 0;
	     root = null;
	}
	
	// 私有方法 getEntry()接受一个键,并且返回 Entry 对象,或者在映射中不包含这个键时返回 null
	// 类似二叉排序树的私有方法 findNode()
	private Entry<K, V> getEntry(K key) {
		Entry<K, V> entry = root;
		int orderValue;
		
		while(entry != null) {
			orderValue = ((Comparable<K>)key).compareTo(entry.key);
			if(orderValue == 0)
				return entry;
			else if(orderValue < 0)
				entry = entry.left;
			else
				entry = entry.right;
		}
		return null;
	}
	
	// 返回指定键所映射的值,如果对于该键而言,此映射不包含任何映射关系,则返回 null
	public V get(Object key) {
		Entry<K, V> p = getEntry((K)key);
		if(p == null)
			return null;
		else
			return p.getValue();
	}
	
	// 如果此映射包含指定键的映射关系,则返回 true
	public boolean containsKey(Object key) {
		return getEntry((K)key) != null;
	}
	
	// 将指定值与此映射中的指定键进行关联。如果该映射以前包含此键的映射关系,那么将替换旧值
	public V put(K key, V value) {
		Entry<K, V> entry = root, parent = null, newNode;
		int orderValue = 0;
		
		while(entry != null) {
			parent = entry;
			orderValue = ((Comparable<K>)key).compareTo(entry.key);
			if(orderValue == 0)
				return entry.setValue(value);
			else if(orderValue < 0)
				entry = entry.left;
			else
				entry = entry.right;
		}
		
		newNode = new Entry<K, V>(key, value, parent);
		
		if(parent == null)
			root = newNode;
		else if(orderValue < 0)
			parent.left = newNode;
		else
			parent.right = newNode;
		
		mapSize++;
		modCount++;
		return null;
	}
	
	// 删除结点的私有方法 removeNode
	private void removeNode(Entry<K, V> dNode) {
		if (dNode == null)
	         return;
		
		// dNode: 待删除结点
		// pNode: 待删除结点的父结点
		// rNode: 待删除结点的替换结点
		Entry<K, V> pNode, rNode;
		
		// 待删除结点的父结点找到了
		pNode = dNode.parent;
		
		// ①待删除的结点至少具有一棵空子树
		if(dNode.left == null || dNode.right == null) {
			// 找替换结点
			if(dNode.right == null)
				rNode = dNode.left;
			else
				rNode = dNode.right;
			
			// 判断待删除结点是不是叶结点的情况
			if(rNode != null)
				rNode.parent = pNode;
			
			// 待删除结点是根结点的情况
			if(pNode == null)
				root = rNode;
			// 连接替换结点到待删除结点父结点的正确分枝上
			else if(((Comparable<K>)dNode.key).compareTo(pNode.key) < 0)
				pNode.left = rNode;
			else
				pNode.right = rNode;
		// ②待删除的结点具有两个非空子树
		}else {
			// pOfR是替换结点父结点的引用
			Entry<K,V> pOfR = dNode;
			
			rNode = dNode.right;
			while(rNode.left != null) {
				pOfR = rNode;
				rNode = rNode.left;
			}
			// 先将R的(key和value)复制到D
			dNode.key = rNode.key;
			dNode.value = rNode.value;
			
			// 如果pOfR是待删除的结点,那么将(R的右子树)作为(D的右子结点)连接
			if(pOfR == dNode)
				dNode.right = rNode.right;
			// 否则将(R的右子树)作为(pOfR的左子结点)连接
			else
				pOfR.left = rNode.right;
			
			// 在这两种情况下,我们都必须要更新R的右子树的父结点
			if (rNode.right != null)
				rNode.right.parent = pOfR;
			
			dNode = rNode;
		}
		dNode = null;
	}
	
	// 删除结点
	// 返回删除的结点
	public V remove(Object key) {
		Entry<K,V> dNode = getEntry((K)key);
		if(dNode == null)
			return null;
		V returnedValue = dNode.getValue();
		removeNode(dNode);
		mapSize--;
		modCount++;
		return returnedValue;
	}
	
	// 返回最小的键
	public K firstKey() {
		Entry<K, V> nextNode = root;
		if(nextNode == null)
			return null;
		while(nextNode.left != null)
			nextNode = nextNode.left;
		return nextNode.key;
	}

	// 返回最大的键
	public K lastKey() {
		Entry<K, V> nextNode = root;
		if(nextNode == null)
			return null;
		while(nextNode.right != null)
			nextNode = nextNode.right;
		return nextNode.key;
	}
	
	public String toString() {
		int max = mapSize - 1;
		StringBuffer buf = new StringBuffer();
		Iterator<Map.Entry<K, V>> it = entrySet().iterator();
		
		buf.append("{");
		for(int j = 0; j <= max; j++) {
			Map.Entry<K, V> e = it.next();
			buf.append(e.getKey() + "=" + e.getValue());
			if(j < max)
				buf.append(", ");
		}
		buf.append("}");
		return buf.toString();
	}
	
	// 跌代器
	private class MyIterator<T> implements Iterator<T> {
		private int expectedModCount = modCount;
		private Entry<K,V> lastReturned = null;
		private Entry<K,V> nextNode = null;
		
		// 构造函数初始化nextNode指向二叉排序树最小的元素
		MyIterator() {
			nextNode = root;
			if(nextNode != null)
				while(nextNode.left != null)
					nextNode = nextNode.left;
		}
		
		// 返回Entry对象
		final Entry<K,V> nextEntry() {
			checkIteratorState();
			if(nextNode == null)
				throw new NoSuchElementException(
						"Iteration has no more elements");
			
			lastReturned = nextNode;
			
			Entry<K,V> p;
			// ①右子树非空移到最左结点
			if(nextNode.right != null) {
				nextNode = nextNode.right;
				while(nextNode.left != null)
					nextNode = nextNode.left;
			// ②在右子树为空时,使用父结点引用在树中向上移动,直到查找到一个左子结点.
			// 这个左子结点的父结点就是要访问的下一结点
			}else {
				p = nextNode.parent;
				while(p != null && nextNode == p.right) {
					nextNode = p;
					p = p.parent;
				}
				nextNode = p;
			}
			return lastReturned;
		}
		
		public boolean hasNext() {
			return nextNode != null;
		}

		public void remove() {
			// check for a missing call to next() or previous()
	         if (lastReturned == null)
	            throw new IllegalStateException(
	               "Iterator call to next() " +
	               "required before calling remove()");

	         // make sure our state is good
	         checkIteratorState();

				// if lastReturned has two children, the replacement node
				// during deletion is nextNode. the value in nextNode
				// is copied to lastReturned. nextNode must be
				// lastReturned
				if (lastReturned.left != null && lastReturned.right != null)
					 nextNode = lastReturned;
	         removeNode(lastReturned);

	         // list has been modified
	         modCount++;
	         expectedModCount = modCount;

	         // we did a deletion. indicate this by setting lastReturned
	         // to null and decrementing treeSize
	         lastReturned = null;
	         mapSize--;
		}
		
		public T next() {
			return null;
		}
		
		private void checkIteratorState() {
	         if (expectedModCount != modCount)
	            throw new ConcurrentModificationException(
	               "Inconsistent iterator");
	    }
		
	}
	
	// 键跌代器
	// next()方法返回键
	private class KeyIterator extends MyIterator<K> {
		public K next() {
			return nextEntry().key;
		}
	}
	
	// next()方法返回Entry对象
	private class EntryIterator extends MyIterator<Map.Entry<K, V>> {
		public Map.Entry<K, V> next() {
			return nextEntry();
		}
	}
	
	/*===============================================================*/
	
	/*=========================视图===================================*/
	private Set<K> kSet = null;
	private Set<Map.Entry<K, V>> eSet = null;

	public Set<K> keySet() {
		// 匿名内部类
		if(kSet == null) {
			kSet = new Set<K>() {
				
				public int size() {
					// 引用TreeMap的size()方法
					return TreeMap.this.size();
				}
				
				public boolean isEmpty() {
					return TreeMap.this.isEmpty();
				}
				
				public void clear() {
					TreeMap.this.clear();
				}
				
				public boolean contains(Object item) {
					return containsKey(item);
				}

				public Iterator<K> iterator() {
					return new KeyIterator();
				}

				public boolean remove(Object item) {
					int oldSize = mapSize;
					TreeMap.this.remove(item);
					return mapSize != oldSize;
				}

				public Object[] toArray() {
					Object[] arr = new Object[size()];
					Iterator<K> it = this.iterator();
					for (int i = 0; i < arr.length; i++) {
						arr[i] = it.next();
					}
					return arr;
				}
				
				public String toString() {
					int max = size() - 1;
					StringBuffer buf = new StringBuffer();
					Iterator<K> it = iterator();
					buf.append("[");
					for (int i = 0; i < mapSize; i++) {
						buf.append(it.next());
						if(i < max)
							buf.append(", ");
					}
					buf.append("]");
					return buf.toString();
				}
				
				public boolean add(K item) {
					throw new UnsupportedOperationException();
				}
				
			};
		}
		return kSet;
	}//end keySet~

	public Set<Map.Entry<K, V>> entrySet() {
		if(eSet == null) {
			eSet = new Set<Map.Entry<K, V>>() {
				
				public int size() {
					return TreeMap.this.size();
				}
				
				public boolean isEmpty() {
					return TreeMap.this.isEmpty();
				}

				public void clear() {
					TreeMap.this.clear();
				}

				public boolean contains(Object item) {
					if(!(item instanceof Map.Entry))
						return false;
					
					Entry<K, V> e = (Entry<K, V>) item;
					V value = e.getValue();
					Entry<K, V> p = getEntry(e.getKey());
					return p != null && p.getValue().equals(value);
				}

				public Iterator<MyInterface.Map.Entry<K, V>> iterator() {
					return new EntryIterator();
				}

				public boolean remove(Object item) {
					if(!(item instanceof Map.Entry))
						return false;
					
					Entry<K,V> entry = (Entry<K,V>)item;
					K key = entry.getKey();

					return TreeMap.this.remove(key) != null;
				}

				public Object[] toArray() {
					Object[] arr = new Object[size()];
					Iterator<Map.Entry<K, V>> it = this.iterator();
					for(int i = 0; i < arr.length; i++) {
						arr[i] = it.next();
					}
					return arr;
				}
				
				public String toString() {
					return TreeMap.this.toString();
				}
				
				public boolean add(MyInterface.Map.Entry<K, V> obj) {
					throw new UnsupportedOperationException();
				}
				
			};
		}
		return eSet;
	}//end entrySet~

	/*===============================================================*/

}//end TreeMap~


测试类Test
package Map;
import MyTime24.Time24;
import MyInterface.*;
import MyInterface.Map.Entry;
public class Test {

	public static void main(String[] args) {
		/*
		TreeMap<String, Integer> tm = new TreeMap<String, Integer>();
		tm.put("V", new Integer(20));
		tm.put("A", new Integer(200));
		tm.put("C", new Integer(80));
		tm.put("C", new Integer(80*2));
		tm.put("G", new Integer(60));
		tm.remove("G");
		
		Set<String> s = tm.keySet();
		s.remove("A");
		
		System.out.println(s); // [C, V]
		
		Iterator<String> iter = s.iterator();
		String str = "";
		while(iter.hasNext()) {
			str = iter.next();
			System.out.print(str + "=" + tm.get(str) + " "); // C=160 V=20 
		}
		System.out.println('\n' + "size=" + s.size()); // 2
		System.out.println(tm);
		
		Set<Map.Entry<String,Integer>> eSet = tm.entrySet();
		Object[] obj = eSet.toArray();
		
		for (int i = 0; i < obj.length; i++) {
			System.out.println(obj[i]); // 调用了Entry类的toString()方法
			System.out.println(eSet.contains(obj[i]));
		}
		*/
		
		// Test entrySet()
		TreeMap<String, Time24> tm = new TreeMap<String, Time24>();
		tm.put("Session 1", new Time24(9, 30));
		tm.put("Session 2", new Time24(14, 00));
		tm.put("Lunch", new Time24(12, 0));
		tm.put("Dinner", new Time24(17, 30));
		
		Set<Map.Entry<String, Time24>> e = tm.entrySet();
		
		Iterator<Map.Entry<String, Time24>> it1 = e.iterator();
		Iterator<Map.Entry<String, Time24>> it2 = e.iterator();
		
		setTime(it1);
		System.out.println("======Session starting time======");
		Start(it2);
		
	}

	private static void setTime(Iterator<Map.Entry<String, Time24>> it) {
		while(it.hasNext()) {
			Map.Entry<String, Time24> me = it.next();
			Time24 t = me.getValue();
			t.addTime(30);
			me.setValue(t);
			System.out.println(me.getKey() + " " + me.getValue());
		}
	}

	private static void Start(Iterator<Map.Entry<String, Time24>> it) {
		while(it.hasNext()) {
			Map.Entry<String, Time24> me = it.next();
			String s = me.getKey();
			if(s.indexOf("Session") > -1)
				System.out.println(s + " starting time " + me.getValue());
		}
		
	}

}


辅助测试类Time24
package MyTime24;

import java.text.DecimalFormat;
import java.util.StringTokenizer;

public class Time24 {

	private int hour; // 0 to 23
	private int minute; // 0 to 59

	private void normalizeTime() {
		int extraHours = minute / 60;
		// set minute in range 0 to 59
		minute %= 60;
		// updata hour. set in range 0 to 23
		hour = (hour + extraHours) % 24;
	}

	public Time24() {
		this(0, 0);
	}

	public Time24(int hour, int minute) {
		setTime(hour, minute);
	}

	public void setTime(int hour, int minute) {
		if (hour < 0 || minute < 0)
			throw new IllegalArgumentException(
					"parameters must be positive integers");

		this.hour = hour;
		this.minute = minute;
		this.normalizeTime();
	}

	public void addTime(int m) {
		if (m < 0)
			throw new IllegalArgumentException(
					"argument must be positive integers");

		minute += m;
		this.normalizeTime();
	}

	public Time24 interval(Time24 t) {
		// convert current time and time t to minutes
		int currTime = hour * 60 + minute;
		int tTime = t.hour * 60 + t.minute;

		// if t is earlier than the current time, add 24 hours to
		// indicate that t is time in the next day
		if (tTime < currTime)
			tTime += 24 * 60;

		// return a reference to a new Time24 object
		return new Time24(0, tTime - currTime);
	}

	public static Time24 parseTime(String s) {
		StringTokenizer stok = new StringTokenizer(s, " :");
		String timePeriod = null;
		int hour, minute;

		hour = Integer.parseInt(stok.nextToken());
		minute = Integer.parseInt(stok.nextToken());
		return new Time24(hour, minute);
	}

	public int getHour() {
		return hour;
	}

	public int getMinute() {
		return minute;
	}

	public String toString() {
		DecimalFormat df = new DecimalFormat("00");
		return new String(hour + ":" + df.format(minute));
	}

}
分享到:
评论
1 楼 jamesliulyc 2010-05-09  
老大包名MyInterface.Set
和类名Set有冲突呀

相关推荐

    二叉排序树的删除.zip

    在实际编程中,如C++、Java、Python等语言都有库支持创建和操作二叉排序树,如C++的`&lt;map&gt;`容器就是基于红黑树实现,而Java的`TreeMap`和Python的`sorteddict`等也类似。掌握这些基础概念和操作方法,对于提升编程...

    java编写的二叉树的各种操作(包括二叉排序树和平衡二叉树)

    本压缩包文件“DataStructTest”包含了对二叉排序树和平衡二叉树的实现,旨在帮助学习者深入理解这些概念。 首先,让我们了解一下二叉树的基本概念。二叉树是由节点构成的树形结构,每个节点最多有两个子节点,分别...

    词频统计(未排序)

    自然语言理解 关于词频统计的代码 利用treemap来完成

    中南民族大学平衡二叉树

    为了完成这样的课程设计,学生需要具备扎实的二叉树基础知识,理解二叉搜索树的性质,并能熟练运用递归或迭代的方式来遍历和操作树。同时,他们还需要学习如何编写测试用例,对实现的平衡二叉树进行充分的单元测试,...

    Algorithms_Binary_Sorted_Tree_

    这两个类实现了`NavigableMap`和`NavigableSet`接口,提供有序的键值对和元素操作,底层就是基于红黑树实现的二叉排序树。 以下是一个简单的Java代码示例,展示如何创建和操作二叉排序树: ```java import java....

    TreeMap源码

    2. `java.util.TreeMap.Node` 类:表示红黑树的节点,包含键、值、颜色和子节点等信息。 3. `put()` 方法:插入键值对,包括插入逻辑和红黑树调整。 4. `remove()` 方法:删除键值对,涉及红黑树的重新平衡。 5. `...

    【IT十八掌徐培成】Java基础第12天-03.TreeMap-集合工具类.zip

    `TreeMap`的工作原理基于红黑树数据结构,这是一种自平衡二叉查找树。这种数据结构保证了插入、删除和查找操作的时间复杂度为O(log n),使得`TreeMap`在保持有序性的同时,能够高效地处理大量数据。 1. **创建和...

    Java里多个Map的性能比较(TreeMap、HashMap、ConcurrentSkipListMap)

    - **实现方式**:TreeMap基于红黑树(Red-Black Tree)实现,这是一种自平衡的二叉查找树。 - **时间复杂度**:插入和查找的平均时间复杂度为O(log n),在插入大量数据时,由于需要保持红黑树的平衡,可能会进行...

    2018京东java面试详解

    * 动态查找表二叉排序树(二叉查找树):一种自平衡的二叉树,用于快速查找和插入。 * 平衡二叉树(AVL 树):一种自平衡的二叉树,用于解决二叉查找树退化成链表的问题。 * B-树:一种平衡的多路查找树,在文件...

    Java源码解析TreeMap简介

    TreeMap是Java中的一种常用的排序树,实现了NavigableMap接口。下面是对TreeMap的详细介绍: 1. TreeMap的实现机制 TreeMap是基于Red-Black树的数据结构,红黑树是一种自平衡的二叉查找树,它可以在O(log n)时间...

    PHP-TreeMap.zip

    在IT领域,数据结构是编程基础中的重要组成部分,而红黑树作为一种自平衡二叉查找树,具有很多独特的性质和优势。PHP虽然不是通常用于实现这类复杂数据结构的语言,但通过对"PHP-TreeMap.zip"的分析,我们可以看到...

    java语言程序设计 (Y.Daniel Liang 著 梁勇)奖励章节 2-4树、B输和红黑树

    在Java中,`java.util.TreeMap`和`java.util.TreeSet`类就是基于红黑树实现的。它们提供了有序的存储和高效的查找、插入和删除操作,适用于需要维护元素排序顺序的场景。 综上所述,2-4树、B树和红黑树是数据结构...

    红黑树算法实现

    红黑树是一种自平衡的二叉查找树,它的设计目标是在进行插入、删除等操作时,能够保持树的平衡,从而保证操作的时间复杂度在最坏情况下为O(log n)。这种特性使得红黑树在大数据量的场景下,如Java集合框架中的...

    红黑树学习文档

    红黑树的设计目的是为了在保持二叉查找树基本操作高效的同时,通过自平衡机制来减少最坏情况下的性能下降。这些操作包括插入、删除和搜索等。平衡的策略使得在插入和删除后,树的高度可以保持在O(log n)级别,从而...

    java树形结构

    在Java中,实现树形结构通常有两种主要方式:通过继承自Java集合框架的`TreeSet`或`TreeMap`类,或者自定义节点类来构建树。`TreeSet`和`TreeMap`利用红黑树(Red-Black Tree)实现,提供了自动排序的功能。而自定义...

    红黑树的java实现 (二叉树也有)

    红黑树(Red-Black Tree)是一种自平衡的二叉查找树,它的设计目标是尽可能地减少在插入、删除和查找等操作时的最坏情况下的时间复杂度。这种数据结构在Java中广泛应用于集合框架,如`java.util.TreeMap`和`java....

    Java集合排序及java集合类详解(Collection、List、Map、Set).pdf

    Java集合排序及Java集合类详解 Java集合框架是Java语言中最重要、最常用的部分之一,它能够使开发者更方便地处理数据结构。Java集合框架主要包括Collection、List、Set、Map四个接口,它们分别实现了不同的数据结构...

    Binary-Search-Tree-Over-Array-Algorithm:该项目是执行诸如二进制搜索算法之类的算法的执行程序

    在Java中实现二叉搜索树,通常会定义一个Node类来表示树的节点,包含键、值和左右子节点的引用。例如: ```java class Node { int key; int value; Node left, right; Node(int item) { key = item; value =...

    java _Tree.rar

    在这个讨论中,我们将深入探讨Java中的树数据结构,特别是`TreeSet`和`TreeMap`这两个基于红黑树实现的集合类。 首先,让我们理解什么是树。树由节点(或称为元素)和边组成,每个节点可以有零个、一个或多个子节点...

Global site tag (gtag.js) - Google Analytics