Hey there I have been trying to get an insertion sort method to work for a class I'm taking and we have been told to use insertion sort to sort a linked list of integers without using the linked list class already in the Java libraries.
Here is my inner Node class I have made it only singly linked as i don't fully grasp the circular doubly linked list concept yet
public class IntNode
{
public int value;
public IntNode next;
}
And here is my insertion sort method in the IntList class
public IntList Insertion()
{
IntNode current = head;
while(current != null)
{
for(IntNode next = current; next.next != null; next = next.next)
{
if(next.value <= next.next.value)
{
int temp = next.value;
next.value = next.next.value;
next.next.value = temp;
}
}
current = current.next;
}
return this;
}
The problem I am having is it doesn't sort at all it runs through the loops fine but doesn't manipulate the values in the list at all can someone please explain to me what I have done wrong I am a beginner.
you need to start each time from the first Node in your list, and the loop should end with the tail of your list -1
like this
public static IntList Insertion()
{
IntNode current = head;
IntNode tail = null;
while(current != null&& tail != head )
{
IntNode next = current;
for( ; next.next != tail; next = next.next)
{
if(next.value <= next.next.value)
{
int temp = next.value;
next.value = next.next.value;
next.next.value = temp;
}
}
tail = next;
current = head;
}
return this;
}
The insertion operation only works if the list being inserted into is already sorted - otherwise you're just randomly swapping elements. To start out, remove an element from the original list and construct a new list out of it - this list only has one element, hence it is sorted. Now proceed to remove the remaining elements from the original list, inserting them into the new list as you go. At the end the original list will be empty and the new list will be sorted.
I agree with the Zim-Zam opinion also.
The loop invariant of insertion sort also specifies this: "the subarray which is in sorted order".
Below is the code, I implemented for insertion sorting in which I created another linked list that contains the element in sorted order:
Node newList=new Node();
Node p = newList;
Node temp=newList;
newList.data=head.data;
head=head.node;
while(head!=null)
{
if(head.data<newList.data)
{
Node newTemp = new Node();
newTemp.data=head.data;
newTemp.node=newList;
newList=newTemp;
p=newList;
}
else
{
while(newList!=null && head.data>newList.data)
{
temp=newList;
newList=newList.node;
}
Node newTemp = new Node();
newTemp.data=head.data;
temp.node=newTemp;
newTemp.node=newList;
newList=p;
}
head=head.node;
}
Related
I'm trying to understand how copy/reference works in the algorithm below to solve LeetCode's 'Merge Two Sorted Lists' problem.
This algorithm uses the iteration approach to merge the linked lists, initially using a 'head' node and initializing it with the value 0. After that, the object from the head node is copied to another handler node. After that, the value of the handler node's next is changed at each iteration of the loop to traverse the linked list, but the head node remains with the current value as 0, but the next nodes are updated and the head.next is returned to the end of iteration.
I did not understand how the head node had all the values of the next property updated and the current property 'val' did not, instead the handler had the property val and the next updated and at no time had it had a new assignment for head.
public static ListNode MergeTwoLists(ListNode list1, ListNode list2)
{
ListNode head = new ListNode(0);
ListNode handler = head;
while (list1 != null && list2 != null)
{
if (list1.val <= list2.val)
{
handler.next = list1;
list1 = list1.next;
}
else
{
handler.next = list2;
list2 = list2.next;
}
handler = handler.next;
}
if (list1 != null)
handler.next = list1;
else if (list2 != null)
handler.next = list2;
return head.next;
}
public class ListNode
{
public int val;
public ListNode next;
public ListNode(int val = 0, ListNode next = null)
{
this.val = val;
this.next = next;
}
}
LeetCode: https://leetcode.com/problems/merge-two-sorted-lists/
Solution I'm referring to (it's in java but I'm testing in c#): https://leetcode.com/problems/merge-two-sorted-lists/discuss/9772/Java-solution-with-real-world-concerns-real-world-concerns
outputI'm doing a project for class where I have to sort a linked list using insertion sort. I am supposed to take user input, convert it into an int array and insert it into a linked list. My problem is for some reason when I go to print the linked list post sort, it only prints the first node. The code worked jsut fine when I was initially testing it(I was manually entering what integers to insert), but now that I'm using arrays it doesn't seem to work. Can anyone help?
(this is only one class from my project but let me know if more information is needed).
Edit: I added a picture of what my output lokos like
import java.util.Arrays;
public class SortLL {
static LL top;
static Node head;
static Node sorted;
//function to insert node at head
public void toHead(int newData){
Node newNode = new Node(newData);
newNode.link = head;
head = newNode;
}
public static void insertion(Node ref){ //problem right now is that i'm only passing in one node
sorted = null;
Node current = ref;
while(current != null){
Node next = current.link;
sortInsert(current);
current = next;
}
head = sorted;
}
static void sortInsert(Node newNode){ //item in this case is val
if(sorted == null || sorted.item >= newNode.item){
newNode.link = sorted;
sorted = newNode;
} else {
Node current = sorted;
while(current.link != null && current.link.item < current.item){
current = current.link;
}
newNode.link = current.link;
current.link = newNode;
}
}
void printList(Node head)
{
while (head != null)
{
System.out.print(head.item + " ");
head = head.link;
}
}
public static void sortList(int[] arrA, int[] arrB){
int[] arr = new int[arrA.length + arrB.length];
System.arraycopy(arrA, 0, arr, 0, arrA.length);
System.arraycopy(arrB, 0, arr, arrA.length, arrB.length);
System.out.println("checking array " + Arrays.toString(arr));
SortLL sort = new SortLL();
for(int i=0;i<arr.length;i++){
sort.toHead(arr[i]);
}
System.out.println("sortLL.java\n\n");
sort.printList(sort.head);
sort.sortInsert(sort.head);
System.out.println("\nLinkedList After sorting");
sort.printList(sort.head);
}
}
Inside your printList() method, you shift the head variable while iterating over the list. When you move the head variable to the end, you essentially destroy the linked list since you lose your reference to the beginning of it. Java will then automatically treat the unreferenced nodes as garbage.
From what I see, after you first call sort.printList(sort.head), you destroyed your original linked list, so it didn't work when sorting.
When calling printList(), it might help to use a temporary node (Node temp = head) so that you don't lose your original head variable.
This is the code I've got so far, and it removes all the first instances of the duplicates but if I got an element repeated more than once it will only remove the first instance and leave the rest instances of this element in the list.
//remove all duplicate items from list.
// if list is null or empty leave it unchanged
public static <T extends Comparable<? super T>>
void deleteReps(LinkedList<T> list)
{
for (int i = 0; i < list.size(); i++)
{
T item = list.get(i);
for(int j = i + 1; j < list.size(); j++)
{
if(item == null && list.get(j) == item || item != null && item.equals(list.get(j)))
{
list.remove(j);
}
}
}
}
Following Eran's answer, I suggest you should iterate the list with Iterator since it eliminate the need for manual indexes and also allows for item removal while iterating the list.
When you remove an element from a list, you have to remember that this will reduce the index for every item after it in the list as well as the size of the list.
EDIT
As sharonbn suggested, here is a working method using an Iterator:
public static <T extends Comparable<? super T>> void deleteReps(LinkedList<T> list)
{
LinkedList<T> noRepsList = new LinkedList<T>();
Iterator<T> itr = list.iterator();
while(itr.hasNext())
{
T currentTest = itr.next();
if (!noRepsList.contains(currentTest))
noRepsList.add(currentTest);
else
itr.remove();
}
}
This may not be the most effective way to do this as it creates another list to compare objects with but it does get the job done.
With a LinkedList you are dealing with reference-based implementation of Objects that are linked together with Nodes. A Node contains an Object and a reference to the next Node only. You should try not to iterate through a LinkedList using indexes because when you start removing or adding Nodes, the indexes change. Unlike an Array that will keep a space null if you remove its content, once you remove a Node from a LinkedList, the list decreases in size, as the previous Node now references the Node that came after the one you deleted, and the deleted Node is lost in memory. So, in your example, you need to take into account that index will change after you remove a duplicate. For this reason, you should always try to traverse a LinkedList in Java via reference and not indexing. In your case, this might work:
void deleteReps(LinkedList<T> list)
{
Node prev = head; // A node to traverse with starts at the head
Node temp = head.getNext(); // A second node to traverse with
Node current = prev; // The node in question
while(prev.getNext() != null) // While the node after prev isn't the end
{ // of the list
T item = current.data; // The item we are looking for duplicates of
while(temp != null) // While temp isn't at the end of the list
{
if(temp.data == item) // If the item in temp is the same as the
{ // item we are looking for
prev.setNext(temp.getNext()); // Set the next Node of prev to the node
// after temp. This "deletes" the Node
// at temp
prev = temp; // prev is now temp
temp = temp.getNext(); // temp is the next Node
}
else // Else if the item is different
{
prev = temp; // prev is now temp
temp = temp.getNext(); // temp is now the next Node
}
} // end while
current = current.getNext(); // current is now the next Node
// so that the
// the next item we are looking for
// duplicates of is an item still in
// the LinkedList
prev = current;
temp = prev.getNext();
} // end while
}
I gave thorough comments so you could follow the logic behind this algorithm. This takes into account the shrinking LinkedList as you delete Nodes because current.getNext() will always be a Node that is still in the LinkedList after the deletion of duplicates occurs.
I am trying to convert a C# code to Java. I have almost converted every thing except the three lines within if condition.
the C# code
LinkedList<T> buk = new LinkedList();
LinkedListNode<T> current = buk.First;
LinkedListNode<T> previous = null;
if (fooCondition) {
previous = current.Previous;
} else {
previous = current;
current = current.Next;
}
The equivalent Java code
LinkedList<T> buk = new LinkedList<>();
T current = buckets.getFirst();
T previous = null;
if (fooCondition) {
? //previous = current.Previous;
} else {
? //previous = current;
? //current = current.Next;
}
As there is no LinkedListNode class in the Java, can any one suggest what would be the equivalent code in Java?
EDIT
It seems like the full code is important to get help. Here is the C# function from the link
protected void MergeBuckets()
{
LinkedListNode<Bucket> current = buckets.First;
LinkedListNode<Bucket> previous = null;
int k = (int)Math.Ceiling(1 / epsilon); // k=1/eps as integer
int kDiv2Add2 = (int)(Math.Ceiling(0.5 * k) + 2); // k/2 as integer
// at this point 1/k <= eps, k >= 2, hence requires eps >= 0.5
// number of concecutive buckets with same count causing a
// merge of the oldest two of those buckets
int numberOfSameCount = 0;
// traverse buckets from first to last, hence in order of
// descending timestamp and ascending count
while (current != null)
{
// previous and current bucket have same count, increment counter
if (previous != null && previous.Value.Count == current.Value.Count)
numberOfSameCount++;
// current is first with that count, reset counter to 1
else
numberOfSameCount = 1;
// detect need for a merge
if (numberOfSameCount == kDiv2Add2)
{
// merge buckets into current and remove previous
current.Value.Timestamp = previous.Value.Timestamp; // take most recent timestamp
current.Value.Count = previous.Value.Count + current.Value.Count; // sum the counts of the buckets,
// i.e. next power of two
buckets.Remove(previous);
// note that a merged bucket might cause a cascade of merges due to its new count,
// hence the new current node should point to the merged bucket otherwise the
// cascade might go unnoticed, temporarily violating the invariant!
previous = current.Previous; // merged bucket's previous, since old previous is removed
//current = current; // trivial, merged bucket is new current
// at this iteration, the traversal stays in place
}
// no merge required, continue normally
else
{
previous = current; // old current bucket or merged bucket
current = current.Next; // current's or merged's next
// at this iteration, the traversal moves to the next (older) bucket
}
}
}
can't you use the listIterator provided by the LinkedList and use its provided methods to browse the Linked list
ListIterator<T> listIterator = linkedListNode.listIterator(0);
if(yourCondition && listIterator.hasNext()){
T next = listIterator.next();
}
else if (listIterator.hasPrevious()){
T previous = listIterator.previous();
}
Hope it helps
The Java class java.util.LinkedList has an inner class LinkedList.Node which is private. The Nodes in a LinkedList cannot be acccessed directly. Instead, refer to methods like List.indexOf(E) and List.add(E, int) or a ListIterator in order to insert elements at specific positions.
final LinkedList<T> list = new LinkedList<>();
list.add(object1);
if (cond) {
list.add(object2, list.indexOf(object1));
} else {
list.addFirst(object2);
}
A frequently used idiom for dealing with LinkedList in Java is to create the LinkedList but primarily operate on it using a ListIterator.
final LinkedList<T> list = new LinkedList<>();
final ListIterator<T> iterator = list.listIterator();
if (!cond && list.hasNext()) {
list.next();
}
list.add(object2);
You can't make a LinkedList without nodes for it. Your code doesn't make sense, unfortunately.
A LinkedList node (in this case doubly linked) consists of the next node, the previous one, and the data in the node, as well as accessor methods. It's pretty simple to implement as it's simply a data storage structure.
class LinkedListNode<T> {
LinkedListNode prevNode, nextNode;
T data;
public LinkedListNode getNext() {
return nextNode;
}
public LinkedListNode getPrev() {
return prevNode;
}
public T getValue() {
return data;
}
public void setNext( LinkedListNode n ) {
nextNode = n;
}
public void setPrev( LinkedListNode n ) {
prevNode = n;
}
public void setValue( T data ) {
data = n;
}
}
You can write the own version of LinkedListNode class which contains the previous and next as it's property/field. For example -
class LinkedListNode{
LinkedListNode previous;
LinkedListNode next;
}
Then add some getter and setter method to access the property/field. You may add another property/field to store the value of the node. This is the basic structure.This might help you.You may have a look at this link also.
Thanks
LinkedList<T> buk=new LinkedList<T>();
//make list
T current=buk.getFirst();
T previous=null;
if (fooCondition) {
previous = current.previous;
} else {
previous = current;
current = current.next;
}
and the structure of T :
Class T{
public T previous;
public T next;
//rest
}
a linear linked list is a set of nodes. This is how a node is defined (to keep it easy we do not distinguish between node an list):
class Node{
Object data;
Node link;
public Node(Object pData, Node pLink){
this.data = pData;
this.link = pLink;
}
public String toString(){
if(this.link != null){
return this.data.toString() + this.link.toString();
}else{
return this.data.toString() ;
}
}
public void inc(){
this.data = new Integer((Integer)this.data + 1);
}
public void lappend(Node list){
Node child = this.link;
while(child != null){
child = child.link;
}
child.link = list;
}
public Node copy(){
if(this.link != null){
return new Node(new Integer((Integer)this.data), this.link.copy());
}else{
return new Node(new Integer((Integer)this.data), null);
}
}
public Node invert(){
Node child = this.link;
while(child != null){
child = child.link;
}
child.link = this;....
}
}
I am able to make a deep copy of the list. Now I want to invert the list so that the first node is the last and the last the first. The inverted list has to be a deep copy.
I started developing the invert function but I am not sure. Any Ideas?
Update: Maybe there is a recursive way since the linear linked list is a recursive data structure.
I would take the first element, iterate through the list until I get to a node that has no child and append the first element, I would repeat this for the second, third....
I sometimes ask this question in interviews...
I would not recommend using a recursive solution, or using a stack to solve this. There's no point in allocating O(n) memory for such a task.
Here's a simple O(1) solution (I didn't run it right now, so I apologize if it needs some correction).
Node reverse (Node current) {
Node prev = null;
while (current != null) {
Node nextNode = current.next;
current.next = prev;
prev = current;
current = nextNode;
}
return prev;
}
BTW: Does the lappend method works? It seems like it would always throw a NullReferenceException.
There's a great recursive solution to this problem based on the following observations:
The reverse of the empty list is the empty list.
The reverse of a singleton list is itself.
The reverse of a list of a node N followed by a list L is the reverse of the list L followed by the node N.
You can therefore implement the reverse function using pseudocode along these lines:
void reverseList(Node node) {
if (node == null) return; // Reverse of empty list is itself.
if (node.next == null) return; // Reverse of singleton list is itself.
reverseList(node.next); // Reverse the rest of the list
appendNodeToList(node, node.next); // Append the new value.
}
A naive implementation of this algorithm runs in O(n2), since each reversal requires an append, which requires an O(n) scan over the rest of the list. However, you can actually get this working in O(n) using a clever observation. Suppose that you have a linked list that looks like this:
n1 --> n2 --> [rest of the list]
If you reverse the list beginning at n2, then you end up with this setup:
n1 [reverse of rest of the list] --> n2
| ^
+------------------------------------------+
So you can append n1 to the reverse of the rest of the list by setting n1.next.next = n1, which changes n2, the new end of the reverse list, to point at n1:
[reverse of the rest of the list] --> n2 --> n1
And you're golden! Again more pseudocode:
void reverseList(Node node) {
if (node == null) return; // Reverse of empty list is itself.
if (node.next == null) return; // Reverse of singleton list is itself.
reverseList(node.next); // Reverse the rest of the list
node.next.next = node; // Append the new value.
}
EDIT: As Ran pointed out, this uses the call stack for its storage space and thus risks a stack overflow. If you want to use an explicit stack instead, you can do so like this:
void reverseList(Node node) {
/* Make a stack of the reverse of the nodes. */
Stack<Node> s = new Stack<Node>();
for (Node curr = node; node != null; node = node.next)
s.push(curr);
/* Start unwinding it. */
Node curr = null;
while (!s.empty()) {
Node top = s.pop();
/* If there is no node in the list yet, set it to the current node. */
if (curr == null)
curr = top;
/* Otherwise, have the current node point to this next node. */
else
curr.next = top;
/* Update the current pointer to be this new node. */
curr = top;
}
}
I believe that this similarly inverts the linked list elements.
I would treat the current list as a stack (here's my pseudo code):
Node x = copyOf(list.head);
x.link = null;
foreach(node in list){
Node temp = copyOf(list.head);
temp.link = x;
x = temp;
}
At the end x will be the head of the reversed list.
I more fammiliar whit C, but still let me try. ( I just do not sure if this runs in Java, but it should)
node n = (well first one)
node prev = NULL;
node t;
while(n != NULL)
{
t = n.next;
n.next = prev;
prev = n;
n = t;
}
Reversing a single-linked list is sort of a classic question. It's answered here as well (and well answered), it does not requires recursion nor extra memory, besides a register (or 2) for reference keeping.
However to the OP, I guess it's a school project/homework and some piece of advice, if you ever get to use single linked list for some real data storage, consider using a tail node as well. (as of now single linked lists are almost extinct, HashMap buckets comes to mind, though).
Unless you have to check all the nodes for some condition during 'add', tail is quite an improvement. Below there is some code that features the reverse method and a tail node.
package t1;
public class SList {
Node head = new Node();
Node tail = head;
private static class Node{
Node link;
int data;
}
void add(int i){
Node n = new Node();
n.data = i;
tail = tail.link =n;
}
void reverse(){
tail = head;
head = reverse(head);
tail.link = null;//former head still links back, so clear it
}
private static Node reverse(Node head){
for (Node n=head.link, link; n!=null; n=link){//essentially replace head w/ the next and relink
link = n.link;
n.link = head;
head = n;
}
return head;
}
void print(){
for (Node n=head; n!=null;n=n.link){
System.out.println(n.data);
}
}
public static void main(String[] args) {
SList l = new SList();
l.add(1);l.add(2);l.add(3);l.add(4);
l.print();
System.out.println("==");
l.reverse();
l.print();
}
}
I was wondering something like that(I didnt test it, so):
invert(){
m(firstNode, null);
}
m(Node v, Node bef){
if(v.link != null)
m(v.link,v);
else
v.link=bef;
}
Without much testing,
Node head = this;
Node middle = null;
Node trail = null;
while (head != null) {
trail = middle;
middle = head;
head = head.link;
middle.link = trail;
}
head = middle;
return head;
public ListNode Reverse(ListNode list)
{
if (list == null) return null;
if (list.next == null) return list;
ListNode secondElem = list.next;
ListNode reverseRest = Reverse(secondElem);
secondElem.Next = list;
return reverseRest;
}
Hope this helps.