/*****************************************************************************/ /* */ /* Hashing Test program: Graphical Version */ /* */ /* February 1998, Toshimi Minoura */ /* */ /*****************************************************************************/ // Each node in the hash table can store a key and a value. // Linear probing should be implemented for collision resolution. import java.awt.*; import java.awt.event.*; import java.util.*; class Node { public String key; // key for this node public Object value; // value associated with key boolean focus; Node(String key, Object val) { // constructor this.key = key; // copy argument value = val; // copy argument focus = true; System.out.println("node with key " + key + " created"); } public String toString() { // create String for node return "node with k = " + key + ", value = " + value; } } class HashG extends StepTestCanvas { static final int TableSize = 17; // hash table size private Node table[]; // storage for hash table data int currentIdx = -1; // index for node currently being visited public HashG() { // constructor table = new Node[TableSize]; } int hash(String key) { // hashing function return Math.abs(key.hashCode() % TableSize); } public void insert(String key, Object data) { // add node to hash table int idx = hash(key); currentIdx = idx; // set arrow location repaintStep("New node with key = " + key + " will be added at " + idx + '.'); table[idx] = new Node(key, data); table[idx].focus = true; // highlight new node System.out.println("New node with key = " + key + " added at " + idx); repaintStep("New node with key = " + key + " added."); table[idx].focus = false; currentIdx = -1; // hide arrow } public Node find(String key) { System.out.println("HashG.find() entered with key = " + key); int idx = hash(key); System.out.println("HashG.find(): idx = " + idx); currentIdx = idx; // show arrow repaintStep("Node with key = " + key + " should be located at " + idx); if (table[idx] != null) { table[idx].focus = true; // highlight node located if (table[idx].key.equals(key)) { table[idx].focus = false; // unhighlight node located return table[idx]; // return node found } else { table[idx].focus = false; // unhighlight node located } } repaintStep("Node with key = " + key + " does not exist."); currentIdx = -1; return null; } static final int TableXLoc = 300; static final int TableYLoc = 20; static final int NodeWidth = 80; static final int NodeHeight = 30; static Color LineColor = new Color(0, 0, 0); static Color EmptyNodeColor = new Color(0, 100, 0); static Color OccupiedNodeColor = new Color(150, 255, 0); static Color NewNodeColor = new Color(255, 255, 0); static final Color RightArrowColor = new Color(0, 100, 255); public void drawRightArrow(Graphics g, int x1, int y1, int x2) { Polygon poly = new Polygon(); // arrow from (x1, y1) to (x2, y1) poly.addPoint(x1, y1 - 2); poly.addPoint(x1, y1 + 2); poly.addPoint(x2 - 6, y1 + 2); poly.addPoint(x2 - 6, y1 + 6); poly.addPoint(x2, y1); // tip of right arrow poly.addPoint(x2 - 6, y1 - 6); poly.addPoint(x2 - 6, y1 - 2); g.fillPolygon(poly); // draw arrow } Font f = new Font("TimesRoman", Font.BOLD, 18); public void paint(Graphics g) { System.out.println("HashG.paint() entered"); g.setFont(f); // set font for letters if (currentIdx >= 0) { int y = TableYLoc + currentIdx * NodeHeight; // y position of arrwo g.setColor(RightArrowColor); // set right arrow color drawRightArrow(g, TableXLoc - NodeWidth * 4 / 5, y + NodeHeight / 2, TableXLoc - 30); } for (int i = 0; i < TableSize; i++) { int y = TableYLoc + i * NodeHeight; // y position of node g.setColor(Color.black); // color for node index if (i < 10) g.drawString(" " + i, TableXLoc - 25, y + NodeHeight / 2 + 4); else g.drawString("" + i, TableXLoc - 25, y + NodeHeight / 2 + 4); if (table[i] == null) { g.setColor(EmptyNodeColor); // set color for empty node } else if (table[i].focus) { g.setColor(NewNodeColor); // set color for new or visited node } else { g.setColor(OccupiedNodeColor); // color for other occupied nodes } g.fillRect(TableXLoc + 2, y + 2, NodeWidth - 3, NodeHeight - 3); g.setColor(Color.black); // color for node frame g.drawRect(TableXLoc, y, NodeWidth, NodeHeight); // draw node if (table[i] == null) { g.setColor(Color.white); g.drawString("null", TableXLoc + NodeWidth / 3, y + NodeHeight / 2 + 4); continue; } g.setColor(Color.blue); // set label color for occupied node g.drawString(table[i].key + ", " + table[i].value, TableXLoc + NodeWidth / 3, y + NodeHeight / 2 + 5); } } public static void main(String argv[]) { new StepTestFrame("Hash Table", new HashG(), 700, 700).show(); } public void runMain() { // called from run() of StepTestCanvas System.out.println("HashG.runMain() entered"); for (int i = 0; i < TableSize; i++) { table[i] = null; // initially no entry } currentIdx = -1; repaintStep(); // display message "Press Step, Delay, or Continue Button" repaintStep("You may provide key values to be ued in the input area as " + "\"e h g s o r a d k w c t\""); int i = 0; // counter StringTokenizer inputTokens = getInputTokens(); // read from input area int inputSize = inputTokens.countTokens(); if (inputSize == 0) { // no key values are provided inputTokens = new StringTokenizer("e h g s o r a d k w c t"); inputSize = inputTokens.countTokens(); } for (i = 0; i < inputSize; i++) { String token = inputTokens.nextToken(); // get next token insert(token, new Integer(i)); } repaintStep("Node insertion complete."); String keys[] = {"c", "h", "w", "donkey", "j"}; for (int j = 0; j < keys.length; j++) { Node nodeFound = find(keys[j]); // locate node with a given key if (nodeFound != null && nodeFound.key.equals(keys[j])) { repaintStep("Node found: " + nodeFound); } else { repaintStep("Node with key = " + keys[j] + " not found."); } } System.out.println("runMain() completed"); } }