Java: Trouble when using BFS to find a shortest path - java

Class State :
import java.util.Arrays;
public class State {
private int data[][];
public int[][] getData() {
return data;
}
public void setData(int[][] data) {
this.data = data;
}
public void swap(int row1, int col1, int row2, int col2){
int temp = this.data[row1][col1];
this.data[row1][col1] = this.data[row2][col2];
this.data[row2][col2] = temp;
}
public State copyState() {
int height = this.data.length;
int width = this.data[0].length;
int[][] temp = new int[height][width];
for (int i = 0; i < height; i++) {
for(int j=0; j< width; j++){
temp[i][j] = this.data[i][j];
}
}
State target = new State(temp);
return target;
}
public State(int[][] data) {
super();
this.data = data;
}
}
Class Node :
public class Node {
private State state;
private Node parent;
private ArrayList<Node> children;
public Node(State state){
this.state = state;
parent = null;
children = new ArrayList<>();
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public Node getParent() {
return parent;
}
public void setParent(Node parent) {
this.parent = parent;
}
public ArrayList<Node> getChildren() {
return children;
}
public void addChild(Node node){
node.setParent(this);
this.children.add(node);
}
public ArrayList<Node> returnSuccessor(){ // generate all possible moves(has been tested - work well)
ArrayList<Node> result = new ArrayList<>();
int[][] matrix = this.getState().getData();
int row = matrix.length;
int col = matrix[0].length;
int rowX = 0;
int colX = 0;
for(int i=0; i<row; i++){
for(int j=0; j<col; j++){
if ( matrix[i][j] == 0) {
rowX = i;
colX = j;
}
}
}
if( (colX-1) >= 0 ){
State temp = this.getState().copyState();
temp.swap(rowX, colX, rowX, colX-1);
Node left = new Node(temp);
result.add(left);
}
if ( (colX+1) < col ){
State temp = this.getState().copyState();
temp.swap(rowX, colX, rowX, colX+1);
Node right = new Node(temp);
result.add(right);
}
if ( (rowX-1) >= 0 ){
State temp = this.getState().copyState();
temp.swap(rowX, colX, rowX-1, colX);
Node top = new Node(temp);
result.add(top);
}
if ( (rowX+1) < row ){
State temp = this.getState().copyState();
temp.swap(rowX, colX, rowX+1, colX);
Node down = new Node(temp);
result.add(down);
}
return result;
}
public void printState(){
System.out.println(Arrays.deepToString(this.getState().getData()));
}
public boolean equal(Node node){ // check whether 2 nodes are the same
return Arrays.deepEquals(this.getState().getData(), node.getState().getData());
}
public boolean checkTree(Node node){ // check whether a node has been added into the tree or not
if (this.equal(node)) {
return true;
}
ArrayList<Node> children = this.getChildren();
boolean result = false;
if (children.size() > 0){
for(int i=0; result == false && i< children.size(); i++){
result = children.get(i).checkTree(node);
}
}
return result;
}
}
Class main :
public class main {
public static void BFS(Node root, Node goal) throws InterruptedException{
Queue<Node> queue = new LinkedList<Node>();
queue.add(root);
while(queue.size()>0){
Node temp = queue.poll();
if (temp.equal(goal)) {
goal.setParent(temp.getParent());
break;
}
else{
ArrayList<Node> successor = temp.returnSuccessor();
for(int i=0; i< successor.size(); i++){
boolean check = root.checkTree(successor.get(i));
if (check == false){
queue.add(successor.get(i));
temp.addChild(successor.get(i));
}
}
}
}
}
public static void main(String[] args) throws InterruptedException {
int[][] initialState = { {2,1}, {3,0} };
int[][] goalState = { {0,1}, {2,3} };
Node root = new Node(new State(initialState));
Node goal = new Node(new State(goalState));
BFS(root,goal);
Node temp = goal;
if(temp.getParent() == null){
System.out.println("There is no such a way to go from the initial state to the goal state");
}
else{
ArrayList<Node> listSteps = new ArrayList<>();
while(temp != null){
listSteps.add(temp);
temp = temp.getParent();
}
for (int i=listSteps.size()-1; i>=0; i--){
listSteps.get(i).printState();
Thread.sleep(1000);
}
int numSteps = listSteps.size()-1;
System.out.println("Number of steps: " + numSteps);
}
}
I want to find a shortest path from the initial state to goal state ( nearly the same as n-puzzle game )
When i try running my program with 2x2 size puzzle as an input, it works well.
For example with input :
int[][] initialState = { {2,1}, {3,0} };
int[][] goalState = { {0,1}, {2,3} };
The result will be:
[[2, 1], [3, 0]]
[[2, 1], [0, 3]]
[[0, 1], [2, 3]]
Number of steps: 2
However, it has an infinite loop with nxn size(n>2)
Sample input:
int[][] initialState = { {7,2,4}, {5,0,6}, {8,3,1} };
int[][] goalState = { {0,1,2}, {3,4,5}, {6,7,8} };
It keeps adding nodes into the queue in DFS method
It makes me confused because the method checkTree in class Node has been written with the purpose to avoid loops which may happen when generate the states.
Can somebody figure out what my mistake is?

Late answer, but I hope it helps someone:
The basic issue in the code posted are these lines :
for(int i=0; i<row; i++){
for(int j=0; j<col; j++){
if ( matrix[i][j] == 0) {
rowX = i;
colX = j;
}
}
}
which result in checking "successor", or neighbors, only for the element (in state data) who`s value is 0. You need to check the neighbors of all elements. Note the comments in the code:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Set;
public class Main {
public static void BFS(Node root, Node goal) throws InterruptedException{
Queue<Node> queue = new LinkedList<>();
Set<Node> visited = new HashSet<>(); //**use to flow which nodes were tested
queue.add(root);
while(queue.size()>0){
Node temp = queue.poll();
if (temp.equals(goal)) {
goal.setParent(temp.getParent());
break;
}
else{
List<Node> successor = temp.returnSuccessor();
for(int i=0; i< successor.size(); i++){
//** made redundant by using visited boolean check = root.checkTree(successor.get(i));
Node node = successor.get(i);
if (visited.add(node)){ //** successful add indicates it was not visited before
queue.add(node);
temp.addChild(node);
}
}
}
}
}
public static void main(String[] args) throws InterruptedException {
int[][] initialState = { {0,1}, {2,3}, {4,5} };
int[][] goalState = {{3,4}, {5,0}, {1,2}};
Node root = new Node(new State(initialState));
Node goal = new Node(new State(goalState));
BFS(root,goal);
if(goal.getParent() == null){
System.out.println("There is no such a way to go from the initial state to the goal state");
}
else{
ArrayList<Node> listSteps = new ArrayList<>();
while(goal != null){
listSteps.add(goal);
goal = goal.getParent();
}
for (int i=listSteps.size()-1; i>=0; i--){
System.out.println(listSteps.get(i));
}
int numSteps = listSteps.size()-1;
System.out.println("Number of steps: " + numSteps);
}
}
}
class State {
private int data[][];
public int[][] getData() { return data;}
public void setData(int[][] data) { this.data = data; }
public void swap(int row1, int col1, int row2, int col2){
int temp = data[row1][col1];
data[row1][col1] = data[row2][col2];
data[row2][col2] = temp;
}
public State copyState() { //**simpler version of
int i = 0;
int[][] temp = new int[data.length][];
for (int[] row : data) {
temp[i++] = Arrays.copyOf(row, row.length); //**simpler way to copy array
}
return new State(temp);
}
public State(int[][] data) {
super();
this.data = data;
}
}
class Node {
private State state;
private Node parent;
private ArrayList<Node> children;
public Node(State state){
this.state = state;
parent = null;
children = new ArrayList<>();
}
public State getState() { return state; }
public void setState(State state) { this.state = state; }
public Node getParent() { return parent;}
public void setParent(Node parent) { this.parent = parent; }
public ArrayList<Node> getChildren() { return children; }
public void addChild(Node node){
node.setParent(this);
children.add(node);
}
public List<Node> returnSuccessor(){
List<Node> result = new ArrayList<>();
int[][] matrix = getState().getData();
int row = matrix.length;
int col = matrix[0].length;
for(int i=0; i<row; i++){
for(int j=0; j<col; j++){
/* need to check possible move for ALL nodes
* if ( matrix[i][j] == 0) {
rowX = i;
colX = j;
}*/
if( (j-1) >= 0 ){
State temp = getState().copyState();
temp.swap(i, j, i, j-1);
Node left = new Node(temp);
result.add(left);
}
if ( (j+1) < col ){
State temp = getState().copyState();
temp.swap(i, j, i, j+1);
Node right = new Node(temp);
result.add(right);
}
if ( (i-1) >= 0 ){
State temp = getState().copyState();
temp.swap(i, j, i-1, j);
Node top = new Node(temp);
result.add(top);
}
if ( (i+1) < row ){
State temp = getState().copyState();
temp.swap(i, j, i+1, j);
Node down = new Node(temp);
result.add(down);
}
}
}
return result;
}
//override toString rather than creating
#Override
public String toString(){
return Arrays.deepToString(getState().getData());
}
//**override equals rather than creating your own equal
#Override
public boolean equals(Object node){
if (node == this) { return true; }
if (node == null) { return false;}
if (!(node instanceof Node)) {return false; }
return Arrays.deepEquals(getState().getData(), ((Node)node).getState().getData());
}
//** override hashCode so each Node has a unique one
#Override
public int hashCode() {
return toString().hashCode();
}
}
I also thing the terminology is a bit confusing. I think it would be cleared if every data element represented a Node, so int[][] initialState = { {2,1}, {3,0} }; represented 4 nodes.
A collection of such nodes create a tree, which represents a unique State.

Related

How to speed up Depth First Search method?

I'm trying to do a Depth First Search of my graph, and something is slowing it down quite a lot and I'm not sure what.
Here is my Bag code:
import java.util.Iterator;
import java.util.NoSuchElementException;
public class Bag<Item> implements Iterable<Item> {
private Node<Item> first; // beginning of bag
private Node<Item> end;
private int n; // number of elements in bag
public int label;
public int edges;
public static class Node<Item> {
private Item item;
private Node<Item> next;
public int label;
public int edges;
}
public Bag() {
first = null; // empty bag initialized
end = null;
n = 0;
}
public void add(Item item) {
if (n==0) {
Node<Item> head = new Node<Item>(); // if bag is empty
first = head;
end = head;
head.item = item; // new node both first and end of bag
edges++;
n++;
}
else {
Node<Item> oldlast = end; // old last assigned to end of node
Node<Item> last = new Node<Item>();
last.item = item;
oldlast.next = last; // new node added after old last
end = last;
n++; // size increased
edges++;
}
}
public Iterator<Item> iterator() {
return new LinkedIterator(first); // returns an iterator that iterates over the items in this bag in arbitrary order
}
public class LinkedIterator implements Iterator<Item> {
private Node<Item> current;
public LinkedIterator(Node<Item> first) {
current = first; // iterator starts at head of bag
}
public boolean hasNext() { return current != null; }
public void remove() { throw new UnsupportedOperationException(); }
public Item next() {
if (!hasNext()) throw new NoSuchElementException(); // if there is next item, current is moved to next
Item item = current.item;
current = current.next;
return item; // item is returned
}
}
}
Here is my driver:
import java.util.ArrayList;
import java.util.Random;
public class Driver {
public static ArrayList<Integer> randomNum(int howMany) {
ArrayList<Integer> numbers = new ArrayList<Integer>(howMany);
Random randomGenerator = new Random();
while (numbers.size() < howMany) {
int rand_int = randomGenerator.nextInt(10000);
if (!numbers.contains(rand_int)) {
numbers.add(rand_int);
}
}
return numbers;
}
public static void main(String[] args) {
ArrayList<Integer> num = randomNum(100);
Graph G = new Graph(num);
System.out.println("The length of longest path for this sequence with graph is: " + G.dfsStart(num));
}
}
I send an ArrayList of random integers to my dfsStart method from the driver, which looks at all the different paths for each starting node in my graph. my DepthFirstSearch method calls the getAdjList for each starting node to find its neighbors using my Bag adj, and then works its way down each path before backtracking.
Here is my Graph code, containing my longest path method:
import java.util.ArrayList;
import java.util.NoSuchElementException;
public class Graph {
public final int V; // initializing variables and data structures
public Bag<Integer>[] adj;
public int longestPath;
public Graph(ArrayList<Integer> numbers) {
try {
longestPath = 0;
this.V = numbers.size();
adj = (Bag<Integer>[]) new Bag[V]; // bag initialized
for (int v = 0; v < V; v++) {
adj[v] = new Bag<Integer>();
}
for (int i = 0; i < V; i++) {
adj[i].label = numbers.get(i);
int j = (i + 1);
while (j < numbers.size()) {
if (numbers.get(i) < numbers.get(j)) {
addEdge(i, numbers.get(j));
}
j++;
}
}
}
catch (NoSuchElementException e) {
throw new IllegalArgumentException("invalid input format in Graph constructor", e);
}
}
public void addEdge(int index, int num) {
adj[index].add(num);
}
public int getIndex(int num) {
for (int i = 0; i < adj.length; i++) {
if (adj[i].label == num) {
return i;
}
}
return -1;
}
public Bag<Integer> getAdjList(int source) {
Bag<Integer> adjList = null;
for (Bag<Integer> list : adj) {
if (list.label == source) {
adjList = list;
break;
}
}
return adjList;
}
public int dfsStart(ArrayList<Integer> numbers) {
for (int i=0;i<numbers.size();i++) {
// Print all paths from current node
depthFirstSearch(numbers.get(i),new ArrayList<>(300));
}
return longestPath;
}
public void depthFirstSearch(int src, ArrayList<Integer> current) {
current.add(src);
Bag<Integer> srcAdj = getAdjList(src);
if (srcAdj.size() == 0) {
// Leaf node
// Print this path
longestPath = Math.max(longestPath, current.size());
}
for (int links : srcAdj) {
depthFirstSearch(links, current);
}
current.remove(current.size()-1);
}
}
I believe the suggestion below helped get rid of the error, but it is still unbelievably slow when trying to find the longest path in a graph of more than 150 vertices.
Even for a small dense graph there can be many unique paths from a src node. I tested for this input [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25] there are 16777216 unique paths from all nodes. So you can expect OOM for bigger inputs. one way is to update the longestPath as soon as a path is found instead of adding it to the list.
Change this to later.
addtoCount(current.size());
to
longestPath = Math.max(longestPath, current.size());
Make sure longestPath is global and initialized to 0 before every test case.
Well, I do not know JAVA but that is an incredible lot of code for doing a simple thing such as depth first search.
In C++ it is done like this:
void cPathFinder::depthFirst(
int v)
{
// initialize visited flag for each node in graph
myPath.clear();
myPath.resize(nodeCount(), 0);
// start recursive search from starting node
depthRecurse(v, visitor);
}
void cPathFinder::depthRecurse(
int v )
{
// remember this node has been visited
myPath[v] = 1;
// look for new adjacent nodes
for (int w : adjacent(v))
if (!myPath[w])
{
// search from new node
depthRecurse(w);
}
}

Java A* algorithm not finding any path

Trying to create a program that takes an image of a maze and outputs the maze with a highlighted solution but my implementation of A* is flawed.
I'm basing the algorithm on Wikipedia's pseudocode and Coding Train's implementation which is the inspiration for this project. I've compared the code for the algorithm and didn't notice anything out of the ordinary.
public class Main {
public static void main(String[] args) {
ImageConverter a = new ImageConverter("file path");
Node[][] nodes = a.to2Darray();
Solver solve = new Solver(nodes);
ArrayList<Node> solution = solve.aStar(new Node(0,1, 0),new Node(14,13,0));
System.out.println(solution);
a.toImage(nodes, solution);
}
}
public class Solver {
private Node[][] graph;
public Solver(Node[][] graph) {
this.graph = graph;
}
public ArrayList<Node> aStar(Node start, Node finish){ // solves maze using A*
ArrayList<Node> closeSet = new ArrayList<>();
ArrayList<Node> openSet = new ArrayList<>();
openSet.add(start);
ArrayList<Node> path = new ArrayList<>();
while (openSet.size()>0){
int bestF = 0;
for (int i = 0; i < openSet.size(); i++){ // find next least costly node
if (openSet.get(i).getF() < openSet.get(bestF).getF()){
bestF = i;
}
}
Node current = openSet.get(bestF);
if (current.equals(finish)){ // check if current node is end node
Node temp = current;
path.add(temp);
while(temp.getPrevious()!=null){
path.add(temp.getPrevious());
temp = temp.getPrevious();
}
return path;
}
openSet.remove(current);
closeSet.add(current);
ArrayList<Node> neighbors = current.getNeighbors();
for (int i = 0; i < neighbors.size(); i++){ // check neighbors
Node n = neighbors.get(i);
boolean isNewPath = false;
if (!closeSet.contains(n) && n.getState()!=1){
double tempG = current.getG()+heuristic(n,current);
if (openSet.contains(n)){
if (tempG < n.getG()){
n.setG(tempG);
isNewPath = true;
}
else{
n.setG(tempG);
openSet.add(n);
isNewPath = true;
}
}
if (isNewPath) {
n.setH(heuristic(n, finish));
n.setF(n.getG() + n.getH());
n.setPrevious(current);
}
}
}
}
return null; // no solution
}
private static double heuristic(Node end, Node finish) {
int y1 = end.getCol();
int x1 = end.getRow();
int y2 = finish.getCol();
int x2 = finish.getRow();
return Math.sqrt((x1-x2)*(x1-x2)+(y2-y1)*(y2-y1)); // order doesn't matter in because of squaring
}
}
public class Node {
private double f, g, h;
private int row, col; // row and col
private int state;
private ArrayList<Node> neighbors = new ArrayList<>();
private Node previous = null;
public Node(int r, int c, int state) {
this.state = state;
row = r;
col = c;
}
public int getRow() {
return row;
}
public int getCol() {
return col;
}
public double getF() {
return f;
}
public double getG() {
return g;
}
public double getH() {
return h;
}
public void setF(double f) {
this.f = f;
}
public void setG(double g) {
this.g = g;
}
public void setH(double h) {
this.h = h;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public void addNeighbor(Node b){
neighbors.add(b);
}
public void setPrevious(Node n){
previous = n;
}
public Node getPrevious(){
return previous;
}
#Override
public String toString(){
return "["+row+"]["+col+"]";
}
public ArrayList<Node> getNeighbors(){
return neighbors;
}
#Override
public boolean equals(Object o){
if (o ==this){
return true;
}
if (!(o instanceof Node)){
return false;
}
Node n = (Node) o;
return row == n.getRow() && col==n.getRow();
}
}
public class ImageConverter {
private BufferedImage image;
private int x;
private int y;
private String path;
public ImageConverter(String path) {
try {
image = ImageIO.read(new FileInputStream(path));
}
catch (IOException e) {
e.printStackTrace();
}
this.path = path;
this.x = image.getWidth(); // done for readability of to2Darray()
this.y = image.getHeight();
}
public Node[][] to2Darray() { // nested loop does [j][i] as [i][j] reflects along line from top left to bot right
Node[][] nodes = new Node[x][y];
for (int i = 0; i < nodes.length; i++){ // inital assignment/null pointer
for (int j = 0; j < nodes.length; j++){
nodes[i][j] = new Node(i,j,0); // the [j][i] thing doesn't matter here
}
}
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
Color t = new Color(image.getRGB(i, j));
if (t.equals(Color.BLACK)) {
nodes[j][i].setState(1); //black pixels are walls
}
else if (t.equals(Color.WHITE)) {
nodes[j][i].setState(0); //white pixels are paths
}
else { // is not black or white
try {
throw new Exception("Pixel at [" + i + "][" + j + "]" + " is not black or white");
}
catch (Exception e) {
System.out.println("Java threw an exception while throwing an exception. God help you" +
" if you ever see this. But if you do, there might be a pixel in the maze that is not b/w");
}
}
}
}
for (int row = 0; row < x; row++){ // add neighbors, if neighbor does not exist (out of bounds) it makes it null
for (int col = 0; col < y; col++){
try{
nodes[row][col].addNeighbor(nodes[row-1][col]); // Node to the top
}
catch (IndexOutOfBoundsException e){
nodes[row][col].addNeighbor(null);
}
try{
nodes[row][col].addNeighbor(nodes[row][col+1]); // Node to the right
}
catch (IndexOutOfBoundsException e){
nodes[row][col].addNeighbor(null);
}
try{
nodes[row][col].addNeighbor(nodes[row+1][col]); // Node to the bottom
}
catch (IndexOutOfBoundsException e){
nodes[row][col].addNeighbor(null);
}
try{
nodes[row][col].addNeighbor(nodes[row][col-1]); // Node to the left
}
catch (IndexOutOfBoundsException e){
nodes[row][col].addNeighbor(null);
}
}
}
return nodes;
}
public void toImage(Node[][] graph, ArrayList<Node> solution) { // converts to image and saves it at location from constructor
BufferedImage imageCopy = this.image;
int index = path.lastIndexOf("\\"); // change this to \\ if on Windows
File file = new File(path.substring(0, index) + "\\solved.png"); // remove the filename from filepath
final int RED = new Color(255, 0, 0).getRGB(); // for readability
final int BLACK = new Color(0, 0, 0).getRGB();
final int WHITE = new Color(255, 255, 255).getRGB();
/*for (int i = 0; i < x; i++) { // convert to BufferedImage
for (int j = 0; j < y; j++) {
if (graph[i][j].getState() == 0) { // empty path
image.setRGB(j, i, WHITE);
}
else if (graph[i][j].getState() == 1) { // wall
image.setRGB(j, i, BLACK);
}
if
}
}*/
for (int i = 0; i < x; i++) { // convert to BufferedImage
for (int j = 0; j < y; j++) {
System.out.println(i+" "+j);
if (solution.contains(graph[j][i])){
imageCopy.setRGB(i,j,RED);
}
}
}
try {
ImageIO.write(image, "png", file);
}
catch (IOException e) {
e.printStackTrace();
}
}
}
In Main, solution should have an ArrayList<Node> of the Node objects that create the best path, however it returns null showing that it doesn't find a solution.
There is an error in the Node.equals() method:
return row == n.getRow() && col==n.getRow();
Should be
return row == n.getRow() && col==n.getCol();
Maybe that is the problem.

Displaying a linked list in java

I'm working on an assignment where I need to create a Linked List given a template. For each new node that is created, I need to print out the updated list. However, up until this point, I've been stumped on how to print out the linked list. Can anyone figure out what am I doing wrong? What I currently have just prints out the number that has been created, followed by blank space, instead of the entire list up to that point.
NumberList.java
import java.util.*;
public class NumberList {
private Node head;
public NumberList() {
}
public void insertAtHead(int x) {
Node newNode = new Node(x);
if (head == null)
head = newNode;
else {
newNode.setNext(head);
head = newNode;
}
}
public void insertAtTail(int x) {
}
public void insertInOrder(int x) {
}
public String toString() {
Node tmp = head;
String result = "";
while (tmp.getNext() != null) {
result += tmp.toString() + " ";
}
return result;
}
//---------------------
// test methods
//---------------------
public static void testInsertAtHead() {
Random r = new Random();
int n = 20;
int range = 1000;
NumberList list = new NumberList();
for (int i=1; i<=n; i++) {
int x = r.nextInt(range);
list.insertAtHead(x);
System.out.println("" + x + ": " + list);
}
}
public static void testInsertAtTail() {
Random r = new Random();
int n = 20;
int range = 1000;
NumberList list = new NumberList();
for (int i=1; i<=n; i++) {
int x = r.nextInt(range);
list.insertAtTail(x);
System.out.println("" + x + ": " + list);
}
}
public static void testInsertInOrder() {
Random r = new Random();
int n = 20;
int range = 1000;
NumberList list = new NumberList();
for (int i=1; i<=n; i++) {
int x = r.nextInt(range);
list.insertInOrder(x);
System.out.println("" + x + ": " + list);
}
}
public static void main(String[] args) {
//testInsertAtHead();
//testInsertAtTail();
testInsertInOrder();
}
}
Node.java
class Node {
private int number;
private Node next;
public Node(int n) {
this.number = n;
this.next = null;
}
public Node getNext() {
return next;
}
public int getNumber() {
return number;
}
public void setNext(Node n) {
if (n == null)
return;
n.setNext(next);
next = n;
}
public String toString() {
return number + "";
}
}
I think your toString() is looping endlessly once the second element is added. You need to move your pointer to the next node:
public String toString() {
Node tmp = head;
String result = "";
while (tmp != null) {
result += tmp.toString() + " ";
tmp = tmp.getNext();
}
return result;
}
I've also updated the condition to handle a null head.

Issues with Objects in a linkedlist

On my count method, i am trying to compare the object being sent with the object calling it, and I have no idea why i can not cal o.get(i) to get the value for Object o being passed. It tells me the method cannot be found even though i can call get(i) normally. Any ideas how i can get the value for the object getting passed so i can compare them?
public class GenericLinkedList<E> implements List<E> {
private class Node<E>{
private E data;
private Node<E> next;
}
private E data;
private Node<E> head = null;
private int size = 0;
private Node<E> nodeAt(int index){
Node<E> curNode = head;
int curIndex = 0;
while(curIndex < index){
curNode = curNode.next;
curIndex++;
}
return curNode;
}
#Override
public E get(int index) {
return nodeAt(index).data;
}
#Override
public void add(E value) {
Node<E> node = new Node<E>();
node.data = value;
if(size == 0){
head = node;
}else{
Node<E> curNode = nodeAt(size - 1);
curNode.next = node;
}
size++;
}
public void add(int index, E value){
Node<E> node = new Node<E>();
node.data = value;
if(size == 0){
head = node;
}else if(index == 0){
node.next = head;
head = node;
}else{
Node<E> curNode = nodeAt(index - 1);
node.next = curNode.next;
curNode.next = node;
}
size++;
}
#Override
public void remove(int index) {
if(index == 0){
head = head.next;
}else{
Node<E> curNode = nodeAt(index - 1);
curNode.next = curNode.next.next;
}
size--;
}
#Override
public void set(int index, E value) {
nodeAt(index).data = value;
}
public String toString(){
String s = "";
Node<E> curNode = head;
s += curNode.data +" -> ";
while(curNode.next != null){
curNode = curNode.next;
s += curNode.data +" -> ";
}
s += "null";
return s;
}
public void clear() {
for (int i = 0; i < size; i++)
set(i, null);
size = 0;
}
#Override
public void removeAll(E o)//Clears out the array object by setting everything to null
{
for(int i = 0; i < this.size; i++)
{
}
}
#Override
public int count(Object o)
{
System.out.println(o);
int count = 0;
for(int i = 0; i< size;i++)
{
if(get(i) == o.get(i))
{
count++;
}
}
return count;
/*int count = 0;
for(int i = 0;i<this.size;i++)
{
for(int j = 0;i<size;j++)
{
}
}
return count;*/
}
public void reverse()
{
int x = size;
for(int i = 0; i < this.size; i++)
{
E temp = this.get(x);
this.set(x, get(i));
this.set(i, temp);
x++;
}
}
public Object subList(int beginIndex, int endIndex)
{
int j = 0;
GenericLinkedList<E> LinkedList = new GenericLinkedList<E>();
if(beginIndex == endIndex)
return LinkedList;
else if(beginIndex > endIndex||endIndex>size||beginIndex<0)
{
return null;
}
else
{
for(int i = beginIndex; i <= endIndex;i++)
{
LinkedList.add(get(i));
j++;
}
}
return LinkedList;
}
public static void main(String[] args) {
GenericLinkedList<Integer> myList = new GenericLinkedList<Integer>();
myList.add(4);
myList.add(7);
myList.add(123123);
System.out.println(myList.get(2));
GenericLinkedList<Integer> myList2 = new GenericLinkedList<Integer>();
myList2.add(4);
myList2.add(7);
myList2.add(8);
myList2.add(3,999);
System.out.println(myList2);
System.out.println(myList.count(myList2));
//System.out.println(myList2);
// myList2.clear();//Testing our clear class
// System.out.println(myList2);
//System.out.println(myList2.subList(1, 3));//Testing our clear class
// System.out.println(myList2);
}
}
You have a problem when trying to call o.get() because it is an object of the base type Object which has no method get defined. To get the proper result you have two possible solutions....
The short solution is to type cast.
((GenericLinkedList<Object>)o).get(i)
Or a more easily readable solution is to change the signature of your count method:
public int count(GenericLinkList<E> list) {
...
}
Change your count method to public int GenericLinkedList(Object o)
If you use Object as the type of the parameter, you can only call the methods which are available on Object.

Program won't compile completely without giving an error of parsing

I'm writing this code to implement a stack as a linked list but I keep getting an error when I compile this part of the code and can't figure out why
I definitely know that it shouldn't be giving me this error since there are enough brackets and none of them are out of place I hope
The Error:
C:\Users\Michelle\Desktop\ITB\Semester 5\Data Structures & Algorithms\Assignment\ListReference.java:108: error: reached end of file while parsing
}
^
1 error
My Code:
public class ListReference implements StackInterface {
private Node top;
//private Object item;
private int NumItems;
public ListReference() {
NumItems = 0;
top = new Node(null);
}
public boolean isEmpty() {
return NumItems == 0;
}
public int size() {
return NumItems;
}
/*public Node find(int index) {
Node curr = tail;
for(int skip = 1; skip < index; skip++) {
curr.getNext();
}
return curr;
}*/
public Object get(int index) {
if(index <= 0)
return null;
Node ListReference = top.getNext();
for(int i=1; i < index; i++) {
if (ListReference.getNext() == null)
return null;
ListReference = ListReference.getData();
}
}
public void add(int index, Object item) {
Node ListReferenceTemp = new Node(item);
Node ListRefCurr = top;
while(ListRefCurr.getNext() != null) {
ListRefCurr = ListRefCurr.getNext();
}
ListRefCurr.setNext(ListReferenceTemp);
NumItems++;
}
public void add(Object data) {
Node ListReferenceTemp = new Node(item);
Node ListRefernce = top;
for(int i=1; i < index && ListReference.getNext() != null; i++) {
ListReference = ListReference.getNext();
}
ListReferenceTemp.setNext(ListReference.getNext());
ListReference.setNext(ListReferenceTemp);
NumItems++;
}
// removes the element at the specified position in this list.
public boolean remove(int index) {
// if the index is out of range, exit
if (index < 1 || index > size())
return false;
Node ListRefCurr = top;
for (int i = 1; i < index; i++) {
if (ListRefCurr.getNext() == null) {
return false;
}
ListRefCurr = ListRefCurr.getNext();
}
ListRefCurr.setNext(ListRefCurr.getNext().getNext());
NumItems--; // decrement the number of elements variable
return true;
}
public String toString() {
Node ListReference = top.getNext();
String output = "";
while (ListREference != null) {
output += "[" + ListRefCurr.getData().toString() + "]";
ListRefCurr = ListRefCurr.getNext();
}
return output;
}

Categories

Resources