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