Revision: 58209
Updated Code
at July 1, 2012 10:13 by edwarddr
Updated Code
/* * Author: Ruo Ding * Date: June 26, 2012 */ import java.io.File; import java.util.ArrayList; import java.util.Hashtable; import java.util.Scanner; public class SimpleTrie { /** * @param args */ private SimpleTrieNode root; private SimpleTrieNode head; public SimpleTrie() { root = new SimpleTrieNode(); head = null; } public void initTrie(String aWord) { if (head!=null) return; SimpleTrieNode scanningNode = root; for (int i = 0; i < aWord.length(); i++) { char letter = aWord.charAt(i); int iChar = Character.getNumericValue(letter) - 10; String subWord = aWord.substring(0, i+1); scanningNode.subNodes[iChar] = new SimpleTrieNode(subWord); scanningNode = scanningNode.subNodes[iChar]; } scanningNode.isWord = true; head = scanningNode; } public void insert(String word) { SimpleTrieNode scanningNode = root; String aWord = word.toLowerCase(); if (head == null) { initTrie(aWord); return; } SimpleTrieNode nextWord = null; SimpleTrieNode prevWord = null; for (int i = 0; i < aWord.length(); i++) { char letter = aWord.charAt(i); int iChar = Character.getNumericValue(letter) - 10; if (scanningNode.subNodes[iChar] != null) { scanningNode = scanningNode.subNodes[iChar]; if (scanningNode.values.length == aWord.length() && scanningNode.toString().equals(aWord) && !scanningNode.isWord) { // if the word occur as a prefix in our list, // than find the fist word with this prefix, insert this in the front nextWord = findNextWord(scanningNode, 0); scanningNode.isWord = true; if (nextWord.prev != null) { prevWord = nextWord.prev; prevWord.next = scanningNode; scanningNode.prev = prevWord; } scanningNode.next = nextWord; nextWord.prev = scanningNode; return; } }else { if (prevWord == null && nextWord == null) { nextWord = findNextWord(scanningNode, iChar+1); prevWord = findPrevWord(scanningNode, iChar-1); } String subWord = aWord.substring(0, i+1); scanningNode.subNodes[iChar] = new SimpleTrieNode(subWord); scanningNode = scanningNode.subNodes[iChar]; } } scanningNode.isWord = true; if (prevWord != null) { prevWord.next = scanningNode; scanningNode.prev = prevWord; } if (nextWord != null) { nextWord.prev = scanningNode; scanningNode.next = nextWord; } } public SimpleTrieNode find(String word) { if (head == null) { return null; } SimpleTrieNode scanningNode = root; String aWord = word.toLowerCase(); for (int i = 0; i < aWord.length(); i++) { char letter = aWord.charAt(i); int iChar = Character.getNumericValue(letter) - 10; if (scanningNode.subNodes[iChar] != null) { scanningNode = scanningNode.subNodes[iChar]; if (scanningNode.values.length == aWord.length()) { if (scanningNode.isWord) { return scanningNode; }else { return null; } } }else { return null; } } return null; } public SimpleTrieNode remove(String word) { SimpleTrieNode toRemove = find(word); if(toRemove.prev!=null) { toRemove.prev.next = toRemove.next; } if(toRemove.next!=null) { toRemove.next.prev = toRemove.prev; } return toRemove; } public SimpleTrieNode getHead() { return head; } // give the parent node and the index starts to scan in parent node public SimpleTrieNode findNextWord(SimpleTrieNode node, int cIndex) { if (node == null) return null; String subWord = node.toString(); for (int i = cIndex; i<node.subNodes.length; i++) { if (node.subNodes[i] != null) { if (node.subNodes[i].isWord) { return node.subNodes[i]; }else { return findNextWord(node.subNodes[i], 0); } } } // none found in the same or below level, proceed to the next in its parent level SimpleTrieNode theParent = null; for (int i = 0; i < subWord.length()-1; i++) { if (theParent == null) { theParent = root; } char letter = subWord.charAt(i); int iChar = Character.getNumericValue(letter) - 10; if (theParent.subNodes[iChar]!=null) { theParent = theParent.subNodes[iChar]; }else { return null; } } int nextIndex = -1; if (subWord.length()>=1) { char nextChar = subWord.charAt(subWord.length()-1); nextIndex = Character.getNumericValue(nextChar) - 10; } return findNextWord(theParent, nextIndex+1); } // give the parent node and the index starts to scan in parent node public SimpleTrieNode findPrevWord(SimpleTrieNode node, int cIndex) { if (node == null) return null; String subWord = node.toString(); for (int i = cIndex; i >= 0; i--) { if (node.subNodes[i] != null) { SimpleTrieNode rSubNode = findPrevWord(node.subNodes[i], 25); if (rSubNode != null) { return rSubNode; }else if (node.subNodes[i].isWord) { return node.subNodes[i]; } } } //if none exist before the index in the node child, check if node is a word if (node.isWord) { return node; } // none found in the same or below level, proceed to the prev in its parent level SimpleTrieNode theParent = null; int iChar = -1; int i; for ( i = 0; i < subWord.length()-1; i++) { if (theParent == null) { theParent = root; } char letter = subWord.charAt(i); iChar = Character.getNumericValue(letter) - 10; if (theParent.subNodes[iChar]!=null) { theParent = theParent.subNodes[iChar]; }else { return null; } } int nextIndex = -1; if (subWord.length()>=1) { char nextChar = subWord.charAt(subWord.length()-1); nextIndex = Character.getNumericValue(nextChar) - 10; } return findPrevWord(theParent, nextIndex-1); } // main just test some basic functions for this SimpleTrie public static void main(String[] args) { SimpleTrie ourTrie = new SimpleTrie(); File dbFile = new File("dictionary.txt"); int wordsCount = 0; int nodesCount = 0; ArrayList<String> allWords = new ArrayList<String>(); Hashtable<String, Integer> table = new Hashtable<String, Integer>(); int duplicateCounts = 0; try{ if (dbFile.exists()) { Scanner preProcessor = new Scanner(dbFile); while (preProcessor.hasNextLine()) { String theWord = preProcessor.nextLine(); if (theWord.equals("abalone")) { System.out.println("Hit abalone"); } ourTrie.insert(theWord); allWords.add(theWord); wordsCount++; if (table.get(theWord)!=null) { duplicateCounts++; } table.put(theWord, new Integer(1)); } preProcessor.close(); } SimpleTrieNode aR = ourTrie.remove("zimbalon"); System.out.println(aR.toString()); SimpleTrieNode printNode = ourTrie.getHead(); while(printNode!=null) { //System.out.println(printNode.toString()); printNode = printNode.next; nodesCount++; } for (int i = 0; i< allWords.size(); i++) { String aWord = allWords.get(i); if (ourTrie.find(aWord) == null) { System.out.println("Word: \'" + aWord + "\' not found!"); } } }catch(Exception e) { System.out.println("Faild with Error: " + e.getMessage() + ", at line: " + wordsCount + ", at node " + nodesCount); } System.out.println("TotalWord from dic is: " + wordsCount + ", and total nodes is: " + nodesCount + ", dupcount: " + duplicateCounts); } } public class SimpleTrieNode { /** * @param args */ public SimpleTrieNode prev; public SimpleTrieNode next; public SimpleTrieNode[] subNodes; public char[] values; public char sValue; public boolean isWord; // true indicate the node contains a word in our dictionary public SimpleTrieNode() { prev = null; next = null; subNodes = new SimpleTrieNode[26]; } public SimpleTrieNode(String word) { prev = null; next = null; subNodes = new SimpleTrieNode[26]; values = word.toCharArray(); if (values.length >= 1) { sValue = values[values.length-1]; } } public String toString() { if (values == null) return ""; return new String(values); } }
Revision: 58208
Initial Code
Initial URL
Initial Description
Initial Title
Initial Tags
Initial Language
at July 1, 2012 10:09 by edwarddr
Initial Code
/* * Author: Ruo Ding * Date: June 22, 2012 */ import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashSet; import java.util.Hashtable; import java.util.Scanner; public class SmallDatabase { public static final String dbFileName = "SmallDatabaseRecords.txt"; Hashtable<String, RecordNode> all_records = new Hashtable<String, RecordNode>(); HashSet<Integer> all_values = new HashSet<Integer>(); private boolean terminates; private CommandNode transactionCommandPointer; private ArrayList<RecordNode> transactionRecords; public static void main(String[] args) { File dbFile = new File(dbFileName); try{ Hashtable<String, RecordNode> oldRecords = new Hashtable<String, RecordNode>(); HashSet<Integer> valueSet = new HashSet<Integer>(); if (dbFile.exists()) { Scanner preProcessor = new Scanner(dbFile); while (preProcessor.hasNextLine()) { RecordNode aRecord = makeRecord(preProcessor.nextLine()); if (aRecord != null) { Integer trial_value = new Integer(aRecord.getValue()); if (valueSet.contains(trial_value)) { getFirstWithValue(oldRecords, trial_value).setNext(aRecord); }else { valueSet.add(new Integer(aRecord.getValue())); } oldRecords.put(aRecord.getName(), aRecord); } } preProcessor.close(); } SmallDatabase mydb = new SmallDatabase(oldRecords, valueSet); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String inputLine = null; while (!mydb.isTerminated()) { inputLine = br.readLine(); if (inputLine.equals("END")) { mydb.setTerminates(true); continue; } CommandNode aCommand = makeCommand(inputLine); if (aCommand != null) { mydb.processCommand(aCommand); } } if (dbFile.exists()) { dbFile.delete(); } dbFile.createNewFile(); FileWriter fstream = new FileWriter(dbFile); BufferedWriter out = new BufferedWriter(fstream); Hashtable<String, RecordNode> finalRecords = mydb.getAll_records(); Enumeration<String> e = finalRecords.keys(); while (e.hasMoreElements()) { String aKey = e.nextElement(); RecordNode currentNode = finalRecords.get(aKey); out.write(aKey + " " + currentNode.getValue() + "\n"); } out.close(); }catch(Exception e) { System.out.println("Processing Database Records Faild with Error: " + e.getMessage()); } } public SmallDatabase(Hashtable<String, RecordNode> table, HashSet<Integer> values) { all_records = table; all_values = values; terminates = false; transactionCommandPointer = null; transactionRecords = null; } public void processCommand(CommandNode aCommand) { switch (aCommand.getCommandId()) { case CommandNode.SET: dbSet(aCommand); break; case CommandNode.GET: dbGet(aCommand.getName()); break; case CommandNode.UNSET: dbUnset(aCommand); break; case CommandNode.NUMEQUALTO: System.out.println(dbGetCount(aCommand.getValue())); break; case CommandNode.BEGIN: dbTranBegin(aCommand); break; case CommandNode.ROLLBACK: dbRollBack(aCommand); break; case CommandNode.COMMIT: dbCommit(); break; default: break; } } private void dbCommit() { if (transactionCommandPointer == null || transactionRecords == null) { System.out.println("FALSE COMMIT"); return; } for (int i = 0; i < transactionRecords.size(); i++) { RecordNode aRecord = transactionRecords.get(i); int aValue = aRecord.getValue(); String aKey = aRecord.getName(); if (all_values.contains(aValue)) { // a value already exists in db // append RecordNode after the first node with such value getFirstWithValue(all_records, aValue).setNext(aRecord); }else { all_values.add(new Integer(aValue)); } all_records.put(aKey, aRecord); } transactionCommandPointer = null; transactionRecords = null; } private void dbRollBack(CommandNode aCmd) { if (transactionCommandPointer == null) { System.out.println("INVALID ROLLBACK"); return; } boolean hitBegin = false; while(transactionCommandPointer != null && !hitBegin) { hitBegin = reverseProcessing(transactionCommandPointer); transactionCommandPointer = transactionCommandPointer.getPrevious(); } } // reversely handles only the meaningful command, i.e. SET & UNSET // return true when the aCmd is a BEGIN private boolean reverseProcessing(CommandNode aCmd) { switch (aCmd.getCommandId()) { case CommandNode.SET: int index = findWithNameInTransaction(aCmd.getName()); if (index >= 0) { transactionRecords.remove(index); }else { System.out.println("Error, any SET in a transaction should store at arraylist"); } break; case CommandNode.UNSET: reverUnset(aCmd); break; case CommandNode.BEGIN: return true; default: break; } return false; } private void reverUnset(CommandNode aCmd) { if (aCmd.getCommandId() != CommandNode.UNSET) { return; } String aKey = aCmd.getName(); int aValue = aCmd.getValue(); RecordNode aRec= new RecordNode(aKey, aValue); // before this step, the aKey should not be present in both arraylist and hashtable if (aCmd.isModifiedFromPersist()) { if (all_values.contains(aValue)) { // a value already exists in db // append RecordNode after the first node with such value getFirstWithValue(all_records, aValue).setNext(aRec); }else { all_values.add(new Integer(aValue)); } all_records.put(aKey, aRec); }else { transactionRecords.add(aRec); } } private void dbTranBegin(CommandNode aCmd) { if (transactionCommandPointer == null) { transactionCommandPointer = aCmd; transactionRecords = new ArrayList<RecordNode>(); }else { transactionCommandPointer.setNext(aCmd); transactionCommandPointer = transactionCommandPointer.getNext(); } } private void dbSet(CommandNode aCmd) { String name = aCmd.getName(); int value = aCmd.getValue(); RecordNode aRecord = new RecordNode(name, value); if (aRecord != null) { if (transactionCommandPointer == null) { Integer trial_value = new Integer(aRecord.getValue()); if (all_values.contains(trial_value)) { if (all_records.get(name) == null) { // if this is a record with new key entry and value already exists in db // append RecordNode after the first node with such value getFirstWithValue(all_records, trial_value).setNext(aRecord); } }else { all_values.add(new Integer(aRecord.getValue())); } RecordNode oldNode = all_records.get(name); if (oldNode != null) { int oldValue = oldNode.getValue(); if (oldValue != value ) { shrinkValues(oldValue); } reconnectNode(oldNode); } all_records.put(aRecord.getName(), aRecord); }else { int indexInNewRecords = findWithNameInTransaction(name); if (indexInNewRecords >= 0) { RecordNode oldNode = transactionRecords.get(indexInNewRecords); int oldValue = oldNode.getValue(); if (oldValue != value ) { shrinkValues(oldValue); } transactionRecords.remove(indexInNewRecords); CommandNode unsetAction = new CommandNode(CommandNode.UNSET, name, false); unsetAction.setValue(oldValue); transactionCommandPointer.setNext(unsetAction); transactionCommandPointer = transactionCommandPointer.getNext(); } else if (all_records.get(name) != null) { RecordNode oldNode = all_records.get(name); int oldValue = oldNode.getValue(); if (oldValue != value ) { shrinkValues(oldValue); } reconnectNode(oldNode); all_records.remove(name); CommandNode unsetAction = new CommandNode(CommandNode.UNSET, name, true); unsetAction.setValue(oldValue); transactionCommandPointer.setNext(unsetAction); transactionCommandPointer = transactionCommandPointer.getNext(); } transactionRecords.add(aRecord); transactionCommandPointer.setNext(aCmd); transactionCommandPointer = transactionCommandPointer.getNext(); } } } private void dbUnset(CommandNode aCmd) { String nameKey = aCmd.getName(); RecordNode result = all_records.get(nameKey); if (result != null) { int oldValue = result.getValue(); shrinkValues(oldValue); reconnectNode(result); all_records.remove(nameKey); if (transactionCommandPointer != null) { CommandNode unsetAction = new CommandNode(CommandNode.UNSET, nameKey, true); unsetAction.setValue(oldValue); transactionCommandPointer.setNext(unsetAction); transactionCommandPointer = transactionCommandPointer.getNext(); } }else { int indexInTran = findWithNameInTransaction(nameKey); if (indexInTran >= 0) { result = findInTransaction(nameKey); int oldValue = result.getValue(); shrinkValues(oldValue); transactionRecords.remove(indexInTran); CommandNode unsetAction = new CommandNode(CommandNode.UNSET, nameKey, false); unsetAction.setValue(oldValue); transactionCommandPointer.setNext(unsetAction); transactionCommandPointer = transactionCommandPointer.getNext(); }else { System.out.println("Not Found, can't unset"); } } } private void reconnectNode(RecordNode oldNode) { if (oldNode.previous != null) { oldNode.previous.setNext(oldNode.next); }else { if (oldNode.next != null) { oldNode.next.previous = null; } } } private void shrinkValues(int oldValue) { if (countRecord(oldValue) == 1) { all_values.remove(new Integer(oldValue)); } } private void dbGet(String key) { RecordNode result = all_records.get(key); if (result != null) { System.out.println(result.getValue()); }else { result = findInTransaction(key); if (result != null) { System.out.println(result.getValue()); }else { System.out.println("NULL"); } } } private RecordNode findInTransaction(String keyValue) { if (transactionRecords == null) { return null; } for (int i = 0; i < transactionRecords.size(); i++) { if (transactionRecords.get(i).getName().equals(keyValue)) { return transactionRecords.get(i); } } return null; } private int dbGetCount(int value) { int recordCountResult = countRecord(value); if (transactionRecords == null) { return recordCountResult; } for (int i = 0; i < transactionRecords.size(); i++) { if (transactionRecords.get(i).getValue() == value) { recordCountResult++; } } return recordCountResult; } public static CommandNode makeCommand(String input) { String[] content = input.split(" "); if (content.length < 1) { System.out.println("Invalid Command"); return null; } if (content[0].equals("SET") && content.length == 3) { return new CommandNode(CommandNode.SET, content[1], Integer.parseInt(content[2])); } else if (content[0].equals("GET") && content.length == 2) { return new CommandNode(CommandNode.GET, content[1]); } else if (content[0].equals("UNSET") && content.length == 2) { return new CommandNode(CommandNode.UNSET, content[1]); } else if (content[0].equals("NUMEQUALTO") && content.length == 2) { return new CommandNode(CommandNode.NUMEQUALTO, Integer.parseInt(content[1])); } else if (content[0].equals("BEGIN") && content.length == 1) { return new CommandNode(CommandNode.BEGIN); } else if (content[0].equals("ROLLBACK") && content.length == 1) { return new CommandNode(CommandNode.ROLLBACK); } else if (content[0].equals("COMMIT") && content.length == 1) { return new CommandNode(CommandNode.COMMIT); }else { System.out.println("Invalid Command"); return null; } } public static RecordNode makeRecord(String input) { String[] content = input.split(" "); if (content.length != 2) { System.out.println("Error making a Record, Invalid Data Format!"); return null; } int rValue = Integer.parseInt(content[1]); return (new RecordNode(content[0], rValue)); } // normal this is invoked when it's certain that there exist a node with inputV to reduce the cost public static RecordNode getFirstWithValue(Hashtable<String, RecordNode> table, int inputV) { Enumeration<String> e = table.keys(); while (e.hasMoreElements()) { String aKey = e.nextElement(); RecordNode currentNode = table.get(aKey); if (currentNode.getValue() == inputV) { return currentNode; } } return null; } public int countRecord(int rValue) { if (!all_values.contains(rValue)) { return 0; } Enumeration<String> e = all_records.keys(); int counter = 0; while (e.hasMoreElements()) { String aKey = e.nextElement(); if (all_records.get(aKey).getValue() == rValue) { counter = 1 + countAdjNode(all_records.get(aKey)); break; } } return counter; } private int countAdjNode(RecordNode a) { int adjCount = 0; RecordNode pre = a.previous; while (pre != null) { adjCount ++; pre = pre.previous; } RecordNode next = a.next; while (next != null) { adjCount++; next = next.next; } return adjCount; } private int findWithNameInTransaction(String name) { if (transactionRecords == null) { return -1; } for (int i = 0; i < transactionRecords.size(); i++) { if (transactionRecords.get(i).getName().equals(name)) { return i; } } return -1; } public boolean isTerminated() { return terminates; } public void setTerminates(boolean terminates) { this.terminates = terminates; } public Hashtable<String, RecordNode> getAll_records() { return all_records; } public void printTable() { Enumeration<String> e = all_records.keys(); while (e.hasMoreElements()) { String aKey = e.nextElement(); System.out.println("Key is: " + aKey + ", value is: " + all_records.get(aKey).getValue()); } } } public class SimpleTrieNode { /** * @param args */ public SimpleTrieNode prev; public SimpleTrieNode next; public SimpleTrieNode[] subNodes; public char[] values; public char sValue; public boolean isWord; // true indicate the node contains a word in our dictionary public SimpleTrieNode() { prev = null; next = null; subNodes = new SimpleTrieNode[26]; } public SimpleTrieNode(String word) { prev = null; next = null; subNodes = new SimpleTrieNode[26]; values = word.toCharArray(); if (values.length >= 1) { sValue = values[values.length-1]; } } public String toString() { if (values == null) return ""; return new String(values); } }
Initial URL
Initial Description
A short practice to write a trie with LinkedList for all the valid words
Initial Title
Trie with LinkedList
Initial Tags
Initial Language
Java