i have a question about circularly linked lists. My linked list object has two references, first and last, and the next node of the last reference is first. I want to write a method that inserts a node into the end of the list.
void insertLast(int k) {
Node a = new Node(k);
if (first == null) {
first = last = a;
} else {
last.after = a;
a.after = first;
}
last = a
}
Is something like this possible? Have I made a mistake?
Yes, it is.
let the current last point to the new one (last.setNext(newNode))
let the new one point to the first (newNode.setNext(first))
set the last to be the new node (last = newNode)
Related
I have these folowing methods and I want to implement this in a class called LinkedBag
void replace(T oldEntry, T newEntry){}
boolean isDuplicated(T anEntry){}
void doubleBag(){}
void replace(T oldEntry,T newEntry) replaces any entry that is equal to oldEntry with the new entry newEntry. For example,suppose that replace(A,D) is called on this bag {A,B,C,A}. The resulting bag should be {D,B,C,D}
the boolean returns true if the entry anEntry appears more than
one time in the bag and false otherwise. For example, calling isDuplicated(B) on the resulting
bag in part 1 should return false, but isDuplicated(D) should return true.
void doubleBag()adds to the bag a copy of each entry that appears in the bag. For example,
calling doubleBag() on the resulting bag in part 1 should change the bag contents to {4’D, 2’B, 2’C}.
Now so far I though of getting the frequency of a node and checking if the node is duplicated like:
public boolean isDuplicated(T anEntry){
Node currentNode =firstNode;
int counter=0;
while ((counter <numberOfEntries)&&(currentNode!=null))
if(anEntry.equals(currentNode)){
return true;
}
return false;
}
and for the replace method I tried assigning values to another variables then removing them and then reassigning them again but I don't think it's right
T entry=null;
T entry1 = null;
oldEntry=entry;
newEntry=entry1;
remove(oldEntry);
entry=newEntry;
entry1=oldEntry;
add(oldEntry);
add(newEntry);
System.out.println( oldEntry+" , "+newEntry );
}
as for the double bag I still don't know how to do it.
Excuse me for my bad programming I am learning java new, and still learning the basics.
Let's just briefly look at your replace method:
T entry = null;
T entry1 = null;
// entry and entry1 are both null
oldEntry = entry;
newEntry = entry1;
// entry, entry1, oldEntry and newEntry are all null.
remove(oldEntry); // remove null
entry = newEntry; // overwriting null with null
entry1 = oldEntry; // same as previous statement
add(oldEntry); // add null
add(newEntry); // add null again
// print "null , null"
System.out.println(oldEntry + " , " + newEntry);
It's not clear what you're trying to do, but at least what's here is just a bunch of nothing. What you probably want is a little more like this:
// assuming oldEntry and newEntry are set somewhere and are correct,
// and that remove and add work as expected:
remove(oldEntry);
add(newEntry);
// And you'll want to repeat this for as many duplicates as there are of oldEntry.
As for the doubleBag method, you'll want some way to walk over entries, and then duplicate them:
Node currentNode = head;
Node newHead = null;
Node newTail = null;
while (currentNode != null) {
Node first = new Node(currentNode.data);
Node second = new Node(currentNode.data);
first.next = second;
if (newHead != null) {
newTail.next = first;
newTail = second;
} else {
newHead = first;
newTail = second;
}
currentNode = currentNode.next;
}
return newHead;
This code traverses the input list starting at head, creates two copies of the node (named first and second), links them together and appends them to a new list, which it returns at the end.
That should get you started. Also, notice how the traversal works, and see how it differs from your isDuplicated implementation (which currently has an infinite loop). I'll leave it to you to fix your implementation.
i have a Stringlist with stuff allready inside of it, this Code should replace a String in the List.
The courious thing for me is, that it works all fine if i replace the headString [0] but if I try i > 0 it wont replace it
public String replaceStringAt(int i, String text) {
Item node = head;
Item item = new Item(text);
int indexCounter=0;
while(node!=null && indexCounter < i) {
node = node.next;
indexCounter++;
}
if(i == 0) {
item.next = head.next;
head = item;
}else {
item.next = node.next;
node = item;
}
return null;
}
Suppose you want to replace the second item in the list, the entry with i = 1.
The loop leaves 'node' pointing at the old item.
Now you point the 'next' of the new item to the 'next' of the old item. So far so good.
Then you point the internal variable 'node', previously pointing at the old item, to the new item. This has no point to it.
The 'next' of the predecessor of the old item is still pointing at the old item. Nowhere do you point that predecessor to the new item. You have not linked the new item into the list.
You absolutely need to update the predecessor in the chain. You can do this with a single pointer variable, but it needs to locate the predecessor, not the item being replaced. (The item being replaced is at predecessor.next, of course).
The root cause of this might be confusion between objects and references to objects. Variables only hold references, so 'node = item' affects nothing except the variable 'node'.
I am currently doing a Cracking the Coding Interview Problem (2.4) and I am supposed to partition a linked list around a value x, such that all nodes less than x come before all nodes greater than or equal to x. However, I am really confused as to why a temporary variable "next" is needed and why is node.next nulled below it. Why can't I just do node = node.next at the end of the while loop?
I am simply creating two linked lists, before and after, and merging them together once the correct values are put into each list.
public static Node partition(Node node, int x) {
Node beforeStart = null;
Node beforeEnd = null;
Node afterStart = null;
Node afterEnd = null;
/* Partition list */
while (node != null) {
Node next = node.next;
node.next = null;
if (node.data < x) {
if (beforeStart == null) {
beforeStart = node;
beforeEnd = beforeStart;
} else {
beforeEnd.next = node;
beforeEnd = beforeEnd.next;
}
} else {
if (afterStart == null) {
afterStart = node;
afterEnd = afterStart;
} else {
afterEnd.next = node;
afterEnd = afterEnd.next;
}
}
node = next;
}
/* Merge before list and after list */
if (beforeStart == null) {
return afterStart;
}
beforeEnd.next = afterStart;
return beforeStart;
}
Why can't I just do node = node.next at the end of the while loop?
It can be done this way. After doing the partition, for each list, you need to set the last node's next pointer to NULL. This will just take two lines of code.
The example code is using next = node.next and node.next = NULL to terminate each list during the partition process, but in this case that's not needed, since the lists don't need NULL terminators until after the partition process is done.
The loop in your question removes nodes from the head of the original list, and appends them to the before list or the after list, until the original list is empty. Then it concatenates the before and after lists.
That's easy to explain and easy to understand.
It can be done without the temporary next or nulling out node.next in every iteration, but then the above description would no longer apply -- nodes would not be removed from the original list in every iteration, the before list and after list would not contain only the appropriate nodes, the operation you perform on them is not 'appending', and nodes would even appear in multiple lists for a while.
Your algorithm would suddenly be a lot more difficult to describe and understand. That is a bad thing in software development, and a bad thing in a coding interview.
I'm currently studying for a test and I don't really understand linked list that well. I was wondering if anyone could explain a few lines of code to me.
class Node{
Node next, previous;
final int value;
Node(int v){
value = v;
}
}
public class Linked{
Node start = null, end = null;
// Add a node on the end
void append(int v){
Node n = new Node(v);
if (start == null){
start = end = n;
return;
}
end.next = n;
n.previous = end;
end = n;
}
// Add a node to the front
void prepend(int v){
Node n = new Node(v);
if (start == null){
end = start = n;
return;
}
n.next = start;
start.previous = n;
start = n;
}
}
The lines that I need explained are the last 3 lines in the append and the prepend methods. The comments explain the purpose of each of the methods, but I don't understand what is actually being done in those lines of code. Thanks in advance.
append
When you wish to add a node at the end of the list, it should be linked to the current last node :
end.next = n; // the current last node points to the new node
n.previous = end; // the new node points back to the previous node
// (which is the current last node)
end = n; // the new node becomes the last node
prepend is similar :
n.next = start; // the node that follows the new node is the current first node
start.previous = n; // the previous node of the current first node is the new node
start = n; // the new node becomes the first node
The class Node shows that there are items in the list called nodes. These items keep track of the item before and after the current node (next and previous). The Linked class creates a Node object for the start and end of the list and has two methods: append will add an integer, v, to after the current node and prepend will add an integer to the node before the current node.
You are going to create a new node that will be after the tail, end of the list.
end.next = n;
Likewise, since it is doubly linked, n will now have a previous node end.
n.previous = end;
And finally since the new node is now the tail of the list we assign it to end.
end = n;
Prepend follows the similar logic. The previous head, start is going to come after the new node.
n.next = start;
Since it is doubly linked, start needs to know that the previous node is the new node.
start.previous = n;
Finally, our new node is the new head.
start = n;
Imagine as if you have a chain, every part (node) of the chain knows only the one in front of it and the one behind it.
So, now i want to append new part (node) to the end of the chain, we'll call it N.
A --> B --> C ===> A --> B --> C --> N.
In order to insert N properly i need N to know C is behind it and C to know N is in front of it. So, now i'll update c.next or in your case end.next to be N and n.previous to be end. And now my new ending is N and not C.
Same thing goes for the start.
A --> B ==> N --> A --> B
We'll updated A, N and start.
I am tring to insert string into doubly linked list in reverse order. But I am not sure how can I maintain the insertion order in reverse order.
This is my below code.
theList.insertReverseLexicographicalOrder("B");
theList.insertReverseLexicographicalOrder("A");
theList.insertReverseLexicographicalOrder("H");
theList.insertReverseLexicographicalOrder("D");
theList.insertReverseLexicographicalOrder("E");
public void insertReverseLexicographicalOrder(String dd) {
Link newLink = new Link(dd);
if (isEmpty()){
last = newLink;
}
first.previous = newLink;
}
newLink.next = first;
first = newLink;
}
Any suggestions will be appreciated with some code based on my solution..
Well you assume that its already in reverse order, so you're going to need some sort of loop through until you find where it should go.. i.e.
Z, Y, X, W, L, K, A
if you're inserting M, then you should loop until you find L, which is lexicographically larger than M, and therefore insert it there. Because the nodes have previous pointers, insertion shouldn't be too hard to figure out on your own
You would need to look through the list comparing each of the elements. Stop when you find the element that goes after the element you are trying to insert. I suggest you implement the compareTo method in your node class: http://www.javapractices.com/topic/TopicAction.do?Id=10
and use it to make the comparisons
Good Luck.
How to insert a node into a linked list:
If the list is empty, the new node will become the first, and if we keep track of that, also the last
Otherwise find the position where to insert, there are three possibilities,
a) the new node has to be inserted before the first
b) the new node has to be inserted after the last
c) the new node has to be inserted between two existing nodes
Update the appropriate references, that may be first, last and some next and previous fields, depending on where it has to be inserted
if (first == null) {
// the list is empty so far
} else
To find the position, first compare the data with the first node's data to see whether it has to be inserted before the first node.
if (newLink.iData.compareTo(first.iData) > 0) {
// put newLink before first
} else {
You have to keep a focus on some list node. Follow the list from the start until you reach the point of insertion:
Link focus = first; // focus first node
while(focus.next != null && newLink.iData.compareTo(focus.next.iData) < 0) {
focus = focus.next;
}
// now you have to insert the new value behind focus, left as exercise
if (focus.next == null) {
// newLink becomes the last node in the list
} else {
// newLink has to be inserted between focus and focus.next
}
}
Then insert. Beware of edge cases, inserting at the front and the end are slightly different.