Linked List Implementation using dummy nodes - java

I am working on a project where i have to union and intersect two sets. I am using Linked list for each set with dummy nodes. This is how i initialize my Sets LL class
public Set() {
top = new Node(Integer.MIN_VALUE, new Node(Integer.MAX_VALUE, null) );
} //end Set
And this is how i insert items.
public void insert(int item) {
Node prev = top;
Node curr = top.next;
while( curr.item < item ) {
prev = curr;
curr = curr.next;
}
prev.next = new Node( item, curr);
size++;
} // insert
Now i am finding it hard to get a union or intersection of two sets.
This is what i have in mind for intersection.
public Set intersection( Set setB ) {
Set setC = new Set ();
//loop over both sets and if both have same value add it otherwise
// get to the next node in both sets.
My question is, am i logically correct with the intersection pseudocode? My union pseudocode is laughable though. Can anyone please guide me though this problem?

Your idea will fail for this simple input:
1 2
2 3
Your idea:
//loop over both sets and if both have same value add it otherwise
// get to the next node in both sets.
First iteration - we have 1 and 2, not same value, so we get to the next in both sets
Second iteration - we have 2 and 3, not same value, so get to next
End
What you actually need is:
On mismatch, advance only the list with lower element
On match, add to result and advance both (or to remove duplicates, keep advancing both as long as the same value is repeating)
For union, the idea is very similar:
On mismatch, add the lower one and advance the list that contained the lower element
On match, add and advance both (or keep advancing both as long as the same value is repeating)

Related

How to do a selection sort with linked list

I think I have the basic idea down for the selection sort, but for some reason it's not working and I don't know why? Anyone have an idea what is wrong here?
A few pointers:
.getValue() just returns the object in the node, I'm using integers.
Node tempNode = new Node(null,null,node.getValue()), the first null is for previous and the second null is for next and the third just sets the object in the node which is integers in this case.
My input is:
9
5
8
6
10
4
My output is this. For some reason it keeps setting 4 over and over again:
4
5
5
4
4
4
public void SelectionSort()
{
Node<T> node2;
Comparable temp;
Node<T> Nodemin;
for(Node<T> node = front;node != null; node = node.getNext())
{
Nodemin = node;
for(node2 = node.getNext();node2 != null; node2 = node2.getNext())
{
temp = node.getValue();
if(temp.compareTo(node2.getValue()) > 0)
{
Nodemin.setValue(node2.getValue());
}
Nodemin = Nodemin.getNext();
}
System.out.println(Nodemin.getValue());
Node<T> tempNode = new Node(null,null,node.getValue());
node.setValue(Nodemin.getValue());
Nodemin.setValue(tempNode.getValue());
}
}
When you are saying Nodemin = Nodemin.getNext();, you are pointing the item to be swapped (the selected item) at the spot beyond where your minimum is. This has an unwanted side effect that when you do the swap, the number you are putting later in the list is going in one beyond the one with which you are swapping it, I believe.
But there is a more subtle flaw in setting Nodemin's value at all as you keep heading down the list and finding lower numbers. Because Nodemin points at a particular location, each time you find a new lowest element, you are not just changing Nodemin's value, but also the value of an item in the list, since they point the same place.
I think you can solve both these problems by changing Nodemin to two separate things, each of which does what you want.
Let minValue be like your temp, tracking the minValue only. Let minLocation always point to where the minValue is (not doing that next line on it ever, just resetting it to where you find a new min).
Then when outside the inner for loop and doing your swap, do it on the place pointed to by minLocation and with the value minValue.
That should fix it. Or it should also work to replace
if(temp.compareTo(node2.getValue()) > 0)
{
Nodemin.setValue(node2.getValue());
}
Nodemin = Nodemin.getNext();
with
if(temp.compareTo(node2.getValue()) > 0)
{
Nodemin = node2;
}
The suggestions to trace through and debug are good ones. You would see evidence of what I am saying, I believe, and catch any mistakes I am making.

Java - Ordered Linked List algorithm

I have a problem in understanding the algorithm of the Linked List, if someone could explain for me, I understood almost everything only a specific part, when the new added item is less than the previous item so we have to move the new item to the left
public boolean addItem(ListItem newItem) {
if (this.root == null) {
// The list was empty, so this item becomes the head of the list
this.root = newItem;
return true;
}
ListItem currentItem = this.root;
while (currentItem != null) {
int comparison = (currentItem.compareTo(newItem));
if (comparison < 0) {
// newItem is greater, move right if possible
if (currentItem.next() != null) {
currentItem = currentItem.next();
} else {
// there is no next, so insert at end of list
currentItem.setNext(newItem).setPrevious(currentItem);
return true;
}
} else if (comparison > 0) {
// newItem is less, insert before
if (currentItem.previous() != null) {
currentItem.previous().setNext(newItem);//previous entry is now the added item
newItem.setPrevious(currentItem.previous()); //the new item previous entry is setted to the current item previous value
newItem.setNext(currentItem); //pointing the new item to the current item
currentItem.setPrevious(newItem); //the previous entry of the current item is equal with the new item
} else {
// the node with a previous is the root
newItem.setNext(this.root).setPrevious(newItem);
this.root = newItem;
}
return true;
} else {
// equal
System.out.println(newItem.getValue() + " is already present, not added.");
return false;
}
}
return false;
}
so where comparison is greater than 0, so lets say I have: 9 11 10 in my Linked List, so the previous entry of 10, which is 11 goes to the previous position to the right, newItem(10)is setted to the previous position with the currentItem.previous value, so the current item is not also 10 now ?
The algorithm is simple. To make it clearer, let me replace the code blocks with a simple English explanation of what it does:
if the list is empty, put the new item as the root of the list.
otherwise, if the list has items, take the root as the current item to compare it to.
this will go over a few iterations until we find the right spot to insert the new item.
For every iteration:
if the new item is bigger than the current spot on the list, move up one spot in the
list to compare next time.
else, if the new item is smaller than the current spot,
and the current spot is not the root of the list - insert
the new item between the current spot and the one before it.
If the current spot is the root of the list, make the new item
the root of the list and tag along the entire list as its next items.
And that's it - you always get a sorted list after a few iterations (the most iterations is the length of the list). you start from the beginning of the list and look at each item against the one you have to insert. If as long as it's bigger than the current spot you move up the list. When you passed the spot it needs to be (the previous spot was smaller, the next spot is bigger) you just insert it in the middle. And you may insert it at the very beginning or at the very end. I hope that helps you understand the algorithm better.
This is implementation of
sorted Linked List
No duplicates are allowed in Linked List
All elements are unique and in ascending order.

deleting a specific item from a java LL

So I'm trying to delete an item from a linked list in java.I'm not using java's predefined LL but I'm working with my own.
I know the concept to delete an item is to traverse in the link and compare the data in the list one by one.
so here's what I came up with, but it doesn't work!
public void delStudent(int regN) {
Node current = head;
Node q = head;
if (current.getStudent().getRegN() == regN) {
head = head.link;
}
for (int i = 0; i < this.length() - 1; i++) {
if (current.getStudent().getRegN() != regN) {
current = current.link;
q = current;
}
}
q.link= current.link.link;
}
Well, if your list is empty, the execution of the if statement in the beginning will immediately give a NullPointerException (because current will be null). Generally, for the LinkedList delete method, you must consider three cases: size == 0, size == 1, and size > 1 (where size is the number of nodes in the Linked List).
public void delStudent(int regN) {
Node current = head;
Node previous = head;
while (current != null ){ // keep traversing till end of list
if (current.getStudent().getRegN() == regN) { // found it!
previous.link = current.link; // relink
if (current == head){ // edge case : removed first element
head = current.link; // move head forward.
}
break;
} else {
previous = current;
current = current.link;
}
}
}
The above code assumes regN is unique and that there is only one student with that regN. Hope this helps.
The mistake is (I think) in these three lines:
current = current.link;
q = current;
(where you set q to be the same as current) and
q.link= current.link.link;
(and maybe also in using length() depending on it's implementation)
To see why let's look at how to delete in more detail:
Let's consider there are three nodes in your list x->y->z and you want to delete y.
In order to do so you need to set x.link = z.
To return to you example it means that the variable q should store the element before current, then deleting current can be done by
q.link = current.link;
In order order to have q be the predecessor of current you have to reverse the two lines above, i.e., use
q = current;
current = current.link;
Why am I saying depending on the implementation of length ? If you implementation of length just returns some number maintained by increasing whenever you add a value to the list, you should also decrement it when deleting one. If length traverses the list in order to find the number of elements then its ok, although not very efficient.
One last comment: your code will not work (even with the fixes I explain above) when there is no element with the given regN. Why? Because you always delete one element. Moreover, you might want to rethink the logic inside the loop. Currently if the element to delete is the second one and there is 1000000 elements you will run the loop nearly 1000000 times.
When you are checking each node you need to delete the node or break once you find a match. You need to maintain a node for the previous node to be able to delete the current node once you find a match.
I just realized that you were attempting to to that with Node q
for (int i = 0; i < this.length() - 1; i++) {
if (current.getStudent().getRegN() != regN) {
q = current;
current = current.link;
} else{ //we have a match
//remove the link to the current item
q.link = current.link;
break;
}
if you are using a doubly linked list you can use node.prev().link = current.link;

Need to remove duplicate nodes in linked list

I am attempting to write code that will remove the duplicate nodes in a singly-linked list. The duplicates removed are only removed until the number stored in the next node changes.
For example, if the input list is [ 0 0 0 0 1 1 0 0 0 3 3 3 1 1 0 ],
the output list is [ 0 1 0 3 1 0 ].
I have attempted to write the code and tried multiple things. Each time when I call the function it either returns the original linked list or just the original head and original tail.
I attempted creating a temporary linked list and storing values in that list but it does not return properly.
My latest attempt is in the code snippet below and only returns the head and tail of the original list.
My question is, how I should proceed with this code? I tried to draw it out and visualize it but it did not help.
I am not looking for code to be written just a push in the correct direction.
I think that the code I have now is a dead end and I may have to restart from scratch.
What is the best way to start to implement this code to achieve an answer?
public void squish() {
SListNode current = head;
SListNode iterator = current.next;
while (iterator != null){
if (current.equals(iterator)){
iterator = iterator.next;
} else {
if (current.next.equals (null)) {
break;
} else {
head.next = iterator;
current = iterator;
}
}
}
}
In your current solution you are trying to do 2 things at once, skipping n equal numbers and re-arranging your list. This makes the solution a bit more complex than necessary.
What you can do is looping while you have a current node and that current node is followed by another.
now within the loop you have 2 possibilities;
either the values of current and next are equal, in that case make the node following current (next) the same as the one following the current next.
or the values are unequal, in that case walk the list by setting the current node to its follower node.
That's it, no explicit assignments to the head reference should be necessary.
I'm guessing that this is homework, so I don't want to give a complete solution.
Working directly with iterators is always tricky. Instead of working in place with a single List, you should consider creating a new List with the solution you want. e.g., schematically...
Create a new empty List for the result
Initialize prevValue
Loop over the values in input list
If the value is not equal to the prevValue
add it to the result list
update prev value
Of course, if the class/assignment really wants you to use iterators, ignore the above...
public void RemoveDuplicates()
{
Dictionary<int, int> myDict = new Dictionary<int, int>();
Node cur = head;
myDict.Add(head.Data, 1);
while (cur.Next != null)
{
if (myDict.ContainsKey(cur.Next.Data))
cur.Next = cur.Next.Next;
else
{
myDict.Add(cur.Next.Data, 1);
cur = cur.Next;
}
}
}

JAVA - sorting a linked list by descending order

i tried to write a method that sort a linked list.
this is java training for me.
the method should get a linked list with values and sort it with selection sort.
but not the usual selection sort, but selection sort that find the biggest number and put it in the start of the linked list. until the list is sorted.
i tried follow the debugger but, i cant really understand what i did wrong.
this is what i tired:
public IntList selectionSort()
{
IntNode tempMax = _head;
IntNode current = _head;
IntNode fromHere = null;
IntNode toHere = _head;
IntNode prev = null;
while(toHere != null)
{
current = toHere;
tempMax = toHere;
while (current != null)
{
if (current.getNext() != null && current.getNext().getValue() > tempMax.getValue())
{
prev = current;
tempMax = current.getNext();
current = current.getNext();
}
else current = current.getNext();
}
prev.setNext(prev.getNext().getNext());
tempMax.setNext(toHere);
if (fromHere == null)
_head = tempMax;
else fromHere.setNext(tempMax);
fromHere = tempMax;
toHere = fromHere.getNext();
}
return this;
}
A few tips:
If you want the smallest number then current.getNext().getValue() > tempMax.getValue() should have a > instead of a <
Your code will also fail if the first element is already the minimum value, as you try to do something to null
I can see duplicated code in here too, current = current.getNext(). Pointer operations are generally hard to code, and writing clearer code sticking to the principle of Don't Repeat Yourself will probably help you see bugs!
It will help people here help you if you print compiler/runtime error messages
The main issue with your code, is that it misbehave when a node is already at the position it should be. If we execute with :
5 -> 1 -> 2 -> 3-> 4
prev will be null and we crash.
If we do with :
1 -> 4 -> 5 -> 3-> 2
at the first iteration you obtain
5 -> 4 -> 1 -> 3-> 2
So far so good.And then, after the loop of the second iteration
5 -> 4 -> 3-> 2 // prev still pointing at 4, 1 dissapears
5 -> 4 -> 4. // tempMax = toHere so tempMax->tempMax, and the other elements are gone
So the manifestation is that prev is invalid in some way.
There is a quick fix, like skipping the repositioning when toHere is the maximum,
but quick fixes are not what you need. You should :
Rethink about some special cases. Empty list, one element, list already sorted, list sorted in reverse, random order, (duplicate element??)
Write unit test for each case
Rewrite your algorithm, and avoid Oh yes, I forgot the case... . Dumb it down, you only need to replace the first element at each given step with the maximum found at this step.
Avoid variables which have redundant information. For example, tempMax should always be the next of prev, so prev alone is enough. Otherwise you are spending brain cells preserving consistency.
Test again the suite case.

Categories

Resources