getRight
方法、contains
方法、toString
方法、preorder
方法、postorder
方法,此五個方法。getRight
方法public LinkedBinaryTree1<T> getRight() { LinkedBinaryTree1 node = new LinkedBinaryTree1(); node.root = root.getRight(); return node; }
這個基本上是以前好久就實現的一個簡單的方法,先進行一個樹的初始化,能夠獲得一個新樹,而後經過下面一行的代碼獲得新的根,使咱們獲得合適的右子樹。html
contains
方法@Override public boolean contains(T targetElement) { if (find(targetElement) == targetElement) { return true; } else { return false; } } @Override public T find(T targetElement) throws ElementNotFoundException { BinaryTreeNode<T> current = findNode(targetElement, root); if (current == null) throw new ElementNotFoundException("LinkedBinaryTree"); return (current.getElement()); }
這個方法其實自己沒有什麼東西,可是裏面須要用到
find
方法,首先用find
方法查找這個結點,假如找到了這個結點就返回true,假如沒有找到就返回false。java
toString
方法public String toString() { UnorderedListADT<BinaryTreeNode<T>> nodes = new week7.jiumingdaima.ArrayUnorderedList<BinaryTreeNode<T>>(); UnorderedListADT<Integer> levelList = new week7.jiumingdaima.ArrayUnorderedList<Integer>(); BinaryTreeNode<T> 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; }
這個代碼直接使用的書上
ExpressionTree
類的代碼node
preorder
方法public Iterator<T> iteratorPreOrder() { ArrayUnorderedList<T> tempList = new ArrayUnorderedList<T>(); preOrder(root, tempList); return new TreeIterator(tempList.iterator()); } public ArrayUnorderedList preorder() { ArrayUnorderedList<T> tempList = new ArrayUnorderedList<T>(); preOrder(root, tempList); return tempList; } protected void preOrder(BinaryTreeNode<T> node, ArrayUnorderedList<T> tempList) { if (node != null) { // System.out.print(node.getElement()+" "); tempList.addToRear(node.getElement()); preOrder(node.getLeft(), tempList); preOrder(node.getRight(), tempList); } }
這個方法要用到的迭代器方法和自己都是已經給出了的,我加了一段方便方法直接使用express
postorder
方法public ArrayUnorderedList postorder() { ArrayUnorderedList<T> tempList = new ArrayUnorderedList<T>(); postOrder(root, tempList); return tempList; }
和前序遍歷同樣都是現成的方法,只是加了一段數組
//根據前序和中序序列,創建二叉樹 public int findroot(String[] S, String s, int begin, int end) { for (int i = begin; i <= end; i++) { if (S[i] == s) { return i; } } return -1; } public BinaryTreeNode getAtree(String[] preSort, int prestart, int preend, String[] inSort, int instart, int inend) { if (prestart > preend || instart > inend) { return null; } if (preSort.length != inSort.length) { try { throw new Exception("不知足條件的非法輸入!"); } catch (Exception e) { e.printStackTrace(); } } BinaryTreeNode treeroot; String rootData = preSort[prestart]; treeroot = new BinaryTreeNode(rootData); int rwhere = findroot(inSort, rootData, instart, inend);//找根節點的位置 treeroot.left = getAtree(preSort, prestart + 1, prestart + rwhere - instart, inSort, instart, rwhere - 1);//左子樹 treeroot.right = getAtree(preSort, prestart + rwhere - instart + 1, preend, inSort, rwhere + 1, inend);//右子樹 return treeroot; } public void getAtree(String[] preOrder, String[] inOrder) { this.root = getAtree(preOrder, 0, preOrder.length - 1, inOrder, 0, inOrder.length - 1); }
getAtree
方法,結合前序和中序序列,找到根結點和左右子樹,而後對左右子樹分別遞歸使用加getAtree
方法,逐步往下創建樹。已知先序遍歷和中序遍歷獲得二叉樹有三個步驟:數據結構
找到根結點。由於先序遍歷按照先訪問根結點再訪問左右孩子的順序進行的,因此先序遍歷的第一個結點就是二叉樹的根。框架
區分左右子樹。在肯定了根結點以後,在中序遍歷結果中,根結點以前的就是左子樹,根結點以後的就是右子樹。若是跟結點前邊或後邊爲空,那麼該方向子樹爲空;若是根節點前邊和後邊都爲空,那麼根節點已經爲葉子節點。ide
分別對左右子樹再重複第1、二步直至徹底構造出該樹。函數
input.txt
每一個選項改一下就行了,我改了一下二叉樹的形狀,結果下面那堆數字就要所有改一下了5 9 10 7 11 12 8 13 14 3 5 6 4 7 8 2 3 4 0 1 2
public int evaluate(String expression) throws EmptyCollectionException { ExpressionTree operand1, operand2; char operator; String tempToken; Scanner parser = new Scanner(expression); while (parser.hasNext()) { tempToken = parser.next(); operator = tempToken.charAt(0); if ((operator == '+') || (operator == '-') || (operator == '*') || (operator == '/')) { operand1 = getOperand(treeStack); operand2 = getOperand(treeStack); treeStack.push(new ExpressionTree(new ExpressionTreeOp(1, operator, 0), operand2, operand1)); } else { treeStack.push(new ExpressionTree(new ExpressionTreeOp(2, ' ', Integer.parseInt(tempToken)), null, null)); } } return (treeStack.peek()).evaluateTree(); }
public void posorder() { System.out.println("後綴表達式爲: "); posOrder(root); System.out.println(""); } public void posOrder(BinaryNode node) { if (node != null) { posOrder(node.getLeft()); posOrder(node.getRight()); System.out.print(node.getData() + " "); } }
removeMax
方法public T removeMax() throws EmptyCollectionException { // To be completed as a Programming Project 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; }
findMin
方法public T findMin() throws EmptyCollectionException { // To be completed as a Programming Project T result = null; if (isEmpty()) throw new EmptyCollectionException("LinkedBinarySearchTree"); else { if (root.left == null) { result = root.element; } else { BinaryTreeNode<T> parent = root; BinaryTreeNode<T> current = root.left; while (current.left != null) { parent = current; current = current.left; } result = current.element; } } return result; }
- HashMap能夠說是Java中最經常使用的集合類框架之一,是Java語言中很是典型的數據結構,咱們總會在不經意間用到它,很大程度上方便了咱們平常開發。 - HashMap 是基於哈希表的 Map 接口的實現。此實現提供全部可選的映射操做,並容許使用 null 值和 null 鍵。(除了非同步和容許使用 null 以外,HashMap 類與 Hashtable 大體相同。)此類不保證映射的順序,特別是它不保證該順序恆久不變。
- HashMap 的實例有兩個參數影響其性能:初始容量 和加載因子。容量 是哈希表中桶的數量,初始容量只是哈希表在建立時的容量。加載因子 是哈希表在其容量自動增長以前能夠達到多滿的一種尺度。當哈希表中的條目數超出了加載因子與當前容量的乘積時,則要對該哈希表進行 rehash 操做(即重建內部數據結構),從而哈希表將具備大約兩倍的桶數。
// 默認構造函數。 public HashMap() { // 設置「加載因子」 this.loadFactor = DEFAULT_LOAD_FACTOR; // 設置「HashMap閾值」,當HashMap中存儲數據的數量達到threshold時,就須要將HashMap的容量加倍。 threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR); // 建立Entry數組,用來保存數據 table = new Entry[DEFAULT_INITIAL_CAPACITY]; init(); } // 指定「容量大小」和「加載因子」的構造函數 public HashMap(int initialCapacity, float loadFactor) { if (initialCapacity < 0) throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity); // HashMap的最大容量只能是MAXIMUM_CAPACITY if (initialCapacity > MAXIMUM_CAPACITY) initialCapacity = MAXIMUM_CAPACITY; if (loadFactor <= 0 || Float.isNaN(loadFactor)) throw new IllegalArgumentException("Illegal load factor: " + loadFactor); // Find a power of 2 >= initialCapacity int capacity = 1; while (capacity < initialCapacity) capacity <<= 1; // 設置「加載因子」 this.loadFactor = loadFactor; // 設置「HashMap閾值」,當HashMap中存儲數據的數量達到threshold時,就須要將HashMap的容量加倍。 threshold = (int)(capacity * loadFactor); // 建立Entry數組,用來保存數據 table = new Entry[capacity]; init(); } // 指定「容量大小」的構造函數 public HashMap(int initialCapacity) { this(initialCapacity, DEFAULT_LOAD_FACTOR); } // 包含「子Map」的構造函數 public HashMap(Map<? extends K, ? extends V> m) { this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1, DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR); // 將m中的所有元素逐個添加到HashMap中 putAllForCreate(m); }
public boolean containsKey(Object key) { return getEntry(key) != null; }
containsKey() 首先經過getEntry(key)獲取key對應的Entry,而後判斷該Entry是否爲null。
getEntry()的源碼以下:源碼分析
final Entry<K,V> getEntry(Object key) { // 獲取哈希值 // HashMap將「key爲null」的元素存儲在table[0]位置,「key不爲null」的則調用hash()計算哈希值 int hash = (key == null) ? 0 : hash(key.hashCode()); // 在「該hash值對應的鏈表」上查找「鍵值等於key」的元素 for (Entry<K,V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; } return null; }
getEntry() 的做用就是返回「鍵爲key」的鍵值對,它的實現源碼中已經進行了說明。
這裏須要強調的是:HashMap將「key爲null」的元素都放在table的位置0處,即table[0]中;「key不爲null」的放在table的其他位置!
public V put(K key, V value) { // 若「key爲null」,則將該鍵值對添加到table[0]中。 if (key == null) return putForNullKey(value); // 若「key不爲null」,則計算該key的哈希值,而後將其添加到該哈希值對應的鏈表中。 int hash = hash(key.hashCode()); int i = indexFor(hash, table.length); for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; // 若「該key」對應的鍵值對已經存在,則用新的value取代舊的value。而後退出! if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } // 若「該key」對應的鍵值對不存在,則將「key-value」添加到table中 modCount++; addEntry(hash, key, value, i); return null; }
說到addEntry(),就不得不說另外一個函數createEntry()。
addEntry()通常用在 新增Entry可能致使「HashMap的實際容量」超過「閾值」的狀況下。例如,咱們新建一個HashMap,而後不斷經過put()向HashMap中添加元素;put()是經過addEntry()新增Entry的。在這種狀況下,咱們不知道什麼時候「HashMap的實際容量」會超過「閾值」;所以,須要調用addEntry()
createEntry() 通常用在 新增Entry不會致使「HashMap的實際容量」超過「閾值」的狀況下。例如,咱們調用HashMap「帶有Map」的構造函數,它繪將Map的所有元素添加到HashMap中;但在添加以前,咱們已經計算好「HashMap的容量和閾值」。也就是,能夠肯定「即便將Map中的所有元素添加到HashMap中,都不會超過HashMap的閾值」。此時,調用createEntry()便可。
public V get(Object key) { if (key == null) return getForNullKey(); // 獲取key的hash值 int hash = hash(key.hashCode()); // 在「該hash值對應的鏈表」上查找「鍵值等於key」的元素 for (Entry<K,V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) return e.value; } return null; }
public V remove(Object key) { Entry<K,V> e = removeEntryForKey(key); return (e == null ? null : e.value); } // 刪除「鍵爲key」的元素 final Entry<K,V> removeEntryForKey(Object key) { // 獲取哈希值。若key爲null,則哈希值爲0;不然調用hash()進行計算 int hash = (key == null) ? 0 : hash(key.hashCode()); int i = indexFor(hash, table.length); Entry<K,V> prev = table[i]; Entry<K,V> e = prev; // 刪除鏈表中「鍵爲key」的元素 // 本質是「刪除單向鏈表中的節點」 while (e != null) { Entry<K,V> next = e.next; Object k; if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) { modCount++; size--; if (prev == e) table[i] = next; else prev.next = next; e.recordRemoval(this); return e; } prev = e; e = next; } return e; }
由於這一大堆英語並非很直觀,我在他們前面進行了編號。而後在我本身試着寫的時候發現0 1 2必須在最下面一排,1是左孩子,2是右孩子,再上面一排數字必須是先安排右孩子和他的孩子們,就是說必須是
2 5 6 1 3 4
而不是
1 3 4 2 5 6
除非沒有右孩子