I'm trying to store a mathematical expression by tokenizing it and putting it into a doubly linked list I created in a lab assignment. The insert method I implemented in the list worked completely fine when I tested before handing in the lab, but when I print the contents of the list after inserting the expression's tokens, some tokens are missing. I know the String Tokenizer is working, as I had it print all the tokens and they all showed up just fine.
Is there something about how String Tokenizer tokenizes strings that prevents me from inserting them as generic Objects in my linkes list? I feel like there's some behavior I'm not aware of here.
For reference, the class containing the method which tokenizes the string and inserts it into a list:
import java.io.File;
import java.io.FileNotFoundException;
import java.lang.*;
import java.util.*;
public class Calculator {
DoubleLinkedListTest infixstorage;
public Calculator(){
infixstorage = new DoubleLinkedListTest();
}
public static DoubleLinkedListTest ReadInFile(String path){
File file = new File(path);
DoubleLinkedListTest list = new DoubleLinkedListTest();
try {
Scanner scanner = new Scanner(file);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
StringTokenizer st = new StringTokenizer(line);
while (st.hasMoreTokens()){
list.insert(st.nextToken());
}
}
scanner.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return list;
}
}
Here is the code for my DoubleLinkedList:
public class DoubleLinkedListTest implements DoubleLinkedList {
private DoubleNode head;
private DoubleNode tail;
public DoubleLinkedListTest(){
head = new DoubleNode();
tail = new DoubleNode();
head.next = tail;
tail.prev = head;
}
public void insert(Object x){
if (lookup(x) == false){
if (head.data == null){
head.data = x;
}
else if (head.data != null && tail.data == null){
tail.data = x;
}
else{
DoubleNode NewNode = new DoubleNode();
NewNode.data = x;
NewNode.next = null;
NewNode.prev = tail;
tail.next = NewNode;
tail = NewNode;
}
}
}
//Runtime of insert method will be n, where n is the number of nodes
public void delete(Object x){
if (this.lookup(x).equals(true)){
if(x.equals(head.data)){
head.next.prev = null;
head = head.next;
}
else{
DoubleNode temp = head;
while(temp.next != null){
if (temp.next.next == null && (temp.next).data.equals(x)){
temp.next.prev = null;
temp.next = null;
break;
}
if ((temp.next).data.equals(x)){
temp.next.next.prev = temp;
temp.next = (temp.next).next;
break;
}
else{
temp = temp.next;
}
}
}
}
}
public Object lookup(Object x){
Boolean search = false;
if (x.equals(head.data)){
search = true;
}
else{
DoubleNode temp = head;
while (temp.next != null){
if (x.equals(temp.data)){
search = true;
break;
}
if (temp.next.next == null && x.equals(temp.next.data)){
search = true;
break;
}
else{
temp = temp.next;
}
}
}
return search;
}
public boolean isEmpty(){
if(head.next == tail && tail.prev == head)
return true;
else
return false;
}
public void printList(){
DoubleNode temp = head;
System.out.println(temp.data + " ");
while (temp.next != null){
temp = temp.next;
System.out.println(temp.data + " ");
}
}
public void printListRev(){
System.out.print(tail.data + " ");
while (tail.prev != head){
tail = tail.prev;
printList();
}
}
}
I figured it out. The scanner is reading multiple lines of the file at once. I thought that there was one line, but it just appears that way in the txt file. It's actually three lines sitting next to each other.
EDIT: False alarm, after deleting the other lines, it is still incorrectly reading the remaining line
EDIT 2: Or at least the print of the list is not correct
Related
public class SearchLinkedList<E> {
private Node<E> first;
public static void main(String[] args){
SearchLinkedList<Integer> list = new SearchLinkedList<Integer>();
list.insert(1000);
list.insert(2000);
list.insert(3000);
System.out.println(list.getFirst());
}
public SearchLinkedList() {
first = null;
}
public void insert(E e) {
if (first == null) {
first = new Node<E>(e);
} else {
//while(temp.next.searched == true) then insert new Node where the next node is null or searched == false
Node<E> temp = new Node<E>(e);
temp.next = first;
first = temp;
}
}
public E getFirst() {
return first.data;
}
public E find(E x) {
if (first == null) {
return null;
} else {
//while (temp != null) if node found set it's searched = true and move it to front of list
Node<E> temp = first;
while (temp != null) {
if (temp.data.equals(x)) {
temp.searched = true;
return temp.data;
}
temp = temp.next;
}
return temp.data;
}
}
private static class Node<E> {
private E data;
private boolean searched;
private Node<E> next;
private Node(E e) {
data = e;
searched = false;
next = null;
}
}
}
So the assignment here is to create a LinkedList class that moves a node to the front of the list (first) if it has been searched.
First image here is when this is called:
list.insert(1000);
list.insert(2000);
list.insert(3000);
Second image is when this is called:
list.find(3000);
list.find(2000);
So the goal is when find is called and node with data is found: Set it's searched boolean to true and move that node to front of list. As of now, my insert just puts new node at the front of list. The comments in insert and find explain what I want to make them do. However, moving an element from the middle of a single linkedlist to front seems hard. Don't know what to do here. You can copy and try this yourself. After calling list.find(2000); and then list.getFirst() We should get 2000. Question is how... My thoughts are on if I should let the Node's booleans decide whether to be infront or not... Not sure here at all.
Thanks to danilllo19 for the help. That answer is correct only issue was that the new elements should be added from the front and so if an element is searched we're supposed to add the new one after the last searched but at the head of the un-serached ones. Solved it like this:
public void insert(E e) {
if(first == null){
first = new Node<E>(e);
}else{
Node<E> temp = first;
while(temp.searched && temp.next != null && temp.next.searched){
temp = temp.next;
}
Node<E> node = new Node<E>(e);
if(temp.searched && temp.next != null && !temp.next.searched){
Node<E> temp2 = temp.next;
temp.next = node;
node.next = temp2;
}else if(temp.searched && temp.next == null){
temp.next = node;
}else{
node.next = temp;
first = node;
}
}
}
I suppose you should do it like this:
public class SearchLinkedList<E> {
private Node<E> first;
public static void main(String[] args) {
SearchLinkedList<Integer> list = new SearchLinkedList<Integer>();
list.insert(1000);
list.insert(2000);
list.insert(3000);
System.out.println(list.getFirst());
System.out.println(list.find(3000));
System.out.println(list.getFirst());
list.insert(4000);
System.out.println(list.find(200));
}
public SearchLinkedList() {
first = null;
}
public void insert(E e) {
if (first == null) {
first = new Node<E>(e);
} else {
//while(temp.next.searched == true) then insert new Node where the next node is null or searched == false
Node<E> temp = first;
while (temp.next != null && temp.next.searched) {
temp = temp.next;
}
Node<E> node = new Node<>(e);
if (temp.next != null) {
node.next = temp.next;
}
temp.next = node;
}
}
public E getFirst() {
return first.data;
}
public E find(E x) {
if (first == null) {
return null;
} else {
//while (temp != null) if node found set it's searched = true and move it to front of list
Node<E> temp = first;
while (temp != null) {
if (temp.data.equals(x)) {
temp.searched = true;
break;
}
temp = temp.next;
}
if (temp == null) return null;
pushForward(temp);
return temp.data;
}
}
//Find pre-linked node with our node, bind our node with parent next node
//and link parent with node.
private void pushForward(Node<E> node) {
if (first == null || first.next == null) return;
Node<E> temp = first;
while (temp.next != null) {
if (temp.next.equals(node)) {
temp.next = temp.next.next;
node.next = first;
first = node;
break;
}
temp = temp.next;
}
}
private static class Node<E> {
private E data;
private boolean searched;
private Node<E> next;
private Node(E e) {
data = e;
searched = false;
next = null;
}
}
}
Also you could mix pushForward and find methods to make find to do what you want by one iteration through the list (O(n)), because O(n^2) there.
Might be helpful: https://www.geeksforgeeks.org/java-program-for-inserting-node-in-the-middle-of-the-linked-list/
I am a beginner with DSA, Since the last couple of days, I was trying to find the correct implementation for the Graph using the adjacency list.
Below I provided the entire code for the way I thought the adjacency list should be implemented.
I have created a SinglyLinkedlist from scratch.
And I am using a Hashmap to improve the Time complexity.
The Integer key in the Hashmap acts as the VERTICE & consists of a LinkedList in its VALUE.
In the vertices, I am storing the Integer ID and in the LinkedList, I am storing all the Friend names for that particular ID.
The Graph has 3 methods:
InsertVertice(int ID ) - creates an empty LinkedList at given ID in hashmap.
insertDataAtID (int ID, String data) - inserts the Data into the LinkedList at the given ID.
printAllDataAtID(int ID) - prints all the friend names or Data present in a LinkedList at a given ID/key in the Hashmap.
Can you please go through the Implementation and advice of any mistakes?
Or better some suggestions on how an Adjacency list can be implemented more effectively?
Thank you for this effort.
import java.util.HashMap;
public class demo {
static HashMap<Integer,SinglyLinkedlist> graph = new HashMap<>();
public static void main(String[] args){
Graph graph = new Graph();
graph.insertVertice(101);
graph.insertDataAtID(101,"Deepesh");
graph.insertDataAtID(101,"Kiran");
graph.insertDataAtID(101,"Aryan");
graph.insertVertice(201);
graph.insertDataAtID(201,"Carl");
graph.insertDataAtID(201,"Arun");
graph.insertDataAtID(201,"Kishan");
graph.insertDataAtID(201,"Betth");
graph.printAllDataAtID(101);
graph.printAllDataAtID(201);
}
}
import java.util.HashMap;
public class Graph{
HashMap<Integer,SinglyLinkedlist> maplist = new HashMap<>();
void insertVertice(Integer id ){
maplist.put(id,new SinglyLinkedlist());
}
void insertDataAtID(Integer id, String data){
if (maplist.get(id)==null){
System.out.println("No such Vertice exist with id : " + id);
System.out.println("Create the Vertice first by calling insertVertice() method.");
}
SinglyLinkedlist linkedlist = maplist.get(id);
linkedlist.insertNode(data);
}
void printAllDataAtID(Integer id) throws NullPointerException {
if (maplist.get(id) == null) {
System.out.println("No such Vertice exist with id : " + id);
System.out.println("Create the Vertice first by calling insertVertice() method.");
} else {
SinglyLinkedlist linkedlist = maplist.get(id);
linkedlist.printAll();
}
}
}
public class SinglyLinkedlist {
Node head;
Node tail;
public static class Node {
Node next;
String data;
}
void insertNode(String data) {
Node newNode = new Node();
newNode.data = data;
if (head == null) {
head = tail = newNode;
newNode.next = null;
} else {
Node temp = head;
while (temp.next != null) {
temp = temp.next;
}
temp.next = newNode;
newNode.next = null;
tail = newNode;
}
}
void removeLastNode() {
Node temp = head;
while (temp.next.next != null) {
temp = temp.next;
}
Node removedNode = temp.next;
tail = temp;
tail.next = null;
System.out.println("Removed value : " + removedNode.data);
}
void printAll() {
if (head == null) {
System.out.println("List is Empty !");
} else {
Node temp = head;
while (temp != null) {
System.out.print(temp.data + " ");
temp = temp.next;
}
}
}
boolean search(String data) {
if (head == null) {
System.out.println("List is Empty !");
} else {
Node temp = head;
while (temp != null) {
if (temp.data.equals(data)) {
System.out.println("Value found !");
return true;
}
temp = temp.next;
}
System.out.println("Value not found !");
}
return false;
}
}
You don't need to traverse the list to insert if you are maintaining tail node.
void insertNode(String data) {
Node newNode = new Node();
newNode.data = data;
if (head == null) {
head = tail = newNode;
newNode.next = null;
} else {
tail.next = newNode;
newNode.next = null;
tail = tail.next;
}
}
So my problem is that I wanna delete a node based on a value inputted by the user, in my program I can already, add, search, and delete the node in the last position, but so far I haven't been able to delete a specific value inputted by the user, if for example I have 1,2,3,4 elements in my list I wanna be able to point at, say 2, and delete it. here are my functions, the last one is the uncompleted one:
//searches node
public void searchNode(int input){
Node temp = first;
boolean found = false;
if(!isEmpty()){
for(int i = 0 ; i<size ; i ++){
if(temp.value == input){
System.out.println(input + " found in the position: " + (i+1));
found = true;
break;
}
temp = temp.rightNode;
}
if(!found)
System.out.println("value not found.");
}
}
//deletes last node
public void deleteLastNode(){
if(isEmpty()){
System.out.println("There are no nodes to delete.");
}
if(last == first){
first = null;
last = null;
} else {
Node current = first;
while(current.rightNode != last){
current = current.rightNode;
}
current.rightNode = null;
last = current;
}
size --;
}
//delete element, input by user.
public void deleteInputByUser(int input) {
Node temp = first;
boolean found = false;
if(isEmpty()){
System.out.println("There are no nodes to delete.");
} else {
}
size--;
}
//Node class
public class Node{
int value;
Node rigthNode;
public Node(int value){
this.value = value;
}
}
Deletion of a node in a Linked List by value is not so bad. This pseudocode should help you get started:
deleteNodeByValue(int val) {
if (head.val = val) {
head = head.next
return
}
current = head
while (current.next != null) {
if (current.next.val = val) {
current.next = current.next.next
return
}
current = current.next
}
}
Find the nodeToDelete and his previousNode, then
previousNode.rightNode = nodeToDelete.rightNode;
you can do it this way. The following code will remove the element once the index is given.
public boolean deleteAt(int index){
Node current=first;
if(index==0){
first=current.rightNode;
return true;
}
currentIndex=0;
previousNode=first;
current=first.rightNode;
while(current!=null){
if(currentIndex==index){
previousNode.rightNode=current.rightNode;
return true;
}
currentIndex++;
previousNode=current;
current=current.rightNode;
}
return false;
}
You could try something like that.
public void deleteNodeByValue(int input) {
Node currNode = first;
boolean found = false;
Node prevNode = first;
if (!isEmpty()) {
for (int i = 0; i < size; i++) {
if (currNode.value == input) {
///////DELETE START
if (currNode == first) {
first = currNode.rightNode;
} else {
prevNode.rightNode = currNode.rightNode;
if (currNode == last)
last = prevNode;
}
////DELETE END
found = true;
size--;
break;
}
prevNode = currNode;
currNode = currNode.rightNode;
}
if (!found)
System.out.println("value not found.");
}
}
I'm trying to tokenize lines of numeric expressions into a linked list for a CS Project. I have to use my own Linked List that I created in a previous lab.
I tokenize each number and operator of a line, and insert each token into a node in my linked list as they are tokenized. When I code the program to print out each token as it's tokenized, each token is printed. But when I tell it to print out the linked list that contains each token as a node, some operators are missing. I don't know what is the cause for this behavior.
Below is the method that creates the Linked List containing each token:
public static LinkedListTest ReadInFile(String path){
File file = new File(path);
LinkedListTest list = new LinkedListTest();
try {
Scanner scanner = new Scanner(file);
int count = 0;
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
StringTokenizer st = new StringTokenizer(line);
while (st.hasMoreTokens()){
list.insert(st.nextToken());
}
}
scanner.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return list;
}
Below are the methods for inserting into a linked list and printing one:
public class LinkedListTest implements LinkedList {
private Node head;
public LinkedListTest(){
head = new Node();
}
public void insert(Object x){
if (lookup(x) == false){
if (head.data == null)
head.data = x;
else{
/*
Node NewNode = new Node();
NewNode.data = x;
NewNode.next = head;
head = NewNode;
*/
//InsertLast
Node temp = head;
while (temp.next != null){
temp = temp.next;
}
Node NewNode = new Node();
NewNode.data = x;
NewNode.next = null;
temp.next = NewNode;
}
}
}
public void printList(){
Node temp = head;
while (temp.next != null){
System.out.print(temp.data + " ");
temp = temp.next;
}
System.out.print(temp.data + " ");
}
}
I solved it. The lookup clause on my insert function was screwing it up.
I am trying to make a method to merge two linked lists for a homework assignment in my programming class. I'm really confused here, the method has to have this method signature:
public UnorderedLinkedListInt merge2(UnorderedLinkedListInt list), so in my tester method it will look like this list3 = list1.merge2(list2). I'm confused on how to make this when the method only takes in one list and not both. Here is my code so far
public class UnorderedLinkedListInt extends LinkedListIntClass {
//Default constructor
public UnorderedLinkedListInt() {
super();
}
public boolean search(int searchItem) {
LinkedListNode current; //variable to traverse the list
current = first;
while (current != null)
if (current.info == searchItem)
return true;
else
current = current.link;
return false;
}
public void insertFirst(int newItem) {
LinkedListNode newNode; //variable to create the new node
//create and insert newNode before first
newNode = new LinkedListNode(newItem, first);
first = newNode;
if (last == null)
last = newNode;
count++;
}
public void insertLast(int newItem) {
LinkedListNode newNode; //variable to create the new node
//create newNode
newNode = new LinkedListNode(newItem, null);
if (first == null) {
first = newNode;
last = newNode;
}
else {
last.link = newNode;
last = newNode;
}
count++;
}
public void deleteNode(int deleteItem) {
LinkedListNode current; //variable to traverse the list
LinkedListNode trailCurrent; //variable just before current
boolean found;
//Case 1; the list is empty
if ( first == null)
System.err.println("Cannot delete from an empty list.");
else {
//Case 2: the node to be deleted is first
if (first.info == deleteItem) {
first = first.link;
if (first == null) //the list had only one node
last = null;
count--;
}
else { //search the list for the given info
found = false;
trailCurrent = first; //trailCurrent points to first node
current = first.link; //current points to second node
while (current != null && !found) {
if (current.info == deleteItem)
found = true;
else {
trailCurrent = current;
current = current.link;
}
}
//Case 3; if found, delete the node
if (found) {
count--;
trailCurrent.link = current.link;
if (last == current) //node to be deleted was the last node
last = trailCurrent;
}
else
System.out.println("Item to be deleted is not in the list.");
}
}
}
public void merge(UnorderedLinkedListInt list2){
UnorderedLinkedListInt list1 = this;
while (list2.first != null) {//while more data to print
list1.insertLast(list2.first.info);
list2.first = list2.first.link;
}
}
public UnorderedLinkedListInt merge2(UnorderedLinkedListInt list2){
UnorderedLinkedListInt list3 = new UnorderedLinkedListInt();
UnorderedLinkedListInt list1 = this;
while (list1.first != null) {//while more data to print
list3.insertLast(list1.first.info);
list1.first = list1.first.link;
}
while (list2.first != null) {//while more data to print
list3.insertLast(list2.first.info);
list2.first = list2.first.link;
}
return list3;
}
}
I'm still having some trouble understanding exactly how linked lists work, any suggestions as to how to design this method would be greatly appreciated.
In a method call like list1.merge2(list2), the method receives list1 as the implicit "current object" that you can access with the this reference.
If you want to you can use another name for it:
public UnorderedLinkedListInt merge2(UnorderedLinkedListInt list2){
UnorderedLinkedListInt list1 = this;
// now merge list1 and list2
}
Your first list would be actual Object pointed to by the this reference.
Try this:
import java.io.*;
class Node1
{
int data;
Node1 link;
public Node1()
{
data=0;
link=null;
}
Node1 ptr,start,temp,ptr1;
void create()throws IOException
{
int n;
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter first data");
this.data=Integer.parseInt(br.readLine());
ptr=this;
start=ptr;
char ins ='y';
do
{
System.out.println("Wanna Insert another node???");
ins=(char)br.read();
br.read();
if(ins=='y')
{
temp=new Node1();
System.out.println("Enter next data");
temp.data=Integer.parseInt(br.readLine());
temp.link=null;
ptr.link=temp;
temp=null;
ptr=ptr.link;
}
}while(ins=='y');
}
void merge()throws IOException
{
ptr1=this;
ptr=this;
Node1 t=new Node1();
t.create();
while(ptr1.link!=null)
{ ptr1=ptr1.link;}
ptr1.link=t.start;
ptr1=t=null;
System.out.println("---------------------------");
System.out.println("Merged LL :\n");
while(ptr!=null)
{
System.out.print("-->"+ptr.data);
ptr=ptr.link;
}
}
}