Use a specific object-property to index, using a Map structure - java

I'd like to use the integer-id-value of my vertex-class as an index, in my Map-structure, without using a parallel data structure.
class Vertex {
private int v;
private int label;
//...
}
I store vertex objects, in a Map<Vertex,ArrayList<Edge>> adjMap.
Is it possible use the v-property of my Vertex class, as an index-key in my Map?

It depends on the Map implementation you are using. For example, for a HashMap you can override equals and hashCode of your Vertex class so that two vertices will be considered equal if their v properties are equal.
class Vertex {
private int v;
private int label;
public Vertex (int v)
{
this.v = v;
}
#Override
public boolean equals (Object o)
{
if (!(o instanceof Vertex))
return false;
Vertex ov = (Vertex)o;
return this.v == ov.v;
}
#Override
public int hashCode ()
{
return v;
}
}
Now, to locate the value for a given v value in your Map :
adjMap.containKey(new Vertex(v));

Ok. Then your equals and hashcode should only use property v. Code below:
public class Vertex {
private int v;
private int label;
public static void main(String[] args) {
Map<Vertex, String> map = new HashMap<Vertex, String>();
Vertex vertex = new Vertex();
vertex.v = 5;
vertex.label = 10;
map.put(vertex, "vertex");
Vertex vertex2 = new Vertex();
vertex2.v = 5;
vertex2.label = 100;
System.out.println("Value:: "+ map.get(vertex2));
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + v;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Vertex other = (Vertex) obj;
if (v != other.v)
return false;
return true;
}
}
Output: Value:: vertex

Related

Find the maximum ratio between the number of nodes in a binary tree

I wrote a class that defines some operations on binary trees.
Now I have to add a method that returns a reference to the node (or to one of the nodes, if there are more than one) U such that the ratio between the number of nodes in the subtree of the root U (thus including the node itself) and height (+1) of the same is maximized.
So I have to add to the sum the value 1 for the leaves otherwise the ratio would be 1/0 = infinity: that is, the result would be any leaf (wrong).
The algorithm must be linear in the number of nodes, visiting the tree once.
Can I define a private class auxiliary in case I need it.
I do not know how to do, someone help me?
My code is this.
public class BinaryTree {
protected class Node {
protected Integer element;
protected Node left;
protected Node right;
Node(int element) {
this.element = element;
left = right = null;
}
Node(int element, Node left, Node right) {
this.element = element;
this.left = left;
this.right = right;
}
boolean isLeaf() {
return left == null && right == null;
}
} //end Node class
public class NodeReference {
private Node node;
private NodeReference(Node node) {
this.node = node;
}
public int getElement() {
return node.element;
}
public void setElement(int e) {
node.element = e;
}
} //end class NodeReference
protected Node root;
public BinaryTree() {
root = null;
}
public boolean isEmpty() {
return root == null;
}
public void add(int element, String path) {
//working properly
}
protected Node add(int elem, String path, Node node) {
//working properly
}
public void printPreOrder() {
//working properly
}
protected void printPreOrder(Node node) {
//working properly
}
public int height() {
//working properly
}
protected int height(Node node) {
//working properly
}
public int sum() {
//working properly
}
private int sum(Node node) {
//working properly
}
public int size() {
//working properly
}
private int size(Node node) {
//working properly
}
public boolean search(int x) {
//working properly
}
protected boolean search(int x, Node node) {
//working properly
}
public boolean equalTo(BinaryTree t) {
//working properly
}
public boolean equals(Object ob) {
//working properly
}
protected boolean areEqual(Node node1, Node node2) {
//working properly
}
public BinaryTree copy() {
//working properly
}
protected Node copy(Node node) {
//working properly
}
public NodeReference find(int x) {
//working properly
}
private Node find(int x, Node nd) {
//working properly
}
public boolean isCompletelyBalanced() {
//working properly
}
private int isCompletelyBalanced(Node node) {
//working properly
}
public boolean is1Balanced() {
//working properly
}
private int is1Balanced(Node node) {
//working properly
}
private class BoolNode {
boolean found;
Node node;
BoolNode(boolean found, Node node) {
this.found = found;
this.node = node;
}
}
public boolean removeSubtree(int x) {
//working properly
}
protected BoolNode removeSubtree(int x, Node node) {
//working properly
}
public int maxElem() throws IllegalStateException {
if(root == null)
throw new IllegalStateException("Empty tree.");
return maxElem(root);
}
private static int max3(int x, int y, int z) {
return max(x, max(y, z));
}
private int maxElem(Node node) {
int max = node.element;
if(node.left != null)
max = Math.max(max, maxElem(node.left));
if(node.right != null)
max = Math.max(max, maxElem(node.right));
return max;
}
public NodeReference maxDescendantsHeightRatio() {
//As I write this method?
}
}
I started doing it this way:
public NodeReference maxDescendantsHeightRatio() {
ArrayList<Node> list = iteratorPreOrder();
ArrayList<NodeWithRatio> listRatio = new ArrayList<NodeWithRatio>();
for(int i = 0; i < list.size(); i++) {
int s = size();
int h = height() + 1;
int r = ratioScore(s, h);
listRatio.add(new NodeWithRatio(this, r));
}
//sort the array list
Collections.sort(listRatio, new Comparator<Point>() {
public int compare(NodeWithRatio o1, NodeWithRatio o2) {
return Integer.compare(o1.ratio, o2.ratio);
}
});
//find max value in the list of node with ratio
NodeWithRatio result = listRatio.get(listRatio.size() - 1); //gets the last item, largest for an ascending sort
return result.node;
//return null;
}
private int ratioScore(int size, int height) {
return size / height;
}
private class NodeWithRatio {
Node node;
int ratio;
public NodeWithRatio(Node n, int r) {
node = n;
ratio = r;
}
} //end NodeWithRatio class
public ArrayList<Node> iteratorPreOrder() {
ArrayList<Node> templist = new ArrayList<Node>();
preorder(root, templist);
for(int i = 0; i < templist.size(); i++)
System.out.println(templist.get(i).element);
return templist;
}
private void preorder(Node node, ArrayList<Node> templist) {
if(node != null) {
templist.add(node); // adds to end of list.
preorder(node.left, templist);
preorder(node.right, templist);
}
}
public int height() {
if(isEmpty())
return -1;
return height(root);
}
protected int height(Node node) {
return (node == null)? -1: 1 + Math.max(height(node.left), height(node.right));
}
public int size() {
if(isEmpty())
return 0;
return size(root);
}
private int size(Node node) {
if(node == null)
return 0;
return size(node.left) + size(node.right) + 1;
}
I think it's the wrong piece of code:
for(int i = 0; i < list.size(); i++) {
int s = size();
int h = height() + 1;
int r = ratioScore(s, h);
listRatio.add(new NodeWithRatio(this, r));
}
Since it is not recursive, but I do not know how to fix it ...
Does anyone have any advice?
Thanks!
As you figured out, the calculation of the ratio is a combination of the calculation of the size and height of the tree.
In order to find the max ratio in one pass over the nodes of the tree, we can use a recursive method that would calculate both the size and height of the tree. In order to calculate the ratio for a node, it's not enough to know the ratios of its two children - we need to know the size and height of the children's sub trees. For this purpose I'll return an array of two ints - the first is the size and the second the height.
public int[] ratio(Node node)
{
int[] result = new int[2];
int[0] = 0;
int[1] = 0;
if (node = null)
return result;
int[] leftRatio = ratio(node.left);
int[] rightRatio = ratio(node.right);
result[0] = leftRatio[0] + rightRatio[0] + 1; // current sub tree size
result[1] = Math.max(leftRatio[1] + rightRatio[1]) + 1; // current sub tree height
return result;
}
Now, if you want to find all the nodes with the highest ratio, you can add a static variable holding the current max ratio and another static variable holding the nodes having that max ratio (I know, it's ugly, but it works).
...
static float maxRatio = 0;
static Set<Node> maxRatioNodes = new Set<Node>();
...
public int[] ratio(Node node)
{
int[] result = new int[2];
int[0] = 0;
int[1] = 0;
if (node = null)
return result;
int[] leftRatio = ratio(node.left);
int[] rightRatio = ratio(node.right);
result[0] = leftRatio[0] + rightRatio[0] + 1; // current sub tree size
result[1] = Math.max(leftRatio[1] + rightRatio[1]) + 1; // current sub tree height
float currRatio = result[0]/result[1];
if (currRatio > maxRatio) { // found a new max ratio
maxRatio = currRatio;
maxRatioNodes.clear();
maxRatioNodes.add (node);
} else if (currRatio == maxRatio) { // node's ratio equals the current max ratio
maxRatioNodes.add (node);
}
return result;
}

mostFrequent method bags adt(abstract data types)

I am trying to implement a method named mostFrequent in a bag that finds the most frequent object in a bag For example, if B = {Bob, Joe, Bob, Ned, Bob, Bob}, then the method
returns Bob. Hint: The method is O(n^2).
public E MostFrequent (Bag<E> B){
// implementation here
}
The adt of the bag is the following:
package edu.uprm.ece.icom4035.bag;
import java.util.Iterator;
import java.util.NoSuchElementException;
public class StaticBag implements Bag {
private int currentSize;
private Object elements[];
private class BagIterator implements Iterator {
private int currentPosition;
public BagIterator(){
this.currentPosition = 0;
}
#Override
public boolean hasNext() {
return this.currentPosition < currentSize;
}
#Override
public Object next() {
if (hasNext()){
return elements[this.currentPosition++];
}
else {
throw new NoSuchElementException();
}
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
}
public StaticBag(int maxSize){
if (maxSize < 1){
throw new IllegalArgumentException("Max size must be at least 1.");
}
this.currentSize = 0;
this.elements = new Object[maxSize];
}
#Override
public void add(Object obj) {
if (obj == null){
throw new IllegalArgumentException("Value cannot be null.");
}
else if (this.size() == this.elements.length){
throw new IllegalStateException("Bag is full.");
}
else {
this.elements[this.currentSize++] = obj;
}
}
#Override
public boolean erase(Object obj) {
int target = -1;
for (int i=0; i < this.size(); ++i){
if (this.elements[i].equals(obj)){
target = i;
break;
}
}
if (target == -1){
return false;
}
else {
this.elements[target] = this.elements[this.currentSize-1];
this.elements[this.currentSize-1] = null;
this.currentSize--;
return true;
}
}
#Override
public int eraseAll(Object obj) {
int copies = 0;
while(this.erase(obj)){
copies++;
}
return copies;
}
#Override
public int count(Object obj) {
int counter = 0;
for (int i=0; i < this.size(); ++i){
if (elements[i].equals(obj)){
counter++;
}
}
return counter;
}
#Override
public void clear() {
for (int i=0; i < this.size(); ++i){
this.elements[i] = null;
}
this.currentSize = 0;
}
#Override
public boolean isEmpty() {
return this.size() == 0;
}
#Override
public int size() {
return this.currentSize;
}
#Override
public boolean isMember(Object obj) {
return this.count(obj) > 0;
}
#Override
public Iterator iterator() {
return new BagIterator();
}
}
the method must be implemented in the most efficient way and if possible using the methods already given in the bag adt
What I've been trying is the following:
public E MostFrequent(Bag<E> B){
for(E e : B){
int counter = B.count(e)
}
}
but I don't seem to think of a way to return the object with more frequencies inside the loop

JTree child nodes with same bounds

I have a JTree with a custom model and custom renderer. They seem to work fine, except that when I expand a node that has multiple child nodes, it draws all child nodes to the same rectangle so only the last node is visible. I can iterate through the child nodes and I can print them to the console, but the UI is different.
This is a sketch of the UI:
// for 1 child node:
ROOT
-- <rendered node>
//for 2 child nodes:
ROOT
|
-- <rendered node - the data of the 2nd node>
//for 3 child nodes:
ROOT
|
|
-- <rendered node - the data of the 3rd node>
I figured out that the BasicTreeUI uses getPathBounds() to determine the bounds of a certain node. Here is how I check it:
doStuffWithTree(JTree tree) {
tree.expandNode(0);
for (int i = 0; i < tree.getRowCount(); i++) {
TreePath tp = tree.getPathForRow(i);
tree.makeVisible(tp);
System.out.println("Bounds of row " + i + ": " + tree.getPathBounds(tp));
}
}
With this check I get that all the nodes - except the node 0 - have the same bounds.
I tried a few tricks with expanding the tree, e.g. expanding all nodes starting from the first; then starting from the last - they all have the same effect.
Finally, the question: what class could I modify to fix this behavior? Are there any known workarounds?
UPDATE
Apparently, something needs to be fixed on the TreeNode implementation. Also, I need to correct myself: I didn't have a custom model, but a cusomtom TreeNode. Here is the SSCCE:
package com.example.jtree;
//lots of obvious imports
public class JTreeBoundsExample extends JFrame {
public static void main(String... args) {
JTreeBoundsExample m = new JTreeBoundsExample();
m.setSize(275, 300);
m.setDefaultCloseOperation(EXIT_ON_CLOSE);
m.setVisible(true);
}
public JTreeBoundsExample() {
ValueTreeNode root = new ValueTreeNode(null, "root");
ValueTreeNode category = new ValueTreeNode(root, "category");
category.put("k1", new ValueTreeNode(category, "v1"));
category.put("k2", new ValueTreeNode(category, "v2"));
category.put("k3", new ValueTreeNode(category, "v3"));
root.put("category", category);
JTree tree = new JTree(root);
tree.setCellRenderer(new ValueCellRenderer());
tree.setRootVisible(false);
tree.expandRow(0);
for (int i = 0; i < tree.getRowCount(); i++) {
TreePath tp = tree.getPathForRow(i);
tree.makeVisible(tp);
System.out.println("Bounds of row " + i + ": " + tree.getPathBounds(tp));
}
Container content = getContentPane();
content.add(new JScrollPane(tree), BorderLayout.CENTER);
}
private static class ValueTreeNode extends HashMap<String, ValueTreeNode> implements TreeNode {
private List<String> keys = new ArrayList<String>();
private TreeNode parent;
private String value;
public ValueTreeNode(TreeNode parent, String value) {
this.parent = parent;
this.value = value;
}
#Override
public ValueTreeNode put(String key, ValueTreeNode val) {
ValueTreeNode old = super.put(key, val);
if (old == null) {
sortKeys();
}
return old;
}
private void sortKeys() {
keys.clear();
keys.addAll(keySet());
Collections.sort(keys);
}
#Override
public Enumeration children() {
final Iterator<String> it = keys.iterator();
return new Enumeration() {
#Override
public boolean hasMoreElements() {
return it.hasNext();
}
#Override
public Object nextElement() {
return it.next();
}
};
}
#Override
public boolean getAllowsChildren() {
return true;
}
#Override
public TreeNode getChildAt(int pos) {
return get(keys.get(pos));
}
#Override
public int getChildCount() {
return size();
}
#Override
public int getIndex(TreeNode arg0) {
return -1;
}
#Override
public TreeNode getParent() {
return parent;
}
#Override
public boolean isLeaf() {
return size() == 0;
}
}
private static class ValueCellRenderer extends DefaultTreeCellRenderer {
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded,
boolean leaf, int row, boolean hasFocus) {
super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
if (value instanceof ValueTreeNode) {
ValueTreeNode vtn = (ValueTreeNode) value;
setText(vtn.value);
}
return this;
}
}
}

How to delete a specific element from a priority queue?

I have created a priority queue using the Java API and I want to remove a specific element from the priority queue at the end of the program. I know it has to do something with the comparator but I can't figure it out. Can someone help? Here's my code:
public static void main(String[] args)
{
PriorityQueue<Element> X = new PriorityQueue<Element>(100, new ElementComparator());
X.add(new Element(30, 3));
X.add(new Element(700, 4.5));
X.add(new Element(100, 6.2));
X.add(new Element(2, 8.1));
System.out.println(X.remove(new Element(100, 6.2)));
}
and here's my Element class:
private int index;
private double value;
public Element(int i, double v)
{
index = i;
value = v;
}
public int getIndex() { return index;};
public double getValue() { return value;};
public void setValue(double v) { value = v;};
And here's the comparator that I created:
public int compare(Element o1, Element o2)
{
int idx1 = o1.getIndex();
int idx2 = o2.getIndex();
if (idx1 < idx2) {
return -1;
} else if (idx1 > idx2) {
return 1;
} else {
return 0;
}
}
public boolean equals(Element o1, Element o2)
{
return o1.getIndex() == o2.getIndex();
}
I appreciate your help...
You need to define equals() and hashcode() on your Element object as such:
public class Element{
private int index;
private double value;
public Element(int i, double v)
{
index = i;
value = v;
}
public int getIndex() { return index;}
public double getValue() { return value;}
public void setValue(double v) { value = v;}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Element)) return false;
Element element = (Element) o;
if (index != element.index) return false;
return true;
}
#Override
public int hashCode() {
return index;
}
}
Defining equals() on the ElementComparator does not perform the same task.

How To Create A Java Graph File from .txt file

I am trying to create a graph file .I have to read in values from a .gra file(which I think is a .txt file).We were told to tokenise lines based on a space in the format <vertex> <name> <x-coord> <y-coord>,same for edge
I had a look at a couple of related questions,but still cant find the answer.
Here's the code I was given:
public EdgeListVertex(V element) {
this.element = element;
}
#Override
public V element() {
return element;
}
public String toString() {
return element.toString();
}
}
private class EdgeListEdge implements Edge<E> {
Position<EdgeListEdge> position;
E element;
EdgeListVertex start, end;
public EdgeListEdge(EdgeListVertex start, EdgeListVertex end, E element) {
this.start = start;
this.end = end;
this.element = element;
}
#Override
public E element() {
return element;
}
public String toString() {
return element.toString();
}
}
private List<EdgeListVertex> vertices;
private List<EdgeListEdge> edges;
public EdgeListGraph() {
vertices = new LinkedList<EdgeListVertex>();
edges = new LinkedList<EdgeListEdge>();
}
#SuppressWarnings("unchecked")
#Override
public Vertex<V>[] endVertices(Edge<E> e) {
EdgeListEdge edge = (EdgeListEdge) e;
Vertex<V>[] endpoints = (Vertex<V>[]) new Vertex[2];
endpoints[0] = edge.start;
endpoints[1] = edge.end;
return endpoints;
}
#Override
public Vertex<V> opposite(Vertex<V> v, Edge<E> e) {
Vertex<V>[] endpoints = endVertices(e);
if (endpoints[0].equals(v)) {
return endpoints[1];
} else if (endpoints[1].equals(v)) {
return endpoints[0];
}
throw new InvalidVertexException();
}
#Override
public boolean areAdjacent(Vertex<V> v, Vertex<V> w) {
for (EdgeListEdge edge: edges) {
if ((edge.start.equals(v)) && (edge.end.equals(w))) return true;
if ((edge.end.equals(v)) && (edge.start.equals(w))) return true;
}
return false;
}
#Override
public V replace(Vertex<V> v, V x) {
EdgeListVertex vertex = (EdgeListVertex) v;
V temp = vertex.element;
vertex.element = x;
return temp;
}
#Override
public E replace(Edge<E> e, E x) {
EdgeListEdge edge = (EdgeListEdge) e;
E temp = edge.element;
edge.element = x;
return temp;
}
#Override
public Vertex<V> insertVertex(V v) {
EdgeListVertex vertex = new EdgeListVertex(v);
Position<EdgeListVertex> position = vertices.insertLast(vertex);
vertex.position = position;
return vertex;
}
#Override
public Edge<E> insertEdge(Vertex<V> v, Vertex<V> w, E o) {
EdgeListEdge edge = new EdgeListEdge((EdgeListVertex) v, (EdgeListVertex) w, o);
Position<EdgeListEdge> position = edges.insertLast(edge);
edge.position = position;
return edge;
}
#Override
public V removeVertex(Vertex<V> v) {
Iterator<Edge<E>> it = incidentEdges(v).iterator();
while (it.hasNext()) it.remove();
EdgeListVertex vertex = (EdgeListVertex) v;
vertices.remove(vertex.position);
return vertex.element;
}
#Override
public E removeEdge(Edge<E> e) {
EdgeListEdge edge = (EdgeListEdge) e;
edges.remove(edge.position);
return edge.element;
}
#Override
public List<Edge<E>> incidentEdges(Vertex<V> v) {
LinkedList<Edge<E>> list = new LinkedList<Edge<E>>();
for (EdgeListEdge edge : edges) {
if (edge.start.equals(v)) list.insertLast(edge);
if (edge.end.equals(v)) list.insertLast(edge);
}
return list;
}
#Override
public List<Vertex<V>> vertices() {
LinkedList<Vertex<V>> list = new LinkedList<Vertex<V>>();
for (EdgeListVertex vertex : vertices) {
list.insertLast(vertex);
}
return list;
}
#Override
public List<Edge<E>> edges() {
LinkedList<Edge<E>> list = new LinkedList<Edge<E>>();
for (EdgeListEdge edge : edges) {
list.insertLast(edge);
}
return list;
}
}
Any tips?
A good approach might be to create a new class with fields for vertex, name and coordinates. Then read in the data from a scanner into an ArrayList of the class you just created. After this, you could just pass the ArrayList into whatever you are using for graphing (which might require a few tweaks).
Example scanner code (untested):
File graphFile = new File(filepath);
Scanner graphScanner = new Scanner(graphFile);
Then, to read from the scanner (untested):
ArrayList<graphClass> dataPoints = new ArrayList<graphClass>(); //you will have to make graphClass
while(graphScanner.hasNextLine()) {
dataPoints.add(new graphClass(graphScanner.nextDouble(), graphScanner.next(), graphScanner.nextDouble(), graphScanner.nextDouble()); //assuming constructor of graphClass takes vertex, name, x, y in that order
I hope this helps.

Categories