/** * Grant D Hawkes * This file implements and AVL Tree including a modified version of lazy deletion. * Much of the code in this file is from Mark Alan Weiss' Data Structures and Algorithms * book and it's accompaning website. */ import java.util.LinkedList; import java.util.StringTokenizer; public class AVLTree { private class AVLNode { public int freq; public int height; public String name; public AVLNode right; public AVLNode left; public LinkedList nameList; public AVLNode(String xname, String xwholeName, AVLNode xleft, AVLNode xright) { name = xname; left = xleft; right = xright; height = -1;// this line is not needed, just an initialization nameList = new LinkedList(); nameList.add(xwholeName); freq = 1;// freq is one because 1 name was just added } } private AVLNode root; public AVLTree() { root = null; } /** * public method to print the tree and then the names of the children in the * tree in alphabetical order (by first name). */ public void printTeams() { printTree(root, ""); System.out.println(); printNames(root); } /** * Given the root of a tree and an initial buffer (indent) String this * method will print a AVL tree sideways to the console. Imagine a handdrawn * tree and flip it 90 degrees counter-clockwise. This is what this method * will print. Format is the name of the node then a colon then the * frequency of people with that first name, example: Grant:2 */ private void printTree(AVLNode curr, String buffer) { if (curr != null) { printTree(curr.right, buffer + " "); System.out.println(buffer + curr.name + ":" + curr.freq); printTree(curr.left, buffer + " "); } } /** * Prints the names of the children in the tree (1 per line) sorted by first * name. */ private void printNames(AVLNode curr) { if (curr != null) { printNames(curr.left); for (int i = 0; i < curr.freq; i++) System.out.println(curr.nameList.get(i)); printNames(curr.right); } } /** Does lazy deletion on the String wholeName in the AVL tree. */ public void remove(String wholeName) { StringTokenizer st = new StringTokenizer(wholeName); String name = st.nextToken();// pulls the first token (first name) // out of the wholeName AVLNode temp = find(name, root); if (temp != null) { if (temp.nameList.contains(wholeName)) { temp.nameList.remove(wholeName); temp.freq--; } } } /** Makes the tree empty by setting the root to null */ public void makeEmpty() { root = null; } /** * Finds the String wholeName in the tree and returns it. Returns null if * not found. */ public String find(String wholeName) { StringTokenizer st = new StringTokenizer(wholeName); String name = st.nextToken(); /* * pulls the first token (first name) out of the wholeName */ /* * temp is the node with the same FIRST name as the person we are * searching for */ AVLNode temp = find(name, root); if (temp != null) { if (temp.nameList.contains(wholeName)) return wholeName; else return null; } return null; } /** * Internal method to find an item in a subtree. * * @param x * is item to search for. * @param t * the node that roots the tree. * @return node containing the matched item. Code from Mark Alan Weiss' data * structures and alogorithms book. */ private AVLNode find(String name, AVLNode curr) { while (curr != null) if (name.compareTo(curr.name) < 0) curr = curr.left; else if (name.compareTo(curr.name) > 0) curr = curr.right; else return curr; return null; } public AVLNode insert(String wholeName) { StringTokenizer st = new StringTokenizer(wholeName); String name = st.nextToken(); root = insert(name, wholeName, root); return root; } /** * Internal method to insert into a subtree. * * @param x * the item to insert. * @param t * the node that roots the tree. * @return the new root. Code from Mark Alan Weiss' data structures and * alogorithms book. */ private AVLNode insert(String name, String wholeName, AVLNode curr) { if (curr == null)// the node is null curr = new AVLNode(name, wholeName, null, null); else if (name.compareTo(curr.name) < 0) { curr.left = insert(name, wholeName, curr.left); if (height(curr.left) - height(curr.right) == 2) // there is an imbalance // see what kind of imbalance it is if (name.compareTo(curr.left.name) < 0) curr = rotateWithLeftChild(curr); else curr = doubleWithLeftChild(curr); } else if (name.compareTo(curr.name) > 0) { curr.right = insert(name, wholeName, curr.right); if (height(curr.right) - height(curr.left) == 2) if (name.compareTo(curr.right.name) > 0) curr = rotateWithRightChild(curr); else curr = doubleWithRightChild(curr); } else /* * it is a duplicate, increase freq and insert name into linked list */ { curr.nameList.add(wholeName); curr.freq++; } // finally update the height as we go curr.height = Math.max(height(curr.left), height(curr.right)) + 1; return curr; } private int height(AVLNode curr) { return curr == null ? -1 : curr.height; } /** * Code from Mark Alan Weiss' data structures and alogorithms book. */ /** * Rotate binary tree node with left child. For AVL trees, this is a single * rotation for case 1. Update heights, then return new root. Code from Mark * Alan Weiss' data structures and alogorithms book. */ private AVLNode rotateWithLeftChild(AVLNode k2) { AVLNode k1 = k2.left; k2.left = k1.right; k1.right = k2; k2.height = Math.max(height(k2.left), height(k2.right)) + 1; k1.height = Math.max(height(k1.left), k2.height) + 1; return k1; } /** * Rotate binary tree node with right child. For AVL trees, this is a single * rotation for case 4. Update heights, then return new root. Code from Mark * Alan Weiss' data structures and alogorithms book. */ private AVLNode rotateWithRightChild(AVLNode k1) { AVLNode k2 = k1.right; k1.right = k2.left; k2.left = k1; k1.height = Math.max(height(k1.left), height(k1.right)) + 1; k2.height = Math.max(height(k2.right), k1.height) + 1; return k2; } /** * Double rotate binary tree node: first left child with its right child; * then node k3 with new left child. For AVL trees, this is a double * rotation for case 2. Update heights, then return new root. Code from Mark * Alan Weiss' data structures and alogorithms book. */ private AVLNode doubleWithLeftChild(AVLNode k3) { k3.left = rotateWithRightChild(k3.left); return rotateWithLeftChild(k3); } /** * Double rotate binary tree node: first right child with its left child; * then node k1 with new right child. For AVL trees, this is a double * rotation for case 3. Update heights, then return new root. Code from Mark * Alan Weiss' data structures and alogorithms book. */ private AVLNode doubleWithRightChild(AVLNode k1) { k1.right = rotateWithLeftChild(k1.right); return rotateWithRightChild(k1); } public static void main(String[] a) { AVLTree avl = new AVLTree(); System.out.println("Insert and Delete TEST1"); avl.insert("Chris Stuhr"); avl.insert("Bob Brenly"); avl.insert("Alan Keyes"); avl.printTeams(); // test1 System.out.println("/nInsert and Delete TEST2"); avl.insert("Xing Shen"); avl.insert("Grant Hawkes"); avl.printTeams(); // test2 avl.remove("Chris Stuhr"); // found avl.printTeams(); // test2 System.out.println("/nInsert and Delete TEST3"); avl.remove("Xing Shen"); // found avl.remove("Grant Hawkes"); // found avl.insert("Bob Dole"); avl.insert("Grant Davis"); avl.printTeams(); // test3 System.out.println("/nInsert and Delete TEST4"); avl.insert("Zing Ye"); avl.insert("Grant Hawkes"); avl.insert("Bill Clinton"); avl.remove("George W Bush"); // not found avl.printTeams(); // test4 System.out.println("/nInsert and Delete TEST5"); avl.insert("George W Bush"); avl.insert("Sanghu Gite"); avl.remove("George W Bush"); // found avl.printTeams(); // test5 System.out.println("/nFind TEST"); System.out.println(avl.find("Grant Hawkes")); // found System.out.println(avl.find("Grant Davis")); // found System.out.println(avl.find("Grant Smith")); // not found System.out.println(avl.find("Sanghu Gite")); // found System.out.println(avl.find("Munindra Das")); // not found System.out.println("/nMakeEmpty TEST"); avl.makeEmpty(); avl.printTeams(); } }
背景 spring和mybatis集成過程中,我們可以通過MapperFactoryBean的方式配置Mapper接口。但是這樣需要在配置文件中,爲每個mapper配置相同的代碼塊,浪費時間。關鍵對於代碼潔癖的人來說,一點不能忍。 <bea
爲什麼要研究字符串? 人機交互的過程中,文字、數字、字母、符號都是字符表現形式,這部分內容佔了人機信息交互的大部分內容,所以有必要明確一些基本問題。因此大部分數據類型都應該有字符串表達形式,我們在定義新類型的時候可以根據需要來定義新類型的
security的簡單原理: 使用衆多的攔截器對url攔截,以此來管理權限。但是這麼多攔截器,不可能對其一一來講,主要講裏面核心流程的兩個。 首先,權限管理離不開登陸驗證的,所以登陸驗證攔截器AuthenticationProcessing
我們經常會需要啓動多個實例的情況來測試註冊中心、配置中心等基礎設施的高可用,也會用來測試客戶端負載均衡的調用等。但是,我們一個應用只能有一個端口號,這就使得在本機測試的時候,不得不爲同一個服務設置不同的端口來進行啓動。 在本地用不同端口啓動
簡介 Java Reflection,稱爲 Java 反射,是Java基礎部分的一個比較難的點。Reflection(反射)是被視爲動態語言的關鍵,通過反射機制,我們可以在運行時(runtime)獲取類的完整結構。例如,可以獲取到
一面 1. 簡短自我介紹 2. 事務的ACID,其中把事務的隔離性詳細解釋一遍 3. 髒讀、幻影讀、不可重複讀 4. 紅黑樹、二叉樹的算法 5. 平常用到哪些集合類?ArrayList和LinkedList區別?HashMap內部數據結構
當我們站在技術之路的原點,未來可能充滿了迷茫,也存在着很多不同的可能。在這個知識爆炸與終身學習/碎片化學習爲主的時代,我們面臨的問題之一就是如何進行有效學習,不僅能有效平衡廣度與深度,並且能真正的積澱下來,提升自己的研發效能。於筆者而
阿里巴巴Java開發手冊 梳理筆記 - finally 塊必須對資源對象、流對象進行關閉 規約內容: 2.1 異常處理 6. 【強制】 finally 塊必須對資源對象、流對象進行關閉,有異常也要做 try - catch 。 說明:如果
在Java方面,能夠實現多線程安全修改對象值得方法只有2個 1.原子操作 2.互斥方法 而在Java當中,或是其他語言中,基本上也都是使用CAS實現。CAS是比較並交換的意思,這個操作包含2個連續的操作,比較,還有賦值,因爲2個操作在cpu
單線程輪詢並執行任務,有可能會導致飢餓。比較適合於一些具有一個任務的週期調度。 任務列表用數組存儲,元素最前面的元素是最先被執行的任務。 schedule方法是固定間隔執行,根據上一次執行的結束時間來定義間隔的開始時間 scheduleAt
創建的ReadWriteLock需要使用兩個方法來繼續創造2個對象,分別是ReadLock和WriteLock。 這兩個鎖對象的方法調用都會匯聚到ReadWriteLock的Sync類中。多個對象的方法調用匯聚到一個對象上面,這個設計模式是
synchronized關鍵字可以修飾普通方法,靜態方法,當修飾普通方法,鎖對象是當前對象,當修飾靜態方法,鎖對象是當前類的class synchroinzed關鍵字可以使用同步代碼塊實現同步,此時可以指定鎖對象。 同步方法的實現方式 同步
AQS是Java多線程編程的重入鎖,管程,工具類的基礎類,是必須要掌握的。不掌握這個類,根本不能稱之爲合格的Java程序員。 即使是把這個類所有的代碼都背會,也是值得的。 如何標識已經有線程在執行呢? 有兩個變量,一個state變量,一個e
################這是之前的思考 內存屏障只是保證清空流水線,如何保證高速緩存的內容更新到最新或刷新到主存呢?這個問題突然想到了,不知道這個需要怎回答。 內存屏障保證的CPU執行執行序列能夠順序執行,而不是亂序執行。當然,前提
使用volidate關鍵字修飾的成員變量,保證可見性,也就是當一個線程修改這樣的成員變量後,其他的線程能夠立即看到這次的修改。有兩個方面的原因: 1.編譯器不優化對這樣的關鍵字修飾變量的一些訪問操作 2.對讀,寫這個關鍵字修飾的變量前後,會