I am given two data structures of Nodes, and I am supposed to combine them into one single Node with alternating data structures. The data structures may or may not be of equal lengths.
I have already attempted this problem and I have checked over my code, but it still isn't correct. I have written other methods that I use in this one particular method, so I will post the code for those too. I came up with my method by looking at examples of how the data organization for this particular problem works.
Get the head of the Node list:
public static <E> Node<E> getHead(Node<E> current) {
Node<E> head = null;
while (current != null) {
head = current;
current = current.previous;
}
return head;
}
Get the number of Nodes in the data structure:
public static <E> int countNodes(Node<E> current) {
int count = 0;
while (current != null) {
count++;
current = current.next;
}
return count;
}
Note that I have tested these two methods (getHead and countNodes) and they have proven to be correct. I have posted them to see if they are missing something.
The Node class itself was written by my instructor and has been tested to be correctly written
public static class Node<E> {
public Node<E> next;
public Node<E> previous;
public E data;
public Node(E d) {
data = d;
}
public String toString() {
if (next == null)
return "";
return data + ", " + next.toString();
}
public boolean equals(Object o) {
Node<E> node = (Node<E>) o;
if (node == null)
return false;
Node<E> current = this;
while (current != null && node != null) {
if (!current.data.equals(node.data)) {
return false;
}
current = current.next;
node = node.next;
}
return current == null && node == null;
}
}
Finally, the method that I am having problems with: (Updated with edits)
public static <E> Node<E> combineNodes(Node<E> current, Node<E> current2) {
Node<E> newNode = null;
int currentSize = countNodes(current);
int current2Size = countNodes(current2);
int size = Math.max(currentSize, current2Size);
for (int i = 0; i < size; i++) {
if (i <= currentSize - 1) {
Node<E> node = new Node<E>(current.data);
newNode.next = node;
node.previous = newNode;
newNode = newNode.next;
current = current.next;
}
if (i <= current2Size - 1) {
Node<E> node = new Node<E>(current2.data);
newNode.next = node;
node.previous = newNode;
newNode = newNode.next;
current2 = current2.next;
}
}
return getHead(newNode);
}
Again, I have looked through the code and I feel like it should work. Is there anything that I am missing or doing wrong?
Edit
I should have included the test case that I was given. My instructor is using the JUnit test case library for the assignment. This is the test case that I have to pass:
#Test
public void combineNodesTest1() {
LinkedData.Node<String> node = makeStructure(10); // Makes a data structure of Nodes from "Fred 0" to "Fred 9"
LinkedData.Node<String> node2 = makeStructure(10);
LinkedData.Node<String> ret = new LinkedData.Node<String>("Fred 0");
ret.next = new LinkedData.Node<String>("Fred 0");
LinkedData.Node<String> r = ret.next;
for(int i = 1; i<10;i++) {
r.next = new LinkedData.Node<String>("Fred "+i);
r = r.next;
r.next = new LinkedData.Node<String>("Fred "+i);
r = r.next;
}
LinkedData.Node<String> answer = LinkedData.combineNodes(node, node2); // Method that I wrote
assertEquals(ret, answer);
}
The makeStructure() method is correctly written.
Edit 2
I have updated the code to actually link the nodes together, but it is still wrong. I'd like to know what I'm doing wrong now.
Thanks,
Steward
From my perspective, you don't change any of pointers (next, previous) in your combineNodes method. You only traverse the structure. What is missing in the first if is
newNode = current;
newNode.next = current2;
current = current.next;
and then the following in the second if
newNode = current2;
newNode.next = current;
current2 = current2.next;
Related
I was tasked with creating my own linked list class, using a book class i made. One of the questions was to Determine the book that appears first alphabetically.
i was able to sort the Linked list alphabetically using bubble sort(i know its not efficient but im still new) here is the code.
public void alphaBubbleSort() {
int size = size();
if (size > 1) {
boolean wasChanged;
do {
Node current = head;
Node previous = null;
Node next = head.next;
wasChanged = false;
while (next != null) {
if (current.book.getName().compareToIgnoreCase(next.book.getName()) > 0) {
wasChanged = true;
if (previous != null) {
Node sig = next.next;
previous.next = next;
next.next = current;
current.next = sig;
} else {
Node temp = next.next;
head = next;
next.next = current;
current.next = temp;
}
previous = next;
next = current.next;
} else {
previous = current;
current = next;
next = next.next;
}
}
} while (wasChanged);
}
}
my problem is i only want the front node and i do not want to alter the linked list order. i tried to do this in my main.
Linky tempLinky = new Linky(); // create temp linked list
tempLinky = linky; // copy temp main linked list to temp
tempLinky.alphaBubbleSort(); // sort temp list
System.out.println(tempLinky.peek());// return object in first node
This did not seem to work. Ive tried some other code that does not work, so ive come here as a last resort.
If you need to find the first book alphabetically, there's no need to sort the entire list (and, as you commented, you don't want to alter the list's order anyway).
Instead, you could iterate over the list and keep the "first" object as you go:
public Book getFirstAlphabetically() {
Node current = head;
Book retVal = head.book;
while (current != null) {
if (current.book.getName().compareToIgnoreCase(retVal.getName()) < 0) {
retVal = current.book;
}
current = current.next;
}
return retVal;
}
Here's an example:
import java.util.Random;
class Book {
String title;
Book(String title){this.title = title;}
}
class Node {
Book b; Node next;
Node(Book b){this.b = b;}
}
public class Main {
static Book least(Node head){
if (head == null) return null;
Book least = head.b;
for(Node n=head.next; n.next!=null; n=n.next)
least = least.title.compareTo(n.b.title) > 0 ? n.b : least;
return least;
}
static void print(Node head){
for(Node n=head; n.next!=null; n=n.next)
System.out.println(n.b.title);
}
static String randString(){
Random r = new Random();
int len = r.nextInt(20)+1;
char[] chars = new char[len];
for(int i=0; i<chars.length; i++)
chars[i]= (char) (r.nextInt(26)+97);
return new String(chars);
}
public static void main(String[] args) {
Node head = new Node(new Book(randString()));
Node next = head;
for(int i = 0; i<20; i++)
next = next.next = new Node(new Book(randString()));
print(head);
System.out.println("==========");
System.out.println(least(head).title);
}
}
I am trying to return all node contents that match a given String input. What I am trying to do is essentially a very simple search engine, where the user is able to type in a String and the program returns all characteristically similar contents it can find in the linked list. The linked list itself is built from a file, formatted as
<<Game’s Name 0>>\t<<Game’s Console 0>>\n
<<Game’s Name 1>>\t<<Game’s Console 1>>\n
where the lines are delimited with a \n and the game and its corresponding console are delimited with a \t.
My current methodology follows searching the linked list with a while loop, assigning a temporary value to the head and reassigning it to it's link as it goes down the list. Once the loop finds contents within a node that matches the current input, it stops the loop and returns the data found in the node. I have yet to try if this could be done with a for loop, as the while loop more than likely would not know when to continue once it has found a match. I am also unsure if the while loop argument is the most efficient one to use, as my understanding of it is very minimal. I believe !temp.equals(query) is stating "temp does not equal query," but I have a feeling that this could be done in a more efficient manner.
This is what I have so far, I will provide the entire Generic linked list class for the sake of context, but the method I am questioning is the very last one, found at line 126.
My explicitly stated question is how can I search through a linked list's contents and return those contents through the console.
import java.io.FileNotFoundException;
import java.util.Scanner;
public class GenLL<T>
{
private class ListNode
{
T data;
ListNode link;
public ListNode(T aData, ListNode aLink)
{
data = aData;
link = aLink;
}
}
private ListNode head;
private ListNode current;
private ListNode previous;
private int size;
public GenLL()
{
head = current = previous = null;
this.size = 0;
}
public void add(T aData)
{
ListNode newNode = new ListNode(aData, null);
if (head == null)
{
head = current = newNode;
this.size = 1;
return;
}
ListNode temp = head;
while (temp.link != null)
{
temp = temp.link;
}
temp.link = newNode;
this.size++;
}
public void print()
{
ListNode temp = head;
while (temp != null)
{
System.out.println(temp.data);
temp = temp.link;
}
}
public void addAfterCurrent(T aData)
{
if (current == null)
return;
ListNode newNode = new ListNode(aData, current.link);
current.link = newNode;
this.size++;
}
public T getCurrent()
{
if(current == null)
return null;
return current.data;
}
public void setCurrent(T aData)
{
if(aData == null || current == null)
return;
current.data = aData;
}
public void gotoNext()
{
if(current == null)
return;
previous = current;
current = current.link;
}
public void reset()
{
current = head;
previous = null;
}
public boolean hasMore()
{
return current != null;
}
public void removeCurrent()
{
if (current == head)
{
head = head.link;
current = head;
}
else
{
previous.link = current.link;
current = current.link;
}
if (this.size > 0)
size--;
}
public int getSize()
{
return this.size;
}
public T getAt(int index)
{
if(index < 0 || index >= size)
return null;
ListNode temp = head;
for(int i=0;i<index;i++)
temp = temp.link;
return temp.data;
}
public void setAt(int index, T aData)
{
if(index < 0 || index >= size || aData == null)
return;
ListNode temp = head;
for (int i = 0; i < index; i++)
temp = temp.link;
temp.data = aData;
}
public T search() throws FileNotFoundException {
Scanner keyboard = new Scanner(System.in);
System.out.println("Search: ");
String query = keyboard.nextLine();
ListNode temp = head;
while(!temp.equals(query))
temp = temp.link;
return temp.data;
//plus some sort of print function to display the result in the console
}
}
You can apply regex for every node's content, if the data type is string apply it if it is of some other datatype convert it into string if possible, else throw some exceptions.
I m beginner at java. I am trying to implement simple linklist structure using java.
I have written following code that inserts node at the end of the linklist.
public static Node insert(Node head,int data) {
if(head == null)
{
Node temp = new Node(data);
head = temp;
return head;
}
else
{
Node temp = new Node(data);
Node current = head;
while(current != null)
{
current = current.next;
}
current = temp;
return head;
}
}
The Node class is defined as follows
class Node {
int data;
Node next;
Node(int d) {
data = d;
next = null;
}
}
The class LinkListDemo has the insert(),display() and main() method as follows..
class LinkListDemo
{
public static Node insert(Node head,int data) {
if(head == null)
{
Node temp = new Node(data);
head = temp;
return head;
}
else
{
Node temp = new Node(data);
Node current = head;
while(current != null)
{
current = current.next;
}
current = temp;
return head;
}
}
public static void display(Node head) {
Node start = head;
while(start != null) {
System.out.print(start.data + " ");
start = start.next;
}
}
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
Node head = null;
int N = sc.nextInt();
while(N-- > 0) {
int ele = sc.nextInt();
head = insert(head,ele);
}
display(head);
sc.close();
}
}
INPUT: 4 2 3 4 1
I gave input as 4(number of nodes to be inserted) 2 3 4 1(corresponding node values)
I expected output to be 2 3 4 1
but the output is only 2.
Please help me to correct my mistake. Thanks in advance.
The problem is in the else part of your insert method. You are looping till current becomes null and then assign the new node temp to it. Assigning the reference to the new node(temp) will not append (or link) to the end of the list.
The correct way is to go to the last node and then link the new node i.e, make the last node's next point to the new node.
It should be like
while(current.next != null) {
current = current.next;
}
current.next = temp;
In your code for insert(), you should have
while(current.next != null)
{
current = current.next;
}
In your code, your current variable will always end up being null, resulting in your node not actually being inserted. This fix makes your current variable the last node in the list, so that you can set the last node's pointer to your new node.
I am inserting node using following code
public void addFirst(int e) {
if (head == null) {
head = new LinkListNode(e);
tail = head;
size = 1;
} else {
LinkListNode nextNode = new LinkListNode(e);
nextNode.setNext(head);
head = nextNode;
size++;
}
}
Working fine...
Just Change little bit code
Node current = head;
while(current.next != null)
{
current = current.next;
}
current.next= temp;
and return head
I'm trying to delete multiples nodes that meets a criteria from a linked list. The program is a bit complex so I'll get state the gist of it. The nodes in my linked list has the following characteristics (a name associated with a number):
Name Number
Dog 1
Cat 1
Rat 2
Donkey 3
Fish 1
I want to be able to delete the nodes with the number 1. My delete function:
public void Delete(Int N) {
Node current = Head;
Node previous = Head;
while (current.getNum() != N) {
if (current.getNextNode() == null) {
System.out.print("Not found");
} else {
previous = current;
current = current.getNextNode();
}
}
if (current == Head) {
Head = Head.getNextNode();
} else {
Node A = current.getNextNode();
previous.setNextNode(A);
}
}
This works but it only removes the first occurrence. I know it may be due to the lack of or appropriate loop structure but I've been working on this for hours and I'm getting confused along the way. I've tried doing a trace table manually but that's not working either.
How can the function be edited so it loops through the entire linked lists and removes the nodes that matches the criteria?
This should remove the matching Node instances from the linked list:
public void delete(int n) {
int count = 0;
Node prev = null, next;
for (Node current = head; current != null; current = next) {
next = current.getNextNode();
if (current.getNum() == n) {
count++;
if (prev != null) {
prev.setNextNode(next);
} else {
head = next;
}
} else {
prev = current;
}
}
System.out.print(count > 0 ? ("Number deleted: " + count) : "Not found");
}
Your loop while (current.getNum() != N) will end after the first occurrence of a node that has the number N. If you want to go through the entire list then the loop should look like
while (current != null) {
//do something with the list
current = current.getNextNode();
}
Specifically for this case you want to remove a node.
Node prev = null;
while (current != null) {
Node next = current.getNextNode()
if(current.getNum() == N){
//condition to remove current node has been found.
if(prev == null){
Head = next;
} else {
prev.setNextNode(next);
}
} else {
//only advance prev if we haven't deleted something
prev = current;
}
current = current.getNextNode();
}
If you want to delete a node in your linkedlist, you can use any of the following ways
a new linked list only with the nodes in which number is not equals to N
or modify the existing one.
I have used the first way, creating a new linked list with element in which number is not equals to N.
class Node {
public String name;
public int number;
public Node next;
}
public class LinkedListTest {
public static void main(String[] args) {
LinkedListTest obj = new LinkedListTest();
Node head = obj.createLinkList();
Node startPointer = head;
while (startPointer != null) {
System.out.println(startPointer.name + " " + startPointer.number);
startPointer = startPointer.next;
}
System.out.println("***********");
Node newNodeHead = obj.deleteNode(1, head);
startPointer = newNodeHead;
while (startPointer != null) {
System.out.println(startPointer.name + " " + startPointer.number);
startPointer = startPointer.next;
}
}
public Node deleteNode(int n, Node head) {
Node current = head;
Node newNodestartPointer = null;
Node newNodeCurrent = null;
while (current != null) {
if (!(current.number == n)) {
if (newNodestartPointer == null) {
newNodestartPointer = new Node();
newNodestartPointer.name = current.name;
newNodestartPointer.number = current.number;
newNodestartPointer.next = null;
newNodeCurrent = newNodestartPointer;
} else {
Node newNode = new Node();
newNode.name = current.name;
newNode.number = current.number;
newNodeCurrent.next = newNode;
newNodeCurrent = newNode;
}
}
current = current.next;
}
return newNodestartPointer;
}
public Node createLinkList() {
Node head = null;
Node newNode = new Node();
newNode.name = "Dog";
newNode.number = 1;
newNode.next = null;
head = newNode;
newNode = new Node();
newNode.name = "Cat";
newNode.number = 1;
newNode.next = null;
head.next = newNode;
Node prevNode = newNode;
newNode = new Node();
newNode.name = "Rat";
newNode.number = 2;
newNode.next = null;
prevNode.next = newNode;
prevNode = newNode;
newNode = new Node();
newNode.name = "Donkey";
newNode.number = 3;
newNode.next = null;
prevNode.next = newNode;
return head;
}
}
the method 'insertAscending' only gives me the first number even after i enter new ones. can anyone help with what i'm doing wrong? Thanks.
public class LinkedList13 {
// Private inner class Node
private class Node{
int data;
Node link;
public Node(){
data = Integer.MIN_VALUE;
link = null;
}
public Node(int x, Node p){
data = x;
link = p;
}
}
// End of Node class
public Node head;
public LinkedList13(){
head = null;
}
public void insertAscending(int data){
Node node = new Node();
node.data = data;
if (head == null)
head = node;
Node p = head;
while (p.link != null)
{
if (p.link.data > data)
{ node.link = p.link;
p.link = node;
break;
}
p= p.link;
}
}
}
Hint: is (p.link != null) ever true?
First of all, you should return after setting the head of the list (when the first element is added).
Second of all, you should handle the case where the newly inserted node is the smallest in the list (and therefore should come first). Your loop never compares the added node to the head of the list.
Finally, if the added element wasn't inserted in the while loop, it should be inserted after the while loop.
public void insertAscending(int data)
{
Node node = new Node();
node.data = data;
if (head == null) {
head = node;
return;
} else if (node.data < head.data) {
node.link = head;
head = node;
return;
}
Node p = head;
boolean added=false;
while (p.link != null)
{
if (p.link.data > data)
{
node.link = p.link;
p.link = node;
added = true;
break;
}
p = p.link;
}
if (!added)
p.link = node;
}
Check out your if condition if(p.link.data > data) the only way a node gets into the list is when that is true. This means, that, if the value of data being inserted it greater than (or equal to) everything that's been inserted so far, it will be discarded.
An easy way to fix this is change break to return and add p.link=node at the end (after the loop).