I am coding an A* algorithm and the algorithm needs a node class to access the nodes and a graph class to be able to draw the graph. The algorithm should be able to show the path from the starting node to the end node and should be able to know the matrix equivalent of it. Here is the code I currently have are:
A Star algorithm class:
import java.util.ArrayList;
import java.util.Comparator;
import java.util.PriorityQueue;
public class A_star extends Node {
public Node[][] searchArea;
public PriorityQueue<Node> openList;
public boolean[][] closedList;
public static Node startNode;
public static Node endNode;
public Node currentNode;
public Node prevNode;
public final int V_H_Cost = 2;
public final int DIAGONAL_COST = 3;
public A_star(Node[][] graph , Node startNode, Node endNode){
super();
searchArea = new Node[row][col];
this.closedList = new boolean[row][col];
this.openList = new PriorityQueue<Node>((Node n1, Node n2) -> {
return Integer.compare(n1.f, n2.f);
});
A_star.startNode = startNode;
A_star.endNode = endNode;
for(int i = 0; i < searchArea.length; i++){
for(int j = 0; j < searchArea[startNode.getRow()].length; j++){
searchArea[i][j] = new Node(i, j);
searchArea[i][j].calculateH(endNode);
searchArea[i][j].visited = false;
}
}
searchArea[startNode.getRow()][startNode.getCol()].f = 0;
for (int i = 0; i < graph.length; i++) {
addBlock(graph[i][0], graph[i][1]);
}
}
public void addBlock(Node i, Node j){
searchArea[i.getRow()][j.getCol()] = null;
}
public void updateCost(Node currentNode, Node t, int cost){
int tFinalCost = t.h + cost;
boolean isOpen = openList.contains(t);
if(!isOpen || tFinalCost < t.f){
t.f = tFinalCost;
t.prev = currentNode;
if(!isOpen)
openList.add(t);
}
}
public void findPath(Node startNode, Node endNode){
ArrayList<Node> path;
path = getPath(currentNode);
System.out.println("path");
for(int i = 0; i < path.size(); i++){
System.out.println(path.get(i));
}
startNode.setG(0);
startNode.calculateH(endNode);
startNode.calculateF();
openList.add(startNode);
while (true){
currentNode = openList.poll();
if(currentNode == null)
break;
closedList[currentNode.getRow()][currentNode.getCol()] = true;
if(currentNode.getRow() == endNode.getRow() && currentNode.getCol() == endNode.getCol())
return;
Node t;
if(currentNode.getRow() - 1 >= 0){
t = searchArea[currentNode.getRow()][currentNode.getCol()];
updateCost(currentNode, t,currentNode.f + V_H_Cost);
if(currentNode.getCol() - 1 >= 0){
t = searchArea[currentNode.getRow() - 1][currentNode.getCol() - 1];
updateCost(currentNode, t,currentNode.f + DIAGONAL_COST);
}
else if(currentNode.getCol() + 1 < searchArea[0].length){
t = searchArea[currentNode.getRow() - 1][currentNode.getCol() + 1];
updateCost(currentNode, t,currentNode.f + DIAGONAL_COST);
}
}
if(currentNode.getCol() - 1 >= 0){
t = searchArea[currentNode.getRow()][currentNode.getCol() - 1];
updateCost(currentNode, t,currentNode.f + V_H_Cost);
}
if(currentNode.getCol() + 1 < searchArea[0].length){
t = searchArea[currentNode.getRow()][currentNode.getCol() + 1];
updateCost(currentNode, t,currentNode.f + V_H_Cost);
}
if(currentNode.getRow() + 1 < searchArea[0].length) {
t = searchArea[currentNode.getRow() + 1][currentNode.getCol()];
updateCost(currentNode, t,currentNode.f + V_H_Cost);
if(currentNode.getCol() - 1 >= 0){
t = searchArea[currentNode.getRow() + 1][currentNode.getCol() - 1];
updateCost(currentNode, t,currentNode.f + DIAGONAL_COST);
}
else if (currentNode.getCol() + 1 < searchArea[0].length){
t = searchArea[currentNode.getRow() + 1][currentNode.getCol() + 1];
updateCost(currentNode, t,currentNode.f + DIAGONAL_COST);
}
}
}
}
public ArrayList<Node> getPath(Node currentNode){
ArrayList<Node> path = new ArrayList<>();
if(closedList[endNode.getRow()][endNode.getCol()]){
currentNode = searchArea[endNode.getRow()][endNode.getCol()];
System.out.print(currentNode);
searchArea[currentNode.row][currentNode.col].visited = true;
while(currentNode.prev != null){
System.out.println(currentNode.prev);
searchArea[currentNode.getRow()][currentNode.getCol()].visited = true;
currentNode = currentNode.prev;
}
path.add(currentNode);
}
else
System.out.println("No Possible Path");
return path;
}
static Node[][] graph = new Node[][] { { new Node(0, 0), new Node(2, 1), new Node(2,2), new Node(3, 3), new Node(0, 4) },
{ new Node(2, 5), new Node(0, 6), new Node(3, 7), new Node(2, 8), new Node(0, 9) },
{ new Node(2, 10), new Node(3, 11), new Node(0, 12), new Node(2, 13), new Node(0, 14)},
{ new Node(3, 15), new Node(2, 16), new Node(2, 17), new Node(0, 18), new Node(3, 19) },
{ new Node(0, 20), new Node(0, 21), new Node(0, 22), new Node(3, 23), new Node(0, 24) } };
//static Graph h = new Graph(graph);
public static void main(String[] args){
startNode = new Node(0, 0);
endNode = new Node(4, 4);
A_star A = new A_star(graph, startNode, endNode);
A.findPath(startNode, endNode);
A.getPath(startNode);
}
The Node class:
public class Node {
public Node prev, next;
public int g;
public int h;
public int f;
public boolean isBlock;
public int row, col;
static int id;
public boolean visited;
public Node(int i, int j) {
}
public Node getPrev(){
return prev;
}
public void setPrev(Node prev){
this.prev = prev;
}
public Node getNext(){
return next;
}
public void setNext(Node next){
this.next = next;
}
public Node(){
super();
row = 5;
col = 7;
this.id = id;
}
public int getID(){
return id;
}
public void setID(int n){
id = n;
}
public int getRow(){
return row;
}
public void setRow(int row){
this.row = row;
}
public int getCol(){
return col;
}
public void setCol(int col){
this.col = col;
}
public void calculateH(Node endNode){
this.h = Math.abs(endNode.row - this.row) + Math.abs(endNode.col - this.col);
}
public void calculateG(Node startNode){
this.g = Math.abs(startNode.row - this.row) + Math.abs(startNode.col - this.col);
}
public void calculateF(){
this.f = getH() + getH();
setF(f);
}
public int getH(){
return h;
}
public void setH(int h){
this.h = h;
}
public int getG(){
return g;
}
public void setG(int g){
this.g = g;
}
public int getF(){
return f;
}
public void setF(int f){
this.f = f;
}
public boolean isVisited() {
return visited;
}
public void setVisited(boolean visited) {
this.visited = visited;
}
public boolean isBlock(){
return isBlock;
}
public void setBlock(boolean isBlock){
this.isBlock = isBlock;
}
}
The graph class:
import java.util.*;
public class Graph extends Node {
LinkedList<Node> nodes; //adj list
ArrayList<LinkedList<Node>> adjList; //other adj list for bfs
int[][] matrix;//matrix to traverse throuhg
Node[] nodeMatrix; //to retrieve the nodes from
Node[][] adjMatrix; // I added this for Dijkstra
Set<Node> allNodes; //set of all nodes in the graph
public Graph(LinkedList<Node> adj, Set<Node> s) {
nodes = adj;
allNodes = s;
}
public Graph(int[][] m, Node[] n) {
matrix = m;
nodeMatrix = n;
}
public Graph(Node[][] g) {
adjMatrix = g;
}
public Graph() {
}
public Graph(ArrayList<LinkedList<Node>> a) {
adjList = a;
}
public ArrayList<LinkedList<Node>> getAdjList() {
return adjList;
}
}
The algorithm class currently does not print the path and I am confused why it does not print.
Feel free to code as much as possible.
Related
I'm trying to print all the word in my prefix tree. I can insert, it's working, but when I try to print all elements of the tree using a preorder way it just gets all messed up. There's some problem on the recursive method PREORDER that I'm using to display all elements.
How can I recursively display all the word on my prefix tree???
public class TrieMain {
public static void main(String[] args) {
TrieTree tree = new TrieTree();
tree.treeInsert("cat");
tree.treeInsert("cattle");
tree.treeInsert("hell");
tree.treeInsert("hello");
tree.treeInsert("rip");
tree.treeInsert("rap");
tree.preorder(tree.getRoot(), "");
}
}
public class TrieTree {
private TrieNode root;
private int wordCount;
public TrieTree() {
this.root = null;
this.wordCount = 0;
}
public TrieNode getRoot() {
return this.root;
}
public void setRoot(TrieNode newRoot) {
this.root = newRoot;
}
public int getWordCount() {
return this.wordCount;
}
public void preorder(TrieNode root, String prefix) {
if (root.getTerminal()) {
System.out.println(prefix);
}
for (int i = 0; i < 26; i++) {
if (root.getCharacters()[i] != '\u0000') {
prefix += root.getCharacters()[i];
preorder(root.getPointers()[i], prefix);
}
}
}
public boolean treeInsert(String word) {
if (this.root == null) {
this.root = new TrieNode();
}
TrieNode temp;
temp = this.root;
int lengthWord = word.length();
for (int i = 0; i < lengthWord; i++) {
int index = getIndex(word.charAt(i));
if (temp.getCharacters()[index] == '\u0000') {
temp.getCharacters()[index] = word.charAt(i);
temp.getPointers()[index] = new TrieNode();
}
temp = temp.getPointers()[index];
}
if (temp.getTerminal()) {
return false;
}
else {
temp.setTerminal(true);
return true;
}
}
public int getIndex(char character) {
int index = ((int) character) - 97;
return index;
}
}
public class TrieNode {
private final int NUM_CHARS = 26;
private char[] characters;
private TrieNode[] pointers;
private boolean terminal;
public TrieNode() {
this.characters = new char[this.NUM_CHARS];
this.pointers = new TrieNode[this.NUM_CHARS];
for (int i = 0; i < this.NUM_CHARS; i++) {
this.characters[i] = '\u0000';
this.pointers[i] = null;
}
this.terminal = false;
}
public char[] getCharacters() {
return this.characters;
}
public TrieNode[] getPointers() {
return this.pointers;
}
public boolean getTerminal() {
return this.terminal;
}
public void setTerminal(boolean newTerminal) {
this.terminal = newTerminal;
}
}
i have to code the Dijkstra algorithm. We got a blueprint for this project. Meaning we were told the classes, field variables and methods we have to use.
We have to read the adjacency matrix from a csv file and then use the Dijkstra algorithm.
My problem already begins in in filling the TreeSet edges...
The problem occurs in Graph.class on line 45 when i try to add the Edges.
Example for the csv :
;A;B;C;D;E;F;G;H
A;;1;3;1;;;;
B;1;;;;3;3;;
C;3;;;1;;;1;
D;1;;1;;1;;2;
E;;3;;1;;1;;5
F;;3;;;1;;;1
G;;;1;2;;;;1
H;;;;;5;1;1;
=>
A -> (B,1), (C,3), (D,1)
B -> (A,1), (E,3), (F,3)
C -> (A,3), (D,1), (G,1)
D -> (A,1), (C,1), (E,1), (G,2)
E -> (B,3), (D,1), (F,1), (H,5)
F -> (B,3), (E,1), (H,1)
G -> (C,1), (D,2), (H,1)
H -> (E,5), (F,1), (G,1)
Could somebody look where my problem is ? My indices are correct i checked them with some sout.
Just need help with filling in the TreeSet! I want to try the Dijkstra part myself.
public class Edge implements Comparable<Edge>{
private int distance;
private Node neighbour;
public Edge(int distance, Node neighbour) {
this.distance = distance;
this.neighbour = neighbour;
}
public int getDistance() {
return distance;
}
public void setDistance(int distance) {
this.distance = distance;
}
public Node getNeighbour() {
return neighbour;
}
public void setNeighbour(Node neighbour) {
this.neighbour = neighbour;
}
#Override
public int compareTo(Edge o) {
if (this.neighbour.getId().equals(o.neighbour.getId())){
return 0;
}else{
return -1;
}
}
}
import java.util.TreeSet;
public class Node {
private String id;
private TreeSet<Edge> edges;
private int distance;
private Node previous;
private boolean isVisited;
public Node(String id) {
this.id = id;
this.edges = new TreeSet<>();
}
public Node(String id, int distance){
this.id = id;
this.distance = distance;
}
#Override
public String toString() {
return "Node{" +
"id='" + id + '\'' +
", edges=" + edges +
", distance=" + distance +
", previous=" + previous +
", isVisited=" + isVisited +
'}';
}
public String getPath(){
return null;
}
public void addEdge(Edge e){
edges.add(e);
}
public void init(){
}
public void setStartNode(Node n){
}
public void visit(Node n){
}
public String getId() {
return id;
}
}
import java.io.File;
import java.io.FileNotFoundException;
import java.nio.file.Path;
import java.util.*;
public class Graph {
private PriorityQueue pq;
private ArrayList<Node> nodes;
public Graph(){
this.pq = new PriorityQueue();
this.nodes = new ArrayList();
}
public void readGraphFromAdjacencyMatrixFile(Path file) throws FileNotFoundException {
Scanner sc = new Scanner(new File(String.valueOf(file)));
ArrayList<String> s = new ArrayList<>();
ArrayList<Character> nodesCharacter = new ArrayList<Character>();
while (sc.hasNext()){
s.add(sc.next());
}
sc.close();
for(char ch: s.get(0).toCharArray()){
if (ch != ';' && ch != ',') {
nodes.add(new Node(Character.toString(ch)));
nodesCharacter.add(ch);
}
}
ArrayList<Node> nodes2 = getNodes();
String node = "";
int index = 0;
for (int i = 1; i < s.size(); i++){
int cnt = -2;
char[] chArray = s.get(i).toCharArray();
for (int j = 0; j < chArray.length; j++){
if(j == 0){
node = String.valueOf(chArray[j]);
index = indexOfNode(String.valueOf((chArray[j])));
}
else if (j >= 2){
if (Character.isDigit(chArray[j])){
int neighbourIndex = indexOfNode("" + nodesCharacter.get(cnt));
Edge e = new Edge(Character.getNumericValue(chArray[j]), nodes.get(neighbourIndex));
nodes.get(index).addEdge(e);
cnt--;
}
}
cnt ++;
}
}
}
public String getAllPAths(){
return null;
}
public void calcWithDijkstra(String startNodeId){
}
public ArrayList<Node> getNodes() {
return nodes;
}
public int indexOfNode(String id){
int cnt = 0;
for (int i = 0; i < nodes.size(); i++){
if (id.equals(nodes.get(i).getId())){
return cnt;
}
cnt++;
}
return -1;
}
}
I've created a Binary Search Tree in JaVa. Unfortunately 'delete' function doesn't work. I will be really appreciated if you could take a look. Thanks in advance..
Problem: I can't inorder print the tree after I delete a node from it.
Node:
class Node {
//Properties
private Node left, right, parent;
private int key;
//Getters and Setters
public Node(int key) {
this.key = key;
}
public int getKey() {
return key;
}
public void setKey(int key) {
this.key = key;
}
public Node getLeft() {
return left;
}
public void setLeft(Node left) {
this.left = left;
}
public Node getRight() {
return right;
}
public void setRight(Node right) {
this.right = right;
}
public Node getParent() {
return parent;
}
public void setParent(Node parent) {
this.parent = parent;
}
}
Binary Search Tree:
public class BinarySearchTree {
//Properties
private Node root;
//Getters and Setters
Node getRoot() {
return root;
}
public void setRoot(Node root) {
this.root = root;
}
//Search Method
public Node search(Node x, int k){
if (x == null || k==x.getKey()){
return x;
}
if (k<x.getKey()){
return search(x.getLeft(), k);
}
else{
return search(x.getRight(), k);
}
}
//Insertion Method
public void insert(Node z) {
Node y = null;
Node x = getRoot();
while (x != null) {
y = x;
if (z.getKey() < x.getKey()) {
x = x.getLeft();
} else {
x = x.getRight();
}
}
z.setParent(y);
if (y == null) {
setRoot(z);
} else if (z.getKey() < y.getKey()) {
y.setLeft(z);
} else {
y.setRight(z);
}
}
//Printer Method
public void inorder(Node x) {
if (x != null) {
inorder(x.getLeft());
System.out.print(x.getKey() + " ");
inorder(x.getRight());
}
}
//Transplant Method
public void transplant(Node u, Node v){
if (u.getParent() == null){
setRoot(v);
}
else if (u==u.getParent().getLeft()){
u.getParent().setLeft(v);
}
else{
u.getParent().setRight(v);
}
if (v!=null){
v.setParent(u.getParent());
}
}
//Deletion Method
public void delete(Node x) {
if (x.getLeft() == null) {
transplant(x, x.getRight());
} else if (x.getRight() == null) {
transplant(x, x.getLeft());
} else {
Node y = minimum(x.getRight());
if (y.getParent() != x) {
transplant(y, y.getRight());
y.setRight(x.getRight());
y.getRight().setParent(y);
}
transplant(x, y);
y.setLeft(x.getLeft());
y.getLeft().setParent(y);
}
}
//Maximum Finder
public Node maximum(Node x) {
while (x.getRight() != null) {
x = x.getRight();
}
return x;
}
//Minimum Finder
public Node minimum(Node x) {
while (x.getLeft() != null) {
x = x.getLeft();
}
return x;
}
//Example Tree Constructor
public void createBST(int[] a){
for (int i=0; i<a.length; i++){
Node nodeToBeAdded = new Node(a[i]);
insert(nodeToBeAdded);
}
inorder(root);
}
}
and a Test class:
public class Test {
public static void main(String[] args) {
//CREATION
System.out.println("CREATION");
BinarySearchTree tree = new BinarySearchTree();
int[] a = {54, 32, 76, 7, 44, 63, 99};
tree.createBST(a);
System.out.println();
System.out.print("The root of the tree is: ");
System.out.println();
System.out.print("Maximum Node is: ");
tree.inorder(tree.maximum(tree.getRoot()));
System.out.println();
System.out.print("Minimum Node is: ");
tree.inorder(tree.minimum(tree.getRoot()));
System.out.println();
//INSERTION
System.out.println("INSERTION");
tree.insert(new Node(25));
tree.inorder(tree.getRoot());
tree.insert(new Node(485));
System.out.println();
tree.inorder(tree.getRoot());
tree.insert(new Node(12));
System.out.println();
tree.inorder(tree.getRoot());
tree.insert(new Node(5));
System.out.println();
tree.inorder(tree.getRoot());
tree.insert(new Node(9985));
System.out.println();
tree.inorder(tree.getRoot());
System.out.println();
System.out.print("Maximum Node is: ");
tree.inorder(tree.maximum(tree.getRoot()));
System.out.println();
System.out.print("Minimum Node is: ");
tree.inorder(tree.minimum(tree.getRoot()));
System.out.println();
//SEARCH
System.out.println("SEARCH");
tree.inorder(tree.search(tree.getRoot(), 32));
System.out.println();
//DELETION
System.out.println("DELETION");
tree.delete(new Node(5));
tree.inorder(tree.getRoot());
}
}
As i can see you don't override equals/hashCode methods so you can't find Node(5) because you created new instance. If you change your code in Test.java:
tree.insert(new Node(12));
System.out.println();
tree.inorder(tree.getRoot());
// Start changes
Node node5 = new Node(5);
tree.insert(node5);
System.out.println();
tree.inorder(tree.getRoot());
// End changes
tree.insert(new Node(9985));
// -cut some code
//DELETION
System.out.println("DELETION");
tree.delete(node5);
System.out.println();
tree.inorder(tree.getRoot());
it will print result
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;
}
public class LinkedList
{
private Node head;
private Node tail;
private int numberOfElements;
public LinkedList()
{
head = null;
tail = null;
this.numberOfElements = 0;
}
public int length()
{
return this.numberOfElements;
}
public void removeFront()
{
Node currNode = head;
head = head.getNextNode();
currNode.setNextNode(null);
this.numberOfElements--;
}
public void removeLast()
{
this.tail = this.tail.prev;
}
public void removeAtIndex(int index) throws AmishException
{
if (index == 0) {
Node q = head;
head = q.getNextNode();
}
else if ((index > numberOfElements - 1) || (index < 0))
System.out.println("Index out bounds.");
else {
Node currNode = head;
for (int i = 0; i < index; i++) {
currNode = currNode.getNextNode();
}
Node temp = currNode;
currNode = temp.getPrevNode();
currNode.setNextNode(temp.getNextNode());
temp = null;
numberOfElements--;
}
}
Node -
public class Node
{
private int payload;
private Node nextNode;
public Node prev;
public Node previous;
public Node next;
public Node(int payload)
{
this.payload = payload;
nextNode = null;
}
public Node getNextNode()
{
return this.nextNode;
}
public Node getPrevNode()
{
return this.getPrevNode();
}
public void setNextNode(Node n)
{
this.nextNode = n;
}
public void display()
{
System.out.print("(" + super.toString() + " : " + this.payload + ")");
if(this.nextNode != null)
{
System.out.print(" -> ");
this.nextNode.display();
}
else
{
System.out.println("");
}
}
public String toString()
{
return "" + super.toString() + " : " + this.payload;
}
public void setPrevNode(Node n)
{
previous = n;
}
}
Driver -
public class Driver
{
public static void main(String[] args) throws Exception
{
LinkedList ll = new LinkedList();
ll.addFront(7);
ll.addFront(5);
ll.addEnd(13);
ll.addEnd(27);
ll.addFront(2);
ll.addAtIndex(1, 0);
ll.addAtIndex(12, 6);
ll.addAtIndex(9, 2);
ll.addAtIndex(11, 2);
//ll.removeFront();
//ll.removeLast();
ll.removeAtIndex(1);
for(int i = 0; i < ll.length(); i++)
{
System.out.println(ll.get(i));
}
}
}
I got what I need to remove the head's index, but how to do anything else is beyond me.
I have the methods to remove the head and the tail now I just need to know how to remove at an index just Like if I were to add at an index.
Okay, completely editing this answer. I took your code and went from that. There were some issues with your Node class, check out mine. I created a barebones Node class, add the any other functionality you may need/want. For the LinkedList class, I created a simple add method that adds to the end of the list. Use this as a prototype for your other adds. Everything right now is working and I put some println's to help you see where the program is at. I highly recommend using a debugger. Also note that this is a doubly linked list.
Linked List
public class LinkedList {
private Node head;
private Node tail;
private int numberOfElements;
public LinkedList()
{
head = null;
tail = null;
numberOfElements = 0;
}
public int length()
{
return numberOfElements;
}
public void removeAtIndex(int index)
{
if (index == 0) {
Node q = head;
head = q.getNextNode();
numberOfElements--;
}
else if ((index > numberOfElements - 1) || (index < 0))
System.out.println("Index out of bounds.");
else {
Node currNode = head;
for (int i = 0; i < index; i++) {
//Node p = currNode;
System.out.println("At this payload " + currNode.getPayload());
currNode = currNode.getNextNode();
System.out.println("Now at this payload " + currNode.getPayload());
}
Node temp = currNode;
System.out.println("Removing the node with payload " + temp.getPayload());
currNode = temp.getPrevNode();
currNode.setNextNode(temp.getNextNode());
temp = null;
numberOfElements--;
}
}
public void add(int num) {
Node newNode = new Node(num);
newNode.setNextNode(null);
if (numberOfElements == 0) {
newNode.setPrevNode(null);
head = newNode;
tail = newNode;
}
else if (numberOfElements == 1) {
head.setNextNode(newNode);
tail = newNode;
tail.setPrevNode(head);
}
else {
newNode.setPrevNode(tail);
tail.setNextNode(newNode);
tail = newNode;
}
System.out.println("Inserted " + num + " into the linked list");
numberOfElements++;
}
public void printList() {
Node temp = head;
while (temp != null) {
System.out.println("Node with payload " + temp.getPayload());
temp = temp.getNextNode();
}
}
}
Node
public class Node {
private int payload;
private Node next;
private Node prev;
public Node(int payload) {
this.payload = payload;
prev = null;
next = null;
}
public Node getNextNode() {
return next;
}
public Node getPrevNode() {
return prev;
}
public void setNextNode(Node n) {
next = n;
}
public void setPrevNode(Node n) {
prev = n;
}
public int getPayload() {
return payload;
}
}
Driver
public class Driver {
public static void main(String[] args) {
LinkedList ll = new LinkedList();
ll.add(7);
ll.add(5);
ll.add(13);
ll.add(27);
ll.add(2);
ll.printList();
ll.removeAtIndex(3);
ll.printList();
}
}