commit 2b551e1e3a470125b280ad4dcef6307d11ada517 Author: joshashtondev Date: Tue Aug 4 06:58:30 2026 -0600 init commit diff --git a/graph-visualizer/App.java b/graph-visualizer/App.java new file mode 100644 index 0000000..5621715 --- /dev/null +++ b/graph-visualizer/App.java @@ -0,0 +1,5 @@ +public class App { + public static void main(String[] args) { + GUI.setup(); + } +} diff --git a/graph-visualizer/DisplayPanel.java b/graph-visualizer/DisplayPanel.java new file mode 100644 index 0000000..577bb1d --- /dev/null +++ b/graph-visualizer/DisplayPanel.java @@ -0,0 +1,114 @@ +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; + +import javax.swing.JPanel; +import javax.swing.text.Position; + +import edu.princeton.cs.algs4.Edge; + +public class DisplayPanel extends JPanel { + + private static ST st; + private int n; + private static final int SIZE = 256; + private int a = SIZE / 2; + private int b = a; + private int r = 4 * SIZE / 5; + + public DisplayPanel() { + super(); + setPreferredSize(new Dimension(300, 300)); + setSize(getPreferredSize()); + } + + @Override + protected void paintComponent(Graphics g) { + st = new ST<>(); + EdgeWeightedGraph G = GraphFunctions.getGraph(); + for(int v = 0; v < G.V(); v++) + st.put(v, new Vertex(v)); + n = st.size(); + // draw the entire graph first + + Graphics2D g2d = (Graphics2D) g; + g2d.setRenderingHint( + RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setColor(Color.WHITE); + a = getWidth() / 2; + b = getHeight() / 2; + int m = Math.min(a, b); + r = 4 * m / 5; + int r2; + if(n > 0) r2 = Math.abs(m - r) / n; + else r2 = Math.abs(m - r) / 2; + for (int i = 0; i < n; i++) { + double t = 2 * Math.PI * i / n; + int x = (int) Math.round(a + r * Math.cos(t)); + int y = (int) Math.round(b + r * Math.sin(t)); + g2d.fillOval(x - r2, y - r2, 2 * r2, 2 * r2); + st.put(i, new Vertex(x, y)); + } + + g.getFont().deriveFont(Font.BOLD); + g2d.setColor(Color.ORANGE); + if(n < 50) { + for(int i = 0; i < n; i++) { + int x = st.get(i).getX(); + int y = st.get(i).getY(); + + g.drawString(i + "", x - (2 * r2), y + (2 * r2)); + } + } + + drawLine(r2, g, g2d, G.edges(), Color.WHITE); + drawLine(r2, g, g2d, GraphFunctions.getMST(), Color.GREEN); + } + + private void drawLine(int r2, Graphics g, Graphics2D g2d, Iterable edges, Color color) { + g2d.setColor(color); + for (Edge e: edges) { + int v = e.either(); + int w = e.other(v); + + int vX = st.get(v).getX(); + int wX = st.get(w).getX(); + int vY = st.get(v).getY(); + int wY = st.get(w).getY(); + + g.drawLine(vX, vY, wX, wY); + g.drawString(String.format("%.0f", e.weight()), ((vX + wX) / 2) + r2, ((vY + wY) / 2) + r2); + } + } + + private class Vertex { // extends JComponent for @Override of paint()? + private int x; + private int y; + private int v; + + public Vertex(int v) { + this.v = v; + } + + public Vertex(int x, int y) { + this.x = x; + this.y = y; + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + public int getV() { + return v; + } + } +} diff --git a/graph-visualizer/EdgeWeightedGraph.java b/graph-visualizer/EdgeWeightedGraph.java new file mode 100644 index 0000000..fb9551d --- /dev/null +++ b/graph-visualizer/EdgeWeightedGraph.java @@ -0,0 +1,204 @@ +import edu.princeton.cs.algs4.In; +import edu.princeton.cs.algs4.Bag; +import edu.princeton.cs.algs4.StdOut; +import edu.princeton.cs.algs4.Edge; +import edu.princeton.cs.algs4.StdRandom; +import java.util.NoSuchElementException; +import java.util.ArrayList; + +/** + * + * Modification of Sedgewick and Wayne's EdgeWeightedGraph, to allow a dynamic number of vertices based upon user input. + * + * @author Robert Sedgewick + * @author Kevin Wayne + * @author Josh Ashton + */ +public class EdgeWeightedGraph { + private static final String NEWLINE = System.getProperty("line.separator"); + + private int V; + private int E; + private ArrayList> adj; + + /** + * Create a new EdgeWeightedGraph with no vertices or edges. These may be added dynamically by the user. + */ + public EdgeWeightedGraph() { + this.V = 0; + this.E = 0; + adj = new ArrayList<>(); + } + + public EdgeWeightedGraph(In in) { + if (in == null) throw new IllegalArgumentException("argument is null"); + + try { + V = in.readInt(); + adj = new ArrayList>(); + for (int v = 0; v < V; v++) { + adj.add(new Bag()); + } + + int E = in.readInt(); + if (E < 0) throw new IllegalArgumentException("Number of edges must be non-negative"); + for (int i = 0; i < E; i++) { + int v = in.readInt(); + int w = in.readInt(); + validateVertex(v); + validateVertex(w); + double weight = in.readDouble(); + Edge e = new Edge(v, w, weight); + addEdge(e); + } + } + catch (NoSuchElementException e) { + throw new IllegalArgumentException("invalid input format in EdgeWeightedGraph constructor", e); + } + + } + + + /** + * Initializes a random edge-weighted graph with {@code V} vertices and E edges. + * + * @param V the number of vertices + * @param E the number of edges + * @throws IllegalArgumentException if {@code V < 0} + * @throws IllegalArgumentException if {@code E < 0} + */ + public EdgeWeightedGraph(int V, int E) { + this.V = V; + adj = new ArrayList>(); + for (int v = 0; v < V; v++) { + adj.add(new Bag()); + } + + if (E < 0) throw new IllegalArgumentException("Number of edges must be non-negative"); + for (int i = 0; i < E; i++) { + int v = StdRandom.uniformInt(V); + int w = StdRandom.uniformInt(V); + int weight = StdRandom.uniformInt(0, 100); + Edge e = new Edge(v, w, (double) weight); + addEdge(e); + } + } + + /** + * Adds a new vertex to the edge-weighted graph. + */ + public void addVertex() { + Bag b = new Bag<>(); + V++; + adj.add(b); + } + + /** + * Adds the undirected edge {@code e} to this edge-weighted graph. + * + * @param e the edge + * @throws IllegalArgumentException unless both endpoints are between {@code 0} and {@code V-1} + */ + public void addEdge(Edge e) { + int v = e.either(); + int w = e.other(v); + validateVertex(v); + validateVertex(w); + adj.get(v).add(e); + adj.get(w).add(e); + E++; + } + + /** + * Returns the number of vertices in this edge-weighted graph. + * + * @return the number of vertices in this edge-weighted graph + */ + public int V() { + return V; + } + + /** + * Returns the number of edges in this edge-weighted graph. + * + * @return the number of edges in this edge-weighted graph + */ + public int E() { + return E; + } + + // throw an IllegalArgumentException unless {@code 0 <= v < V} + private void validateVertex(int v) { + if (v < 0 || v >= V) + throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1)); + } + + /** + * Returns the edges incident on vertex {@code v}. + * + * @param v the vertex + * @return the edges incident on vertex {@code v} as an Iterable + * @throws IllegalArgumentException unless {@code 0 <= v < V} + */ + public Iterable adj(int v) { + validateVertex(v); + return adj.get(v); + } + + /** + * Returns the degree of vertex {@code v}. + * + * @param v the vertex + * @return the degree of vertex {@code v} + * @throws IllegalArgumentException unless {@code 0 <= v < V} + */ + public int degree(int v) { + validateVertex(v); + return adj.get(v).size(); + } + + /** + * Returns all edges in this edge-weighted graph. + * To iterate over the edges in this edge-weighted graph, use foreach notation: + * {@code for (Edge e : G.edges())}. + * + * @return all edges in this edge-weighted graph, as an iterable + */ + public Iterable edges() { + Bag list = new Bag(); + for (int v = 0; v < V; v++) { + int selfLoops = 0; + for (Edge e : adj(v)) { + if (e.other(v) > v) { + list.add(e); + } + // add only one copy of each self loop (self loops will be consecutive) + else if (e.other(v) == v) { + if (selfLoops % 2 == 0) list.add(e); + selfLoops++; + } + } + } + return list; + } + + /** + * Returns a string representation of the edge-weighted graph. + * This method takes time proportional to E + V. + * + * @return the number of vertices V, followed by the number of edges E, + * followed by the V adjacency lists of edges + */ + public String toString() { + StringBuilder s = new StringBuilder(); + s.append("vertices: " + V + " || edges: " + E + NEWLINE); + for (int v = 0; v < V; v++) { + s.append("vertex " + v + " edges: "); + for (Edge e : adj.get(v)) { + s.append(e + " "); + } + s.append(NEWLINE); + } + return s.toString(); + } +} diff --git a/graph-visualizer/GUI.java b/graph-visualizer/GUI.java new file mode 100644 index 0000000..09b20e3 --- /dev/null +++ b/graph-visualizer/GUI.java @@ -0,0 +1,237 @@ +import edu.princeton.cs.algs4.StdRandom; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseListener; +import java.io.File; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JMenuBar; +import javax.swing.JTextField; +import javax.swing.UIManager; +import javax.swing.border.BevelBorder; + +public class GUI { + private final static Color bg = Color.DARK_GRAY; + private final static Color fg = Color.WHITE; + private static JFrame frame; + private static JPanel contentPane; + + public static void setup() { + frame = new JFrame("Graph"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setPreferredSize(new Dimension(1000, 1000)); + frame.setSize(frame.getPreferredSize()); + frame.setResizable(false); + + try { + UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); + } catch (Exception e) { + System.out.println("Error with cross platform look/feel in frameSetup()."); + } + GraphFunctions.init(); + frame.add(createContentPane()); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private static JPanel createContentPane() { + contentPane = new JPanel(new BorderLayout()); + contentPane.add(new DisplayPanel(), BorderLayout.CENTER); + contentPane.add(createButtonPane(), BorderLayout.NORTH); + contentPane.setForeground(fg); + contentPane.setBackground(bg); + + return contentPane; + } + + private static JPanel createButtonPane() { + JPanel pane = new JPanel(); + pane.setForeground(fg); + pane.setBackground(bg); + pane.setAlignmentX(0.5f); + pane.setLayout(new BoxLayout(pane, BoxLayout.X_AXIS)); + pane.setBorder(BorderFactory.createLineBorder(Color.BLACK)); + + pane.add(createAddVPanel()); + + JTextField vertex1 = new JTextField(); + JTextField vertex2 = new JTextField(); + JTextField eWeight = new JTextField(); + vertex1.setForeground(fg); + vertex1.setBackground(bg); + vertex2.setForeground(fg); + vertex2.setBackground(bg); + eWeight.setForeground(fg); + eWeight.setBackground(bg); + + pane.add(vertex1); + pane.add(vertex2); + pane.add(eWeight); + + JButton b = new JButton("Add an edge"); + b.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent arg0) { + if(vertex1.getText().equals("") || vertex2.getText().equals("") || eWeight.getText().equals("")) { + int v = StdRandom.uniformInt(GraphFunctions.getGraph().V()); + int w = StdRandom.uniformInt(GraphFunctions.getGraph().V()); + double weight = StdRandom.uniformInt(0, 100); + GraphFunctions.addEdge(v, w, weight); + } + else { + GraphFunctions.addEdge(Integer.parseInt(vertex1.getText()), + Integer.parseInt(vertex2.getText()), + Double.parseDouble(eWeight.getText())); + } + contentPane.removeAll(); + frame.setContentPane(createContentPane()); + contentPane.repaint(); + contentPane.revalidate(); + } + }); + b.setFocusPainted(false); + b.setFocusable(false); + b.setForeground(fg); + b.setBackground(bg); + pane.add(b); + + JPanel p = new JPanel(new GridLayout(1, 2)); + JPanel subPanel = new JPanel(new GridLayout(2, 1)); + b = new JButton("Reset graph"); + b.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent arg0) { + GraphFunctions.reset(); + contentPane.removeAll(); + frame.setContentPane(createContentPane()); + contentPane.repaint(); + contentPane.revalidate(); + } + }); + b.setFocusPainted(false); + b.setFocusable(false); + b.setForeground(fg); + b.setBackground(bg); + subPanel.add(b); + + b = new JButton("Load graph"); + b.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent arg0) { + JFileChooser fc = new JFileChooser("~"); + int returnVal = fc.showOpenDialog(frame); + if (returnVal == JFileChooser.APPROVE_OPTION) { + GraphFunctions.loadGraph(fc.getSelectedFile()); + contentPane.removeAll(); + frame.setContentPane(createContentPane()); + contentPane.repaint(); + contentPane.revalidate(); + } + } + }); + b.setFocusPainted(false); + b.setFocusable(false); + b.setForeground(fg); + b.setBackground(bg); + subPanel.add(b); + + p.add(subPanel); + p.add(createRandomPanel()); + + contentPane.add(p, BorderLayout.SOUTH); + + return pane; + } + + private static JPanel createAddVPanel() { + JPanel vertPnl = new JPanel(new GridLayout(1, 3)); + vertPnl.setForeground(fg); + vertPnl.setBackground(bg); + JLabel verticesLbl = new JLabel("Number of vertices to add: "); + verticesLbl.setForeground(fg); + verticesLbl.setBackground(bg); + vertPnl.add(verticesLbl); + JTextField addVertices = new JTextField(); + addVertices.setForeground(fg); + addVertices.setBackground(bg); + vertPnl.add(addVertices); + JButton b = new JButton("Add vertices"); + b.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent arg0) { + if(addVertices.getText().equals("")) GraphFunctions.addVertex(); + else { + for(int i = 0; i < Integer.parseInt(addVertices.getText()); i++) + GraphFunctions.addVertex(); + } + contentPane.removeAll(); + frame.setContentPane(createContentPane()); + contentPane.repaint(); + contentPane.revalidate(); + } + }); + b.setFocusPainted(false); + b.setFocusable(false); + b.setForeground(fg); + b.setBackground(bg); + vertPnl.add(b); + return vertPnl; + } + + private static JPanel createRandomPanel() { + JPanel randomPanel = new JPanel(new GridLayout(2, 1)); + randomPanel.setForeground(fg); + randomPanel.setBackground(bg); + JPanel subPanel = new JPanel(new GridLayout(2, 2)); + subPanel.setForeground(fg); + subPanel.setBackground(bg); + JLabel veLabel = new JLabel("Number of Vertices:"); + veLabel.setForeground(fg); + JTextField vertexCount = new JTextField(); + vertexCount.setForeground(fg); + vertexCount.setBackground(bg); + JLabel edLabel = new JLabel("Number of edges:"); + edLabel.setForeground(fg); + JTextField edgesCount = new JTextField(); + edgesCount.setForeground(fg); + edgesCount.setBackground(bg); + subPanel.add(veLabel); + subPanel.add(vertexCount); + subPanel.add(edLabel); + subPanel.add(edgesCount); + randomPanel.add(subPanel); + JButton b = new JButton("Random graph"); + b.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent arg0) { + if(vertexCount.getText().equals("") || edgesCount.getText().equals(""))GraphFunctions.random(10, 20); + else GraphFunctions.random(Integer.parseInt(vertexCount.getText()), Integer.parseInt(edgesCount.getText())); + contentPane.removeAll(); + frame.setContentPane(createContentPane()); + contentPane.repaint(); + contentPane.revalidate(); + } + }); + b.setFocusPainted(false); + b.setFocusable(false); + b.setForeground(fg); + b.setBackground(bg); + randomPanel.add(b); + + return randomPanel; + } +} diff --git a/graph-visualizer/GraphFunctions.java b/graph-visualizer/GraphFunctions.java new file mode 100644 index 0000000..23fcce2 --- /dev/null +++ b/graph-visualizer/GraphFunctions.java @@ -0,0 +1,76 @@ +import edu.princeton.cs.algs4.In; +import edu.princeton.cs.algs4.KruskalMST; + +import java.io.File; +import java.util.Random; + +import edu.princeton.cs.algs4.Edge; + +/** + * @author Josh Ashton + */ +public class GraphFunctions { + + private static KruskalMST mst; + private static EdgeWeightedGraph g = new EdgeWeightedGraph(); // TODO: Convert to a DirectedEdgeWeightedGraph at some point. + + public static void init() { + String fileName = "./resources/GraphInternet.txt"; + g = new EdgeWeightedGraph(new In(fileName)); + + edu.princeton.cs.algs4.EdgeWeightedGraph G = new edu.princeton.cs.algs4.EdgeWeightedGraph(g.V()); + for (Edge e : g.edges()) { + G.addEdge(e); + } + mst = new KruskalMST(G); + } + + public static void random(int V, int E) { + g = new EdgeWeightedGraph(V, E); + edu.princeton.cs.algs4.EdgeWeightedGraph G = new edu.princeton.cs.algs4.EdgeWeightedGraph(g.V()); + for (Edge e : g.edges()) { + G.addEdge(e); + } + mst = new KruskalMST(G); + } + + public static void reset() { + g = new EdgeWeightedGraph(); + + edu.princeton.cs.algs4.EdgeWeightedGraph G = new edu.princeton.cs.algs4.EdgeWeightedGraph(g.V()); + for (Edge e : g.edges()) { + G.addEdge(e); + } + mst = new KruskalMST(G); + } + + public static void loadGraph(File f) { + g = new EdgeWeightedGraph(new In(f)); + + edu.princeton.cs.algs4.EdgeWeightedGraph G = new edu.princeton.cs.algs4.EdgeWeightedGraph(g.V()); + for (Edge e : g.edges()) { + G.addEdge(e); + } + mst = new KruskalMST(G); + } + + public static void addVertex() { + g.addVertex(); + } + + public static void addEdge(int v, int w, double cost) { + g.addEdge(new Edge(v, w, cost)); + } + + public static Iterable getMST() { + edu.princeton.cs.algs4.EdgeWeightedGraph G = new edu.princeton.cs.algs4.EdgeWeightedGraph(g.V()); + for (Edge e : g.edges()) { + G.addEdge(e); + } + return new KruskalMST(G).edges(); + } + + public static EdgeWeightedGraph getGraph() { + return g; + } +} diff --git a/graph-visualizer/ST.java b/graph-visualizer/ST.java new file mode 100644 index 0000000..012d87c --- /dev/null +++ b/graph-visualizer/ST.java @@ -0,0 +1,206 @@ +import edu.princeton.cs.algs4.StdIn; +import edu.princeton.cs.algs4.StdOut; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.TreeMap; + + /** + * For additional documentation, see + * Section 3.5 of + * Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne. + * + * @author Robert Sedgewick + * @author Kevin Wayne + * + * @param the generic type of keys in this symbol table + * @param the generic type of values in this symbol table + */ +public class ST, Value> implements Iterable { + + private TreeMap st; + + /** + * Initializes an empty symbol table. + */ + public ST() { + st = new TreeMap(); + } + + + /** + * Returns the value associated with the given key in this symbol table. + * + * @param key the key + * @return the value associated with the given key if the key is in this symbol table; + * {@code null} if the key is not in this symbol table + * @throws IllegalArgumentException if {@code key} is {@code null} + */ + public Value get(Key key) { + if (key == null) throw new IllegalArgumentException("calls get() with null key"); + return st.get(key); + } + + /** + * Inserts the specified key-value pair into the symbol table, overwriting the old + * value with the new value if the symbol table already contains the specified key. + * Deletes the specified key (and its associated value) from this symbol table + * if the specified value is {@code null}. + * + * @param key the key + * @param val the value + * @throws IllegalArgumentException if {@code key} is {@code null} + */ + public void put(Key key, Value val) { + if (key == null) throw new IllegalArgumentException("calls put() with null key"); + if (val == null) st.remove(key); + else st.put(key, val); + } + + /** + * Removes the specified key and its associated value from this symbol table + * (if the key is in this symbol table). + * This is equivalent to {@code remove()}, but we plan to deprecate {@code delete()}. + * + * @param key the key + * @throws IllegalArgumentException if {@code key} is {@code null} + */ + public void delete(Key key) { + if (key == null) throw new IllegalArgumentException("calls delete() with null key"); + st.remove(key); + } + + /** + * Removes the specified key and its associated value from this symbol table + * (if the key is in this symbol table). + * This is equivalent to {@code delete()}, but we plan to deprecate {@code delete()}. + * + * @param key the key + * @throws IllegalArgumentException if {@code key} is {@code null} + */ + public void remove(Key key) { + if (key == null) throw new IllegalArgumentException("calls remove() with null key"); + st.remove(key); + } + + /** + * Returns true if this symbol table contain the given key. + * + * @param key the key + * @return {@code true} if this symbol table contains {@code key} and + * {@code false} otherwise + * @throws IllegalArgumentException if {@code key} is {@code null} + */ + public boolean contains(Key key) { + if (key == null) throw new IllegalArgumentException("calls contains() with null key"); + return st.containsKey(key); + } + + /** + * Returns the number of key-value pairs in this symbol table. + * + * @return the number of key-value pairs in this symbol table + */ + public int size() { + return st.size(); + } + + /** + * Returns true if this symbol table is empty. + * + * @return {@code true} if this symbol table is empty and {@code false} otherwise + */ + public boolean isEmpty() { + return size() == 0; + } + + /** + * Returns all keys in this symbol table in ascending order, + * as an {@code Iterable}. + *

+ * To iterate over all of the keys in the symbol table named {@code st}, + * use the foreach notation: {@code for (Key key : st.keys())}. + * + * @return all keys in this symbol table in ascending order + */ + public Iterable keys() { + return st.keySet(); + } + + /** + * Returns all keys in this symbol table in ascending order. + * To iterate over all of the keys in a symbol table named {@code st}, use the + * foreach notation: {@code for (Key key : st)}. + *

+ * This method is provided for backward compatibility with the version from + * Introduction to Programming in Java: An Interdisciplinary Approach. + * + * @return all keys in this symbol table in ascending order + * @deprecated Replaced by {@link #keys()}. + */ + @Deprecated + public Iterator iterator() { + return st.keySet().iterator(); + } + + /** + * Returns the smallest key in this symbol table. + * + * @return the smallest key in this symbol table + * @throws NoSuchElementException if this symbol table is empty + */ + public Key min() { + if (isEmpty()) throw new NoSuchElementException("calls min() with empty symbol table"); + return st.firstKey(); + } + + /** + * Returns the largest key in this symbol table. + * + * @return the largest key in this symbol table + * @throws NoSuchElementException if this symbol table is empty + */ + public Key max() { + if (isEmpty()) throw new NoSuchElementException("calls max() with empty symbol table"); + return st.lastKey(); + } + + /** + * Returns the smallest key in this symbol table greater than or equal to {@code key}. + * + * @param key the key + * @return the smallest key in this symbol table greater than or equal to {@code key} + * @throws NoSuchElementException if there is no such key + * @throws IllegalArgumentException if {@code key} is {@code null} + */ + public Key ceiling(Key key) { + if (key == null) throw new IllegalArgumentException("argument to ceiling() is null"); + Key k = st.ceilingKey(key); + if (k == null) throw new NoSuchElementException("argument to ceiling() is too large"); + return k; + } + + /** + * Returns the largest key in this symbol table less than or equal to {@code key}. + * + * @param key the key + * @return the largest key in this symbol table less than or equal to {@code key} + * @throws NoSuchElementException if there is no such key + * @throws IllegalArgumentException if {@code key} is {@code null} + */ + public Key floor(Key key) { + if (key == null) throw new IllegalArgumentException("argument to floor() is null"); + Key k = st.floorKey(key); + if (k == null) throw new NoSuchElementException("argument to floor() is too small"); + return k; + } + + public static void main(String[] args) { + ST st = new ST(); + for (int i = 0; !StdIn.isEmpty(); i++) { + String key = StdIn.readString(); + st.put(key, i); + } + for (String s : st.keys()) + StdOut.println(s + " " + st.get(s)); + } +} diff --git a/graph-visualizer/resources/GraphInternet.txt b/graph-visualizer/resources/GraphInternet.txt new file mode 100644 index 0000000..e568317 --- /dev/null +++ b/graph-visualizer/resources/GraphInternet.txt @@ -0,0 +1,23 @@ +9 +21 +0 1 38 +0 3 48 +0 5 35 +0 8 40 +1 2 50 +1 3 36 +1 7 42 +1 8 48 +2 4 25 +2 5 40 +2 7 43 +2 8 30 +3 5 30 +3 6 65 +3 8 35 +4 5 20 +4 8 28 +5 8 27 +6 7 60 +6 8 55 +7 8 52