課程:《程序設計與數據結構》
班級: 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