I am working on an exercise and I ran into a problem.
In NodeList, create a static method Node arrayToNode(String[] arr)
which converts a String array into a list. Your method should create a first Node,
and then go through the rest of the array, creating a Node at each step, and using
append to put the created Node at the end of the list. Test this method on the
command line arguments. What happens if the array is empty?
Currently my code is like this
public static Node arrayToNode(String[] arr) {
Node first = new Node(arr[0]);
ArrayList<Node> list = new ArrayList<Node>();
for(int i=1; i<arr.length;i++){
list.add(new Node(arr[i]));
}
}
as you can see there is no return statement YET.
I am not sure if the person who wrote the exercise made a mistake by writing Node instead of void but I cannot ask him.
The append method is
public void append(Node fin){
if(next==null)
next=fin;
else
append(next);
}
and the instance variables and the constructor is as follows:
public String value;
public Node next;
public Node(String s){
value =s;
next=null;
}
I am quite unsure what it means to put the node at the end of the list as the ArrayList keeps on expanding.
Also, I have questions about using the deploying the append method as in how to even use it in the TestNode class.
Thanks for the comment.
I have now realized what the problem was and have made appropriate changes.
public static Node arrayToNode(String[] arr){
Node first = new Node(arr[0]);
for(int i=1; i<arr.length;i++){
Node nd = new Node(arr[i]);
nd.append(nd);
first.next=nd;
}
return first;
}
could you see if this is correct?
Unless I'm missing something, your append method should be this:
public void append(Node fin) {
if (next == null)
next = fin;
else
next.append(fin); // <- this line changed
}
That will append fin down the line until it reaches the end of the list while the way you have it in your OP will give infinite recursion.
If it's supposed to be that way then creating the list is very simple. You can just append each value to the original one.
public class Node {
public static void main(String[] args) {
Node begin = arrToLL(new String[] {
"hello 1", "hello 2", "hello 3", "hello 4", "hello 5"
});
while (begin != null) {
System.out.println(begin.val);
begin = begin.next;
}
}
static Node arrToLL(String[] arr) {
if (arr == null) {
return null;
} else if (arr.length == 0) {
return new Node("null");
}
int ind = 0;
Node begin = new Node(arr[ind++]);
while (ind < arr.length) {
begin.append(new Node(arr[ind++]));
}
return begin;
}
/* instance */
String val;
Node next;
Node(String val) { this.val = val; }
void append(Node ap) {
if (next == null) {
next = ap;
} else {
next.append(ap);
}
}
}
Output is:
hello 1
hello 2
hello 3
hello 4
hello 5
Inside the "to list" loop you could also "shuffle ahead" by assigning next to a variable like in my println loop. That way you aren't taking advantage of the "pass through".
public static Node arrayToNode(String[] arr){
Node first = new Node(arr[0]);
for(int i=1; i<arr.length;i++){
Node nd = new Node(arr[i]);
nd.append(nd); // <- appends nd to itself
first.next=nd; // <- always assigns the new value to first
}
return first;
}
That's getting closer but I've commented the two lines that are in err. I think what you will end up with is:
First Node with the first array element linked to
A second Node with the last array element linked to
Itself (the second Node)
You can do this without append but you need another variable to shuffle:
public static Node arrayToNode(String[] arr){
Node first = new Node(arr[0]);
Node current = first;
for(int i=1; i<arr.length;i++){
Node nd = new Node(arr[i]);
current.next = nd; // <- append the new node to the last
current = nd; // <- shuffle ahead to the new one
}
return first;
}
Otherwise if I'm correct in thinking append had an error you can do something closer to my main example (including the shuffle if you want and a for loop works just as well).
Related
Small problem i am having with a program here. I am trying to create a program that adds Words to Linked Lists within a Array depending on their hashCode, determined by my hashFunction. If they have the same value for their hashCode they get added into a Linked List. I have a small count method that counts how many times a word is in the List. It works by computing the value for their hashFunction. It then goes to that value in the array, and iterates through the LinkedList until it reaches a Null value. It has a count variable which is incremented each time it finds the word in the list. This is my code:
public class test{
public static class Node<T>{
public T data;
public Node<T> next;
public Node(){
}
public Node(T data, Node<T> next)
{
this.data = data;
this.next = next;
}
}
static Node[] array = new Node[512];
public static void add(String word){
int position = hashFunction(word);
if(array[position] == null){
array[position] = new Node(word, null);
}else{
Node newHead = new Node(word, array[position]);
array[position] = newHead;
}
}
public static void remove(String word){
int remove = hashFunction(word);
Node head = array[remove];
if(head.data == word){
head = head.next;
System.out.println("Found");
}else if(head.data != word){
for(; array[remove] != null; array[remove] = array[remove].next){
if(array[remove].data == word){
array[remove] = array[remove].next;
}
}
System.out.println("Yusuf");
}
}
public static int count(String word){
int number = 0;
int position = hashFunction(word);
for(; array[position] != null; array[position] = array[position].next){
if(array[position].data == word){
number++;
}
}
System.out.println(number);
return number;
}
public static int hashFunction(String a){
int sum = 1;
for(int i = 0; i<a.length(); i++){
char b = a.charAt(i);
int value = (int) b;
sum *= value;
}
return sum % array.length;
}
public static void addthings(String word, int n){
for(int i = 0; i<n; i++){
add(word);
}
}
public static void main(String[] args) {
addthings("abc", 500000);
count("abc");
count("abc");
count("abc");
count("abc");
}
}
My issue is the first time I add values in it and check how many times it occurs it works fine, but any more calls to the Count method after that returns 0 for some reason.
I have another issue too which is my remove method isn't removing the items from the Linked List I want it too. The code iterates through the List, and when it finds the item which is meant to be removed, it removes the pointer from there and points it to the next value. This isn't working however.
Can someone show me how to fix these two issues please?
Thanks.
In your function if you write something Node head it means you are creating some local instance for a Node. If you set head = head.next this will simply change the state of your local instance variable not the state of your array.
You are checking if the first node contains the data which you are looking and trying to remove it then you have to remove it from your source Array(Array in which your references reside).So you can write something like this:
if(head.data == word)
array[remove] = head.next;
This was an example. The point is that you are not chaning things in your array but in your local variable.
public static void remove(String word){
int remove = hashFunction(word);
Node head = array[remove];
if(head.data == word){
head = head.next;
System.out.println("Found");
}else if(head.data != word){
for(; array[remove] != null; array[remove] = array[remove].next){
if(array[remove].data == word){
array[remove] = array[remove].next;
}
}
System.out.println("Yusuf");
}
}
A second mistake is in second clause where you just set array[remove] = array[remove].next;
It will break your linkedlist into two different linkedlist. Suppose you have 4 elements in linkedlist A,B,C,D and you remove B and there were pointers like this A->B->C->D then you are adding no pointers from A -> C. Here you break your linkedlist.
You can use while loop that will work easily.
I am currently working on my own Java class called LString, which is meant to convert back and forth between linked lists of characters and Strings.
I am having issues with my toString() method, specifically keeping track of the "head" of the linked list in order to loop through it and concatenate the characters into a new string. While researching, I read that I am supposed to keep track of the head of the list somehow, but I can't figure out how to implement it.
Any help would be greatly appreciated!
Edit: The error message I am receiving is:
LString.java:79: error: cannot find symbol
ListNode current = this.front;
public class LString{
private static int length;
// ListNode constructors
// Creates a new ListNode with characters stored in variable "data" and
// Node named next
private class ListNode{
char item;
ListNode next;
private ListNode(){
}
// creates a new ListNode that has the value and links to the specified ListNode
private ListNode(char item, ListNode next){
this.item = item;
this.next = next;
}
// given a character, creates a new ListNode that doesn't link to anything
private ListNode(char item){
this.item = item;
this.next = null;
}
}
public LString(){
this.length = 0;
ListNode front = new ListNode();
}
//LString
// Takes in a String object and loops until it has added all characters to a new linked list
public LString(String original){
ListNode front;
this.length = 1; // length keeps track of number of nodes
if (original.charAt(0) == 0){ // creates a new ListNode if it is an empty string
front = new ListNode();
}
else {
front = new ListNode(original.charAt(0));
}
//System.out.println("this is happening " + front.item);
//ListNode current = front;
for (int index = 1; index < original.length(); index++) {
front.next = new ListNode(original.charAt(index), front.next);
front = front.next;
//System.out.println("strings: " + front.item);
length++;
}
//System.out.println("length: " + length);
}
// returns length of the LString object
public int length(){
return this.length;
}
// toString takes an LString object and converts it to a string
public String toString(){
StringBuilder newString;
ListNode current = this.front;
while (current.next != null){
newString.append(current.item);
current = current.next;
}
return newString.toString();
}
public static void main(String[] args){
LString stuffTest = new LString("hello");
int valueOf = stuffTest.length();
System.out.println(stuffTest.length());
String testMeWhy = stuffTest.toString();
}
}
The general pattern for building a linked list by appending to the end is:
At the beginning:
head = null;
tail = null;
To append newNode to the list:
if (head == null) {
head = newNode;
} else {
tail.next = newNode;
}
tail = newNode;
I think you're trying to do this by keeping just one pointer in the list class, which doesn't work very well. Also, doing things using this pattern means you don't have to have a "special" node at the front of the list, unless there's some other good reason to. It looks like you were trying to use new ListNode() with no arguments to create some kind of special node, but only sometimes. It's unnecessary and just makes things more complicated.
Your basic problem is that there should be only one front, and it should be a class member and not a local variable. That is how your LString class "keeps track" of the first node.
public class LString {
private ListNode front = null;
private int size = 0;
...
This will get you started and allow you to maintain the actual list. Your other LString methods will also need some work, but once you get past this problem you should be able to use your debugger to step through the code and solve the remaining issues yourself.
Given singly Linked List: 1 -> 2 -> 3 -> 4 -> 5 -> null
Modify middle element as doubly Linked List Node
here middle element is 3
3 -> next should point to 4
3 -> prev should point to 1
Can any one suggest how can it be done ? interviewer gave me hint use interface. but I couldn't figure it out how.
I have to iterate over this linked list and print all the node and when it reaches to the middle, print where next and prev is pointing to, then print till the end of the list.
Expected output : 1, 2, Middle: 3, Prev: 1, Next: 4, 5
I'm facing problem in adding the middle node.
So, this "works", but if this is expected to be answered on an interview, it is way too much work.
LinkedList
public class LinkedList {
public interface Linkable<V, L extends Linkable> {
V getValue();
L getNext();
void setNext(L link);
}
public static class Node implements Linkable<Integer, Linkable> {
int value;
Linkable next;
Node(int value) {
this.value = value;
}
#Override
public Integer getValue() {
return value;
}
#Override
public Linkable getNext() {
return next;
}
#Override
public void setNext(Linkable link) {
this.next = link;
}
}
private Linkable head;
public boolean isEmpty() {
return this.head == null;
}
public Linkable getHead() {
return head;
}
public void add(int v) {
Node next = new Node(v);
if (isEmpty()) {
this.head = next;
} else {
Linkable tmp = this.head;
while (tmp.getNext() != null) {
tmp = tmp.getNext();
}
tmp.setNext(next);
}
}
}
Interface
interface DoublyLinkable<V, L extends LinkedList.Linkable> extends LinkedList.Linkable<V,L> {
LinkedList.Linkable getPrev();
void setPrev(LinkedList.Linkable prev);
}
DoubleNode
public class DoubleNode extends LinkedList.Node implements DoublyLinkable<Integer, LinkedList.Linkable> {
LinkedList.Linkable prev;
public DoubleNode(int value) {
super(value);
}
#Override
public LinkedList.Linkable getPrev() {
return prev;
}
#Override
public void setPrev(LinkedList.Linkable prev) {
this.prev = prev;
}
}
Driver
Outputs
1, 2, Middle: 3, Prev: 1, Next: 4, 5
public class Driver {
public static LinkedList getList() {
LinkedList list = new LinkedList();
for (int i = 1; i <= 5; i++) {
list.add(i);
}
return list;
}
public static void main(String[] args) {
LinkedList list = getList();
LinkedList.Linkable head = list.getHead();
LinkedList.Linkable beforeMiddle = null;
LinkedList.Linkable middle = list.getHead();
LinkedList.Linkable end = list.getHead();
if (head != null) {
// find the middle of the list
while (true) {
if (end.getNext() == null || end.getNext().getNext() == null) break;
beforeMiddle = middle;
middle = middle.getNext();
end = end.getNext().getNext();
}
// Replace middle by reassigning the pointer to it
if (beforeMiddle != null) {
DoubleNode n = new DoubleNode((int) middle.getValue()); // same value
n.setPrev(list.getHead()); // point back to the front
n.setNext(middle.getNext()); // point forward to original value
beforeMiddle.setNext((DoublyLinkable) n);
middle = beforeMiddle.getNext();
}
// Build the "expected" output
StringBuilder sb = new StringBuilder();
final String DELIMITER = ", ";
head = list.getHead();
boolean atMiddle = false;
if (head != null) {
do {
if (head instanceof DoublyLinkable) {
atMiddle = true;
String out = String.format("Middle: %d, Prev: %d, ", (int) head.getValue(), (int) ((DoublyLinkable) head).getPrev().getValue());
sb.append(out);
} else {
if (atMiddle) {
sb.append("Next: ");
atMiddle = false;
}
sb.append(head.getValue()).append(DELIMITER);
}
head = head.getNext();
} while (head != null);
}
sb.setLength(sb.length() - DELIMITER.length());
System.out.println(sb.toString());
}
}
}
By definition, a single-linked list consists of single-linked nodes only, and a double-linked consists of double-linked nodes only. Otherwise. it is neither.
By definition the field prev of a double-linked list must point to the previous element.
Whatever you are supposed to build. It's something not well specified. So if you really were asked this in an interview (and did not misunderstand the question - maybe he wanted you to point out that ghis violates the interface?) this is a case for the code horror stories of http://thedailywtf.com/ - section "incompetent interviewers".
If you haven't, you'd better define a lenght() function so given one linked list you can know how many nodes does it have.
Thanks to the response of Cereal_Killer to the previous version of this answer, I noticed that the list is firstly a singly linked list, and you just have to make the middle node be linked both to the next node and to some previous node.
Now I guess that you have defined two structures (Struct, Class or whatever depending on the language you're using). So lets say you have Node_s defined as a node with only a next pointer, and Node_d with both a next and a prev pointer. (Node_d may inherite from Node_s so you just have to add the prev attribute in the child class). Knowing this, the code above should be doing what you need:
function do_it(my_LinkedList linkedList){
int i_middle;
int length = linkedList.length();
if ( (length ÷ 2 ) != 0 ) i_middle = length / 2;
else return -1;
Node_s aux = linkedList.first();
int index = 0;
Node_d middle= null;
while (aux != null) {
if (index == i_middle - 1){ //now aux is the middle's previous node
middle.data = aux.next.data; //aux.next is the middle singly node, we assignate the data to the new double linked node
middle.prev = aux; //as we said, aux is the prev to the middle
midle.next = aux.next.next; //so aux.next.next is the next to the middle
print(what you need to print);
}else {
print("Node " + index " next: "+ aux.next);
}//end if
index++;
aux = aux.next;
} //end while
}//end function
This previous code should be doing what you need. I wrote the answer in some kind of pseudo-java code so if you're not familiar with Java or don't understand what my pseudo-code does, please let me know. Anyway, the idea of my code may present some troubles depending on the language you're working with, so you'll have to adapt it.
Note that at the end of the execution of this program, your data structure won't be a singly linked list, and neither a double one, since you'll have linkedList.length() - 1 nodes linked in a signly way but the middle one will have two links.
Hope this helps.
I am learning Linked List in Java and I am trying to add numbers to the tail, say a 10 Numbers. However, after insertion I am only able to retrieve the last two numbers, I don't understand what I am doing wrong. Here is my code:
import java.util.*;
public class LinkTry
{
public static void main(String args[])
{
Scanner sx = new Scanner(System.in);
Node N = new Node();
for(int i=0;i<10;i++)
{
Node last = new Node();
while(N.link!=null)
N=N.link;
last.data = sx.nextInt();
N.link = last;
}
System.out.println("");
for(Node x=N;x!=null;x=x.link)
System.out.print("-->"+x.data);
}
public static class Node
{
int data;
Node link;
}
}
I am having a bit trouble how address is passed on here, an answer that explains the memory addressing in Linked list would be very helpful.
import java.util.Scanner;
public class LinkTry
{
public static void main(String args[])
{
Scanner sx = new Scanner(System.in);
Node first = null;
Node last = null;
for(int i=0;i<10;i++) {
Node current = new Node();
current.data = sx.nextInt();
if (first == null) {
first = current;
last = current;
} else {
last.link = current;
last = current;
}
}
System.out.println("");
for(Node x=first;x!=null;x=x.link)
System.out.print("-->"+x.data);
}
public static class Node
{
int data;
Node link;
}
}
The problem is that this line:
N=N.link;
causes N to no longer point to the head of the list, whereas this line:
for(Node x=N;x!=null;x=x.link)
assumes that N still points to the head of the list.
To fix this, you need to use separate variables — you need to keep separate references to the head of the list (for later reference) and the tail of the list (for appending elements there).
The problem is in the for loop. As you are iterating through the loop you have lost reference to the head of the List you started with i.e., Node N = new Node();
Issue in the for loop, highlighted between ** ** below
for(int i=0;i<10;i++)
{
Node last = new Node();
while(N.link!=null)
N=N.link;
last.data = sx.nextInt();
**N.link = last;**
}
At the end of 10 iterations, now 'N' is pointing to last but one Node. And so it is printing only last 2 items.
So the app reads from an external file a bunch of strings, each on a separate line.
For example:
and
cake
here
It is not arranged in any particular order. I need to read these letters and put them into linked list and finally sort them.
I need help on doing that:
Here is the current code:
import java.util.*;
import java.io.*;
public class LinkedList
{
static File dataInpt;
static Scanner inFile;
public static void main(String[] args) throws IOException
{
dataInpt=new File("C:\\lldata.txt");
inFile=new Scanner(dataInpt);
Node first = insertInOrder();
printList(first);
}
public static Node getNode(Object element)
{
Node temp=new Node();
temp.value=element;
temp.next=null;
return temp;
}
public static void printList(Node head)
{
Node ptr; //not pointing anywhere
for(ptr=head;ptr!=null;ptr=ptr.next)
System.out.println(ptr.value);
System.out.println();
}
public static Node insertInOrder()
{
Node first=getNode(inFile.next());
Node current=first,previous=null;
Node last=first;
int count=0;
while (inFile.hasNext())
{
if (previous!=null
&& ((String)current.value).compareTo((String)previous.value) > 0)
{
last.next=previous;
previous=last;
}
if (previous!=null
&& ((String)current.value).compareTo((String)previous.value) < 0)
{
current.next=last;
last=current;
}
previous=current;
current=getNode(inFile.next());
}
return last;
}
}
But that gives an infinite loop with "Cat".
Here is the data file:
Lol
Cake
Gel
Hi
Gee
Age
Rage
Tim
Where
And
Kite
Jam
Nickel
Cat
Ran
Jug
Here
Okay, self-study. Split the reading and inserting. Though old and new code both have 14 lines of code,
it makes it more intelligable.
public static Node insertInOrder() {
Node first = null;
while (inFile.hasNext()) {
String value = inFile.next().toString();
first = insert(first, value);
}
return first;
}
/**
* Insert in a sub-list, yielding a changed sub-list.
* #param node the sub-list.
* #param value
* #return the new sub-list (the head node might have been changed).
*/
private static Node insert(Node node, String value) {
if (node == null) { // End of list
return getNode(value);
}
int comparison = node.value.compareTo(value);
if (comparison >= 0) { // Or > 0 for stable sort.
Node newNode = getNode(value); // Insert in front.
newNode.next = node;
return newNode;
}
node.next = insert(node.next, value); // Insert in the rest.
return node;
}
This uses recursion (nested "rerunning"), calling insert inside insert. This works like a loop, or work delegation to a clone, or like a mathematical inductive proof.
Iterative alternative
also simplified a bit.
private static void Node insert(Node list, String value) {
Node node = list;
Node previous = null;
for (;;) {
if (node == null || node.value.compareTo(value) >= 0) {
Node newNode = getNode(value);
newNode.next = node;
if (previous == null)
list = newNode;
else
previous.next = newNode;
break;
}
// Insert in the rest:
previous = node;
node = node.next;
}
return list;
}
public static Node insertInOrder()
{
Node first=getNode(inFile.next());
Node current=first,previous=null;
Node last=first;
int count=0;
while (inFile.hasNext())
{
if (previous!=null
&& ((String)current.value).compareTo((String)previous.value) > 0)
{
last.next=previous;
previous=last;
}
if (previous!=null
&& ((String)current.value).compareTo((String)previous.value) < 0)
{
current.next=last;
last=current;
}
previous=current;
current=getNode(inFile.next());
}
return last;
}
First of all, you never do anything with the last line read from the file, so that's not ever inserted. You have to read the line and create the new Node before relinking next pointers.
Then, if last and previous refer to the same Node and the data of current is larger than that of previous,
if (previous!=null
&& ((String)current.value).compareTo((String)previous.value) > 0)
{
last.next=previous;
previous=last;
}
You set last.next = last, breaking the list. From the code (in particular the absence of a sort(Node) function), it seems as though you want to sort the list as it is created. But you only ever compare each new Node with one other, so that doesn't maintain order.
For each new node, you have to find the node after which it has to be inserted, scanning from the front of the list, and modify current.next and the predecessor's next.
In relatively simple code like that in your question, a good exercise to understanding it is to work through a few interations of your loop, inspecting the values of all your local variable to see the effect of your code. You can even do it by hand if the code is simple. If it is too difficult to do by hand, your code is probably too complicated. If you can't follow it, how can you know if you are doing what you intend. For example, I could be wrong, but this appears the be the state at the top of each iteration of the loop. It starts falling apart on the third time through, and by the fourth you have a severe problem as your list becomes disjointed.
1)last = first = Lol, current = previous = null
Lol->null
2)last = first = previous = Lol, current = Cake
Lol->Lol
3)first = Lol, last = Cake, previous = Cake, current = Gel
Cake->Lol->Lol
4)first = Lol, last = Cake, previous = Cake, current = Hi
Cake->Gel, Lol->Lol
Quite honestly, if I were running the course, I would consider the correct answer to be:
List<String> list = new LinkedList<String>();
// read in lines and: list.add(word);
Collections.sort(list);
Ok, I don't remember exactly school theory about insertion sort, but here is somehow a mix of what I think it is and your code:
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class LinkedList {
public static class Node {
public String value;
public Node next;
}
static File dataInpt;
static Scanner inFile;
public static void main(String[] args) throws IOException {
inFile = new Scanner("Lol\r\n" + "Cake\r\n" + "Gel\r\n" + "Hi\r\n" + "Gee\r\n" + "Age\r\n" + "Rage\r\n" + "Tim\r\n" + "Where\r\n"
+ "And\r\n" + "Kite\r\n" + "Jam\r\n" + "Nickel\r\n" + "Cat\r\n" + "Ran\r\n" + "Jug\r\n" + "Here");
Node first = insertInOrder();
printList(first);
}
public static Node getNode(String element) {
Node temp = new Node();
temp.value = element;
temp.next = null;
return temp;
}
public static void printList(Node head) {
Node ptr; // not pointing anywhere
for (ptr = head; ptr != null; ptr = ptr.next) {
System.out.println(ptr.value);
}
System.out.println();
}
public static Node insertInOrder() {
Node current = getNode(inFile.next());
Node first = current, last = current;
while (inFile.hasNext()) {
if (first != null && current.value.compareTo(first.value) < 0) {
current.next = first;
first = current;
} else if (last != null && current.value.compareTo(last.value) > 0) {
last.next = current;
last = current;
} else {
Node temp = first;
while (current.value.compareTo(temp.value) < 0) {
temp = temp.next;
}
current.next = temp.next;
temp.next = current;
}
current = getNode(inFile.next());
}
return first;
}
}
And it works like a charm. Of course this far from optimal, both in terms of performance and code reuse.