课程:《程序设计与数据结构》
班级: 1723
姓名: 余坤澎
学号:20172313
实验教师:王志强
实验日期:2018年9月26日
必修/选修: 必修html
public LinkedBinaryTree<T> getRight() { if(root == null) throw new EmptyCollectionException("Get right operation failed. The tree is empty."); LinkedBinaryTree<T> result = new LinkedBinaryTree<>(); result.root = root.getRight(); return result; }
public boolean contains(T targetElement) { if(findNode(targetElement,root) != null) return true; else return false; }
public String toString() { UnorderedListADT<BinaryTreeNode> nodes = new ArrayUnorderedList<BinaryTreeNode>(); UnorderedListADT<Integer> levelList = new ArrayUnorderedList<Integer>(); BinaryTreeNode current; String result = ""; int printDepth = this.getHeight(); int possibleNodes = (int)Math.pow(2, printDepth + 1); int countNodes = 0; nodes.addToRear(root); Integer currentLevel = 0; Integer previousLevel = -1; levelList.addToRear(currentLevel); while (countNodes < possibleNodes) { countNodes = countNodes + 1; current = nodes.removeFirst(); currentLevel = levelList.removeFirst(); if (currentLevel > previousLevel) { result = result + "\n\n"; previousLevel = currentLevel; for (int j = 0; j < ((Math.pow(2, (printDepth - currentLevel))) - 1); j++) result = result + " "; } else { for (int i = 0; i < ((Math.pow(2, (printDepth - currentLevel + 1)) - 1)) ; i++) { result = result + " "; } } if (current != null) { result = result + (current.getElement()).toString(); nodes.addToRear(current.getLeft()); levelList.addToRear(currentLevel + 1); nodes.addToRear(current.getRight()); levelList.addToRear(currentLevel + 1); } else { nodes.addToRear(null); levelList.addToRear(currentLevel + 1); nodes.addToRear(null); levelList.addToRear(currentLevel + 1); result = result + " "; } } return result; }
public Iterator<T> iteratorPreOrder() { ArrayUnorderedList<T> tempList = new ArrayUnorderedList<T>(); preOrder(root, tempList); return new TreeIterator(tempList.iterator()); } protected void preOrder(BinaryTreeNode<T> node, ArrayUnorderedList<T> tempList) { if (node != null) { tempList.addToRear(node.getElement()); preOrder(node.getLeft(), tempList); preOrder(node.getRight(), tempList); } }
public void buildTree(T[] inorder, T[] postorder) { BinaryTreeNode temp=makeTree(inorder, 0, inorder.length, postorder, 0, postorder.length); root = temp; } public BinaryTreeNode<T> makeTree(T[] inorder,int startIn,int lenIn,T[] postorder,int startPos,int lenPos){ if(lenIn<1){ return null; } BinaryTreeNode root; T rootelement=postorder[startPos];//postorder中的第一个元素就是当前处理的数据段的根节点 root=new BinaryTreeNode(rootelement); int temp; boolean isFound=false; for(temp=0;temp<lenIn;temp++){ if(inorder[startIn+temp]==rootelement){ isFound=true;//此时找到结点 break; } } if(!isFound)//若是不存在相等的状况就跳出该函数 return root; root.setLeft(makeTree(inorder, startIn, temp, postorder, startPos+1, temp)); root.setRight(makeTree(inorder, startIn+temp+1, lenIn-temp-1, postorder, startPos+temp+1, lenPos-temp-1)); return root; }
public BinaryTreeNode buildTree(String str) { ArrayList<String> operList = new ArrayList<>(); ArrayList<LinkedBinaryTree> numList = new ArrayList<>(); StringTokenizer st = new StringTokenizer(str); String token; while (st.hasMoreTokens()) { token = st.nextToken(); if (token.equals("(")) { String str1 = ""; while (true) { token = st.nextToken(); if (!token.equals(")")) str1 += token + " "; else break; } LinkedBinaryTree temp = new LinkedBinaryTree(); temp.root = buildTree(str1); numList.add(temp); token = st.nextToken(); } if (token.equals("+") || token.equals("-")) { operList.add(token); } else if (token.equals("*") || token.equals("/")) { LinkedBinaryTree left = numList.remove(numList.size() - 1); String A = token; token = st.nextToken(); if (!token.equals("(")) { LinkedBinaryTree right = new LinkedBinaryTree(token); LinkedBinaryTree node = new LinkedBinaryTree(A, left, right); numList.add(node); } else { String str1 = ""; while (true) { token = st.nextToken(); if (!token.equals(")")) str1 += token + " "; else break; } LinkedBinaryTree temp2 = new LinkedBinaryTree(); temp2.root = buildTree(str1); LinkedBinaryTree node1 = new LinkedBinaryTree(A, left, temp2); numList.add(node1); } } else numList.add(new LinkedBinaryTree(token)); } while (operList.size() > 0) { LinkedBinaryTree left = numList.remove(0); LinkedBinaryTree right = numList.remove(0); String oper = operList.remove(0); LinkedBinaryTree node2 = new LinkedBinaryTree(oper, left, right); numList.add(0, node2); } node = (numList.get(0)).root; return node; }
public T removeMax() throws EmptyCollectionException { T result = null; if (isEmpty()) throw new EmptyCollectionException("LinkedBinarySearchTree"); else { if (root.right == null) { result = root.element; root = root.left; } else { BinaryTreeNode<T> parent = root; BinaryTreeNode<T> current = root.right; while (current.right != null) { parent = current; current = current.right; } result = current.element; parent.right = current.left; } modCount--; } return result; } public T findMin() throws EmptyCollectionException { if(isEmpty()) System.out.println("BinarySearchTree is empty!"); return findMin(root).getElement(); } private BinaryTreeNode<T> findMin(BinaryTreeNode<T> p) { if (p==null)//结束条件 return null; else if (p.left==null)//若是没有左结点,那么t就是最小的 return p; return findMin(p.left); } public T findMax() throws EmptyCollectionException { if(isEmpty()) System.out.println("BinarySearchTree is empty!"); return findMax(root).getElement(); } private BinaryTreeNode<T> findMax(BinaryTreeNode<T> p){ if (p==null)//结束条件 return null; else if (p.right==null) return p; return findMax(p.right); }
public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, Cloneable, java.io.Serializable
TreeMap 是一个有序的key-value集合,它是经过红黑树实现的。
TreeMap 继承于AbstractMap,因此它是一个Map,即一个key-value集合。
TreeMap 实现了NavigableMap接口,意味着它支持一系列的导航方法。好比返回有序的key集合。
TreeMap 实现了Cloneable接口,意味着它能被克隆。
TreeMap 实现了java.io.Serializable接口,意味着它支持序列化。java
//使用默认构造函数构造TreeMap时,使用java的默认的比较器比较Key的大小,从而对TreeMap进行排序。 public TreeMap() { comparator = null; } //带比较器的构造函数 public TreeMap(Comparator<? super K> comparator) { this.comparator = comparator; } //带Map的构造函数,Map会成为TreeMap的子集 ublic TreeMap(Map<? extends K, ? extends V> m) { comparator = null; putAll(m); } //该构造函数会调用putAll()将m中的全部元素添加到TreeMap中。从中,咱们能够看出putAll()就是将m中的key-value逐个的添加到TreeMap中。putAll()源码以下: public void putAll(Map<? extends K, ? extends V> m) { for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) put(e.getKey(), e.getValue()); } //带SortedMap的构造函数,SortedMap会成为TreeMap的子集,该构造函数不一样于上一个构造函数,在上一个构造函数中传入的参数是Map,Map不是有序的,因此要逐个添加。而该构造函数的参数是SortedMap是一个有序的Map,咱们经过buildFromSorted()来建立对应的Map。 public TreeMap(SortedMap<K, ? extends V> m) { comparator = m.comparator(); try { buildFromSorted(m.size(), m.entrySet().iterator(), null, null); } catch (java.io.IOException cannotHappen) { } catch (ClassNotFoundException cannotHappen) { } }
public V put(K key, V value) {//插入或设置元素,返回原始value值(若是插入返回null) Entry<K,V> t = root; if (t == null) {//根元素为空时直接创建根元素 root = new Entry<K,V>(key, value, null); size = 1; modCount++; return null; } int cmp; Entry<K,V> parent; // split comparator and comparable paths Comparator<? super K> cpr = comparator; if (cpr != null) {//存在比较器 do {//循环查找父元素 parent = t;//设置父元素 cmp = cpr.compare(key, t.key); if (cmp < 0) t = t.left;//继续查找左边元素 else if (cmp > 0) t = t.right;//继续查找右边元素 else return t.setValue(value);//相等直接进行value设置 } while (t != null); } else {//不存在比较器,按compareTo方法查找 if (key == null) throw new NullPointerException(); Comparable<? super K> k = (Comparable<? super K>) key; do { parent = t; cmp = k.compareTo(t.key); if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else return t.setValue(value); } while (t != null); } Entry<K,V> e = new Entry<K,V>(key, value, parent); if (cmp < 0) parent.left = e; else parent.right = e; fixAfterInsertion(e); size++; modCount++; return null; } private void fixAfterInsertion(Entry<K,V> x) {//插入数据后的树形变化处理 x.color = RED;//插入元素默认颜色为红色 while (x != null && x != root && x.parent.color == RED) {//当父节点的颜色为红色时,须要进行变化 if (parentOf(x) == leftOf(parentOf(parentOf(x)))) {//若是父元素为其父的左节点 Entry<K,V> y = rightOf(parentOf(parentOf(x)));//取右节点(叔节点) if (colorOf(y) == RED) {//颜色为红 setColor(parentOf(x), BLACK);//父节点设置为黑色 setColor(y, BLACK);//右节点设置为黑色 setColor(parentOf(parentOf(x)), RED);//父元素的父元素设置为红色 x = parentOf(parentOf(x));//x设置为父元素的父元素,继续进行断定 } else {//叔节点不可能为黑色,故下面为无叔节点状况,必然须要进行旋转 if (x == rightOf(parentOf(x))) {//若是当前元素为其父的右节点 x = parentOf(x);//x设置为父元素,继续进行断定 rotateLeft(x);//进行左旋操做 } setColor(parentOf(x), BLACK);//父节点设置为黑色 setColor(parentOf(parentOf(x)), RED);//父元素的父元素设置为红色 rotateRight(parentOf(parentOf(x)));//进行右旋操做 } } else {//父元素为其父的右节点 Entry<K,V> y = leftOf(parentOf(parentOf(x)));//取左节点(叔节点) if (colorOf(y) == RED) {//颜色为红 setColor(parentOf(x), BLACK); setColor(y, BLACK); setColor(parentOf(parentOf(x)), RED); x = parentOf(parentOf(x));//x设置为父元素的父元素,继续进行断定 } else {//叔节点不可能为黑色,故下面为无叔节点状况,必然须要进行旋转 if (x == leftOf(parentOf(x))) {//若是当前元素为其父的左节点 x = parentOf(x);//x设置为父元素,继续进行断定 rotateRight(x);//进行右旋操做 } setColor(parentOf(x), BLACK); setColor(parentOf(parentOf(x)), RED); rotateLeft(parentOf(parentOf(x)));//进行左旋操做 } } } root.color = BLACK;//根节点设置为黑色 }
final Entry<K,V> getEntry(Object key) {//根据key值查找元素方法;final方法不容许被子类重写 // Offload comparator-based version for sake of performance if (comparator != null)//存在比较器,按比较器进行比较查找 return getEntryUsingComparator(key); if (key == null)//key值为null抛空指针异常 throw new NullPointerException(); Comparable<? super K> k = (Comparable<? super K>) key; Entry<K,V> p = root; while (p != null) {//从root开始循环查找,一直到叶子节点 int cmp = k.compareTo(p.key);//采用key的compareTo方法进行比较 if (cmp < 0)//小于继续查找左边 p = p.left; else if (cmp > 0)//大于继续查找右边 p = p.right; else return p;//等于返回当前元素 } return null; }
blic V remove(Object key) { Entry<K,V> p = getEntry(key);//先找到须要删除的元素 if (p == null) return null; V oldValue = p.value; deleteEntry(p); return oldValue; } private void deleteEntry(Entry<K,V> p) { modCount++; size--; // If strictly internal, copy successor's element to p and then make p // point to successor. if (p.left != null && p.right != null) {//若是有两个孩子 Entry<K,V> s = successor (p);//查找下一元素 p.key = s.key; p.value = s.value;//p的数据替换为该元素数据 p = s;//将p指向该元素,做为原始元素(被删除元素) } // p has 2 children // Start fixup at replacement node, if it exists. Entry<K,V> replacement = (p.left != null ? p.left : p.right);//将替换元素设置为左元素(没有则为右元素) if (replacement != null) {//替换元素不为空 // Link replacement to parent replacement.parent = p.parent;//将替换元素与原始元素的父亲链接起来 if (p.parent == null) root = replacement; else if (p == p.parent.left) p.parent.left = replacement; else p.parent.right = replacement; // Null out links so they are OK to use by fixAfterDeletion. p.left = p.right = p.parent = null;//原始元素链接清空 // Fix replacement if (p.color == BLACK)//删除元素为黑色,须要进行删除后树形变化操做 fixAfterDeletion(replacement); } else if (p.parent == null) { // return if we are the only node. root = null;//根节点的删除 } else { // No children. Use self as phantom replacement and unlink. if (p.color == BLACK) fixAfterDeletion(p); //没有孩子时,使用本身做为替换节点,先树形变化再进行链接清空操做 if (p.parent != null) { if (p == p.parent.left) p.parent.left = null; else if (p == p.parent.right) p.parent.right = null; p.parent = null; } } } private void fixAfterDeletion(Entry<K,V> x) {//删除数据后的树形变化处理 while (x != root && colorOf(x) == BLACK) {//当前节点为黑(替换元素不可能为黑,只有删除自身的状况) if (x == leftOf(parentOf(x))) {//左节点 Entry<K,V> sib = rightOf(parentOf(x));//取父亲的右节点(兄节点) if (colorOf(sib) == RED) {//颜色为红 setColor(sib, BLACK); setColor(parentOf(x), RED);//着色 rotateLeft(parentOf(x));//按父左旋 sib = rightOf(parentOf(x));//指向左旋后的父亲的右节点(为黑) } //颜色为黑 if (colorOf(leftOf(sib)) == BLACK && colorOf(rightOf(sib)) == BLACK) {//两个孩子均为黑(实际只可能为无孩子状况) setColor(sib, RED);//着色 x = parentOf(x);//x指向父节点继续判断 } else { if (colorOf(rightOf(sib)) == BLACK) {//右节点为黑(实际只可能为无右孩子) setColor(leftOf(sib), BLACK); setColor(sib, RED);//着色 rotateRight(sib);//按兄右旋 sib = rightOf(parentOf(x));//指向右旋后的父亲的右节点 } setColor(sib, colorOf(parentOf(x))); setColor(parentOf(x), BLACK); setColor(rightOf(sib), BLACK);//着色 rotateLeft(parentOf(x));//按父左旋 x = root;//结束循环 } } else { // symmetric//右节点 Entry<K,V> sib = leftOf(parentOf(x));//取父亲的左节点(兄节点) if (colorOf(sib) == RED) {//颜色为红 setColor(sib, BLACK); setColor(parentOf(x), RED);//着色 rotateRight(parentOf(x));//按父右旋 sib = leftOf(parentOf(x));//指向右旋后的父亲的左节点(为黑或空) } //颜色为黑 if (colorOf(rightOf(sib)) == BLACK && colorOf(leftOf(sib)) == BLACK) {//两个孩子均为黑 setColor(sib, RED);//着色 x = parentOf(x);//x指向父节点继续判断 } else { if (colorOf(leftOf(sib)) == BLACK) {//左节点为黑 setColor(rightOf(sib), BLACK); setColor(sib, RED);//着色 rotateLeft(sib);//按兄左旋 sib = leftOf(parentOf(x));//指向左旋后的父亲的左节点 } setColor(sib, colorOf(parentOf(x))); setColor(parentOf(x), BLACK); setColor(leftOf(sib), BLACK);//着色 rotateRight(parentOf(x));//按父右旋 x = root;//结束循环 } } } setColor(x, BLACK);//将x置为黑色 }
public V put(K key, V value) { //若是table数组为空数组{},进行数组填充(为table分配实际内存空间),入参为threshold,此时threshold为initialCapacity 默认是1<<4(=16) if (table == EMPTY_TABLE) { inflateTable(threshold);//分配数组空间 } //若是key为null,存储位置为table[0]或table[0]的冲突链上 if (key == null) return putForNullKey(value); int hash = hash(key);//对key的hashcode进一步计算,确保散列均匀 int i = indexFor(hash, table.length);//获取在table中的实际位置 for (Entry<K,V> e = table[i]; e != null; e = e.next) { //若是该对应数据已存在,执行覆盖操做。用新value替换旧value,并返回旧value Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this);//调用value的回调函数,其实这个函数也为空实现 return oldValue; } } modCount++;//保证并发访问时,若HashMap内部结构发生变化,快速响应失败 addEntry(hash, key, value, i);//新增一个entry return null; }
private void inflateTable(int toSize) { int capacity = roundUpToPowerOf2(toSize);//capacity必定是2的次幂 threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);//此处为threshold赋值,取capacity*loadFactor和MAXIMUM_CAPACITY+1的最小值,capaticy必定不会超过MAXIMUM_CAPACITY,除非loadFactor大于1 table = new Entry[capacity];//分配空间 initHashSeedAsNeeded(capacity);//选择合适的Hash因子 }
void addEntry(int hash, K key, V value, int bucketIndex) { if ((size >= threshold) && (null != table[bucketIndex])) { resize(2 * table.length);//当size超过临界阈值threshold,而且即将发生哈希冲突时进行扩容,新容量为旧容量的2倍 hash = (null != key) ? hash(key) : 0; bucketIndex = indexFor(hash, table.length);//扩容后从新计算插入的位置下标 } //把元素放入HashMap的桶的对应位置 createEntry(hash, key, value, bucketIndex); } //建立元素 void createEntry(int hash, K key, V value, int bucketIndex) { Entry<K,V> e = table[bucketIndex]; //获取待插入位置元素 table[bucketIndex] = new Entry<>(hash, key, value, e);//这里执行连接操做,使得新插入的元素指向原有元素。 //这保证了新插入的元素老是在链表的头 size++;//元素个数+1 }
此次实验的难度分布的比较不均匀,大致上来讲就是简单的很简单,难的很是难,在一些小地方也浪费了不少时间,致使没有在预想的时间内完成实验,但愿本身能在之后的学习生活中继续努力,不断进步!node