I need help with a Circular Doubly Linked List in Java.
This is my code (originally coded by "sanfoundry"; it uses interfaces):
LinkedList.java:
public class LinkedList<T extends Comparable<T>> implements
ILinkedList<T> {
private ILinkedListNode<T> head;
private ILinkedListNode<T> end;
private int size;
public LinkedList() {
head = null;
end = null;
head = null;
size = 0;
}
#Override
public void append(T element) {
ILinkedListNode<T> tempNode = new LinkedListNode(element, null, null);
if (head == null) {
head = tempNode;
end = head;
} else {
tempNode.setPrev(end);
tempNode.setNext(tempNode);
end = tempNode;
}
size++;
}
// should return element at position "index"
#Override
public T get(int index) {
return null;
}
#Override
public int size() {
return size;
}
#Override
public ILinkedListNode<T> getHead() {
return head;
}
}
Now I need help to get it working. Did I do something wrong and what do I have to code in method "public T get (int index)"? Sorry, but I'm a Java noob :(
EDIT: Is this a possible solution?
public T get(int index) {
T element = null;
if (index == 0) {
element = head.getElement();
} else if (index == size()-1) {
element = head.getPrev().getElement(); // end.getElement() also possible
} else {
ILinkedListNode<T> temp = head;
for (int i = 0; i < index; i++) {
temp = temp.getNext();
}
element = temp.getElement();
}
return element;
}
You should traverse the LinkedList, keeping track of your current position as you go. When your current position is equal to the index passed in, then you can return the T from that node.
Read about traversing a linked list here.
Try making some test cases. Ideally you'll want to use a real test framework but using a normal main method could work. For example:
public static void main(String[] args) {
ILinkedList<String> a = new LinkedList<String>();
System.out.println(a.size()); // 0
System.out.println(a.getHead()); // null
a.append("foo");
System.out.println(a.size()); // 1
System.out.println(a.get(0)); // "foo"
System.out.println(a.get(1)); // decide yourself what this should result in
a.append("bar");
System.out.println(a.size()); // 2
System.out.println(a.get(0)); // "foo"
System.out.println(a.get(1)); // "bar"
a.append("baz");
System.out.println(a.size()); // 3
System.out.println(a.get(0)); // "foo"
System.out.println(a.get(1)); // "bar"
System.out.println(a.get(2)); // "baz"
}
Expand the test as necessary. See if the code returns what you expect it to, or if the code never returns, or throws an exception, etc.... The easiest way to check whether your code is running properly is, after all, to actually run it.
Hint: the code, as of this writing, has some errors.
Also, if the code can run as expected, consider:
Traversing the nodes backward if it's faster than forward.
Using a recursion instead of iteration.
Related
I'm having trouble writing a method that appends all elements in a method's parameter list to the end of another list. The method is supposed to return true if the list was changed, and false otherwise.
For example, if the original list was 1->6->5, and the other list is 3->8->2. After the call, the list is now 1->6->5->3->8->2.
I'm having trouble with the Boolean return statements as I am confused how they link into the logic of the list. I also don't know how far the pointers need to move in order to append the lists. The whole thing can be done in one loop but I don't know how.
public boolean appendList(DynamicList othrList) {
for (DynamicNode tmp = head; tmp != null; tmp.getNext()) {
if(tmp == null) {
DynamicNode ex = otherList.getList;
tmp.setNext(ex);
}
return true;
}
return false;
}
Full code:
public class DynamicNode {
private Object info; // the data in the node
private DynamicNode next; // refers to the next node on the list
public DynamicNode(Object x, DynamicNode n) {
info = x;
next = n;
}
public Object getInfo() { return info; }
public DynamicNode getNext() { return next; }
public void setInfo(Object x) { info = x; }
public void setNext(DynamicNode n) { next = n; }
public String toString() { return info.toString(); }
}
class DynamicList {
private DynamicNode head;
public DynamicList() { head = null; }
public DynamicList(DynamicNode head) { this.head = head; }
public boolean isEmpty() { return head == null; }
public DynamicNode getList() { return head; }
// The problem
public boolean appendList(DynamicList othrList) {
for (DynamicNode tmp = head; tmp != null; tmp.getNext()) {
if(tmp == null) {
DynamicNode ex = otherList.getList;
tmp.setNext(ex);
}
return true;
}
return false;
}
}
For the code in question (with comments in the code holding additional explanation).
This does fulfill the requirement: "if the original list was 1->6->5, and the other list is 3->8->2. After the call, the list is now 1->6->5->3->8->2."
It appends the elements(nodes) so after appending both list share the same nodes. Which should be okay. However this implies that if a node in "othrlist" changes after appending, it will also change in the list. Often this is the expected behavior.
So it is "shallow" and does not create any unessary (deep-)copies of elements.
To sum up this behaves the way, the aproach the op choose in his method does: One(!) loop, only appending and not duplicating.
public boolean appendList(DynamicList othrList) {
DynamicNode tmp = head;
if(tmp == null) { //special case empty list
head = othrList.getList();
return null != head; //early exit, list changed if head is no longer null.
}
while (tmp.getNext() != null) tmp = tmp.getNext(); //search for the last element
tmp.setNext(othrList.getList()); //link last element to head of other.
return null != tmp.getNext(); //list changed if tmp.next is no longer null(as it was before).
}
(disclaimer: for school, so cant import other Java utilities)
So I have to merge sort on a linked list, and I have almost all of it down. Here it is:
class musicNode {
String track; // The name of the track
int played= 0; // The number of times played
int shuffleTag= 0; // For shuffling
musicNode next;
public musicNode() { // Here's how we construct an empty list.
next = null;
}
public musicNode(String t) {
track = t; next = null;
}
public musicNode(String t, musicNode ptr) {
track = t; next = ptr;
}
public boolean LTTrack(musicNode x) { // Compares tracks according to alphabetical order on strings
if (this.track.compareTo(x.track)<=0) return true;
else return false;
}
};
// This class represents a playlist;
// We assume that each track appears at most once in the playlist
public class MusicPlayer {
protected musicNode head = null; // Pointer to the top of the list.
int length=0; // the number of nodes in the list.
boolean debug= false;
public MusicPlayer() {
}
public void setToNull() {
head = null;
}
public boolean isEmpty() {
return head == null;
}
public musicNode head() {
return head;
}
void insertTrack(String name) { // Inserts a new track at the top of the list.
musicNode temp= new musicNode(name, head);
head= temp;
length++;
}
void sortTrack() { // TODO
musicNode main = this.head;
mergeSort(main);
}
public musicNode mergeSort(musicNode head) {
if ((head == null) || (head.next == null)){
return head;
}
musicNode left = head;
musicNode right = head.next;
while((right != null) && (right.next != null)){
head = head.next;
right = (right.next).next;
}
right = head.next;
head.next = null;
return merge(mergeSort(left), mergeSort(right));
}
There also this JUnit test:
public void testSortMixed() {
MusicPlayer trackList= new MusicPlayer();
trackList.insertTrack("d");
trackList.insertTrack("b");
trackList.insertTrack("e");
trackList.insertTrack("a");
trackList.insertTrack("c");
MusicPlayer trackListTwo= new MusicPlayer();
trackListTwo.insertTrack("e");
trackListTwo.insertTrack("d");
trackListTwo.insertTrack("c");
trackListTwo.insertTrack("b");
trackListTwo.insertTrack("a");
trackList.sortTrack();
musicNode tmp= trackList.head;
musicNode tmp2= trackListTwo.head;
for(int i=0; i< 5; i++){
assertEquals(tmp2.track, tmp.track);
tmp2= tmp2.next;
tmp=tmp.next;
}
}
The problem is that it sorts according to the last track you insert, and only from then on. So say you insert alphabets from a-f, but the last one you insert was "c", itll only show you "cdef". But if the last one was "a" then it works as intended.
So how it works is, when you insert a track it gets inserted onto the beginning of the list, not end, becoming the head. I feel like that may be whats messing it up, as I adapted and looked from my notes and online which insert at the bottom.
I dont know how to account for this though. Also I know it sorts based on what was inserted last (in the JUnit test above it sorts to "cde" because I created a main function and played around with it)
ANY help appreciated.
The key point is the second line in the method sortTrack:
void sortTrack() {
musicNode main = this.head;
this.head = mergeSort(main); // you forgot to set the head of linked list to the merged
}
I'd tested it in my laptop and everything goes okay now xD
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've been working through some standard coding interview questions from a book I recently bought, and I came across the following question and answer:
Implement an algorithm to find the nth to last element in a linked list.
Here's the provided answer:
public static LinkedListNode findNtoLast(LinkedListNode head, int n) { //changing LinkedListNode to ListNode<String>
if(head == null || n < 1) {
return null;
}
LinkedListNode p1 = head;
LinkedListNode p2 = head;
for(int j = 0; j < n-1; ++j) {
if(p2 == null) {
return null;
}
p2 = p2.next;
}
if(p2 == null) {
return null;
}
while(p2.next != null) {
p1 = p1.next;
p2 = p2.next;
}
return p1;
}
I understand the algorithm, how it works, and why the book lists this as its answer, but I'm confused about how to access the LinkedListNodes to send as an argument to the method. I know that I'd have to create a LinkedListNode class (since Java doesn't already have one), but I can't seem to figure out how to do that. It's frustrating because I feel like I should know how to do this. Here's something that I've been working on. I'd greatly appreciate any clarification. You can expand/comment on my code or offer your own alternatives. Thanks.
class ListNode<E> {
ListNode<E> next;
E data;
public ListNode(E value) {
data = value;
next = null;
}
public ListNode(E value, ListNode<E> n) {
data = value;
next = n;
}
public void setNext(ListNode<E> n) {
next = n;
}
}
public class MyLinkedList<E> extends LinkedList {
LinkedList<ListNode<E>> list;
ListNode<E> head;
ListNode<E> tail;
ListNode<E> current;
ListNode<E> prev;
public MyLinkedList() {
list = null;
head = null;
tail = null;
current = null;
prev = null;
}
public MyLinkedList(LinkedList<E> paramList) {
list = (LinkedList<ListNode<E>>) paramList; //or maybe create a loop assigning each ListNode a value and next ptr
head = list.getFirst();
tail = list.getLast(); //will need to update tail every time add new node
current = null;
prev = null;
}
public void addNode(E value) {
super.add(value);
//ListNode<E> temp = tail;
current = new ListNode<E>(value);
tail.setNext(current);
tail = current;
}
public LinkedList<ListNode<E>> getList() {
return list;
}
public ListNode<E> getHead() {
return head;
}
public ListNode<E> getTail() {
return tail;
}
public ListNode<E> getCurrent() {
return current;
}
public ListNode<E> getPrev() {
return prev;
}
}
How can the LinkedListNode head from a LinkedList?
Update: I think part of my confusion comes from what to put in the main method. Do I need to create a LinkedList of ListNode? If I do that, how would I connect the ListNodes to each other? How would I connect them without using a LinkedList collection object? If someone could show me how they would code the main method, I think that would put things into enough perspective for me to solve my issues. Here's my latest attempt at the main method:
public static void main(String args[]) {
LinkedList<ListNode<String>> list = new LinkedList<ListNode<String>>();
//MyLinkedList<ListNode<String>> list = new MyLinkedList(linkedList);
list.add(new ListNode<String>("Jeff"));
list.add(new ListNode<String>("Brian"));
list.add(new ListNode<String>("Negin"));
list.add(new ListNode<String>("Alex"));
list.add(new ListNode<String>("Alaina"));
int n = 3;
//ListIterator<String> itr1 = list.listIterator();
//ListIterator<String> itr2 = list.listIterator();
LinkedListNode<String> head = new LinkedListNode(list.getFirst(), null);
//String result = findNtoLast(itr1, itr2, n);
//System.out.println("The " + n + "th to the last value: " + result);
//LinkedListNode<String> nth = findNtoLast(list.getFirst(), n);
ListNode<String> nth = findNtoLast(list.getFirst(), n);
System.out.println("The " + n + "th to the last value: " + nth);
}
In an attempt to connect the nodes without using a custom linked list class, I have edited my ListNode class to the following:
class ListNode<E> {
ListNode<E> next;
ListNode<E> prev; //only used for linking nodes in singly linked list
ListNode<E> current; //also only used for linking nodes in singly linked list
E data;
private static int size = 0;
public ListNode() {
data = null;
next = null;
current = null;
if(size > 0) { //changed from prev != null because no code to make prev not null
prev.setNext(this);
}
size++;
}
public ListNode(E value) {
data = value;
next = null;
current = this;
System.out.println("current is " + current);
if(size > 0) {
prev.setNext(current);//this line causing npe
}
else
{
prev = current;
System.out.println("prev now set to " + prev);
}
size++;
System.out.println("after constructor, size is " + size);
}
public ListNode(E value, ListNode<E> n) {
data = value;
next = n;
current = this;
if(size > 0) {
prev.setNext(this);
}
size++;
}
public void setNext(ListNode<E> n) {
next = n;
}
}
As is right now, the program will run until it reaches prev.setNext(current); in the single argument constructor for ListNode. Neither current nor prev are null at the time this line is reached. Any advice would be greatly appreciated. Thanks.
You don't actually need a separate LinkedList class; the ListNode class is a linked list. Or, to state it differently, a reference to the head of the list is a reference to the list.
The use of head, tail, current, prev in the sample code you posted has come from a double-linked list which is a data type that has links in both directions. This is more efficient for certain types of applications (such as finding the nth last item).
So I would recommend renaming your ListNode class to LinkedList and renaming next to tail.
To add a new item to the list you need a method that creates a new list with the new item at it's head. Here is an example:
class LinkedList<E> {
...
private LinkedList(E value, LinkedList<E> tail) {
this.data = value;
this.tail = tail;
}
public LinkedList<E> prependItem(E item) {
return new LinkedList(item, this);
}
}
Then to add a new item i to list you use list = list.prependItem(i);
If for some reason you need to always add the items to the end, then:
private LinkedList(E value) {
this.data = value;
this.tail = null;
}
public void appendItem(E item) {
LinkedList<E> list = this;
while (list.tail != null)
list = list.tail;
list.tail = new LinkedList<>(item);
}
However this is obviously pretty inefficient for long lists. If you need to do this then either use a different data structure or just reverse the list when you have finished adding to it.
Incidentally, an interesting side effect of this is that a reference to any item in the list is a reference to a linked list. This makes recursion very easy. For example, here's a recursive solution for finding the length of a list:
public int getLength(LinkedList list) {
if (list == null) {
return 0;
} else {
return 1 + getLength(list.getTail());
}
}
And using this a simple (but very inefficient!) solution to the problem you provided - I've renamed the method to make its function more obvious:
public LinkedList getTailOfListOfLengthN(LinkedList list, int n) {
int length = getLength(list);
if (length < n) {
return null;
} else if (length == n) {
return list;
} else {
return getTailOfLengthN(list.getTail(), n);
}
}
And to reverse the list:
public LinkedList<E> reverse() {
if (tail == null) {
return this;
} else {
LinkedList<E> list = reverse(tail);
tail.tail = this;
tail = null;
return list;
}
}
As I hope you can see this makes the methods a lot more elegant than separating the node list classes.
Actually you have created a linked list with you class ListNode.
A linked list is made of a node and a reference to another linked list (see the recursion?).
I'm trying to make a custom linked list, so far I've figured out how to make the general structure and the two easiest methods (insertFirst and deleteFirst). The next thing I want to do is make a get method that takes the index of a link and then returns the string at that location. I don't have any index or address assigned to each link, so I don't see how to refer to a specific location in my linked list. I see that if I write first.next I get the second item, and first.next.next I get the third item.. But I need to figure out how to make my index parameter (the one passed into the get method) correlate with the proper location in my list. How can I do this?
Here's my code:
Test code:
class LinkedListTest {
public static void main(String[] args)
{
LinkedList list = new LinkedList();
list.insertFirst("cat");
list.insertFirst("dog");
list.insertFirst("fish");
list.insertFirst("cow");
list.insertFirst("horse");
list.insertFirst("pig");
list.insertFirst("chicken");
System.out.println(list.get(1));
}
}
My class:
public class LinkedList
{
private Link first;
public LinkedList()
{
first = null;
}
public void insertFirst(String word)
{
Link link = new Link(word);
link.next = first;
first = link;
}
public String deleteFirst()
{
Link temp = first;
first = first.next;
return temp.toString();
}
public String get(int index)
{
// the following is just to show that I can access different links
// by adding more .next's after first--- but i need a way to access
// the correct link based on the index passed in
// String second = first.next.item;
String third = first.next.next.item;
// String fourth= first.next.next.next.item
return third;
}
}
public class Link
{
public String item;
public Link next;
//Link constructor
public Link(String theItem)
{
item = theItem;
}
}
Assuming that get(0) returns you the first element:
If you want to put this method inside public class LinkedList:
public String get(int index)
{
assert( index >= 0 )
Link current = this.first;
while (index > 0) {
index--;
current = current.next;
// Check to see if this is out of bounds of the links
if (current == Null) {
// Since you are returning a String, you can also return
// some kind of a flag to say that the index is out of bounds
return Null;
}
}
return current.item;
}
Alternatively, you can also implement this inside public class Link:, but this is not advisable since it wastes space on your call stack:
public String get(int index)
{
assert ( index >= 0 )
if ( index == 0 ) {
return this.item;
} else {
index--;
if ( next == null ) {
return Null;
}
return next.get(index)
}
}
and inside public class LinkedList:
public String get(int index)
{
return first.get(index);
}
Hope this helps!
LinkedList is supposed to have O(n) for finding the element.
So essentially what this means is that you need to keep doing element.next till you reach the nth index.
First of all, if you are creating your own LinkedList class, you should name it as such rather than using the existing LinkedList class. So, rather you can use MyLinkedList
Second, you can't access the elements in the LinkedList by index. That is not how LinkedList works, or should work if you are creating your own. Rather you get them based on the value. So, you should pass the value to your get method, and iterate through your LinkedList to get the appropriate Link with the given value.
recursive
public String get(int index)
{
assert index >= 0;
return get(index, first);
}
public String get(int index, Link cursor) {
if (cursor == null) {
return null;
} else if (index == 0) {
return cursor.toString();
} else {
return get(index-1, cursor.next);
}
}
iterative
public String get(int index)
{
assert index >= 0;
Link cursor = first;
while (index > 0) {
if (cursor == null) {
return null;
}
cursor = cursor.next;
index--;
}
return cursor.toString();
}
This should help you with what you need:
http://www.dreamincode.net/forums/topic/143089-linked-list-tutorial/