This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 5 years ago.
I am trying to write a program for quicksort using singly linked list in java.
Below is the code.
public class QuickSortInSLinkedList {
Node head;
private static class Node{
private int data;
private Node next;
Node(int data){
this.data = data;
this.next = null;
}
}
public void printList(Node head){
Node node = head;
while(node != null){
System.out.print(node.data+" ,");
node = node.next;
}
}
private Node getLastNode(Node head){
Node node = head;
while(node != null && node.next != null){
node = node.next;
}
return node;
}
public void push(int data){
Node node = new Node(data);
if(head == null){
head = node;
return;
}
node.next = head;
head = node;
}
void quickSort(Node head){
Node lastnode = getLastNode(head);
head = _quickSort(head, lastnode);
return;
}
Node _quickSort(Node low, Node high){
Node newHead = null, newTail = null;
if(low == null || low == high){
return low;
}
Node part = partition(low, high, newHead, newTail);
if (newHead != part){
Node temp = newHead;
while(temp.next != part){
temp = temp.next;
}
temp.next = null;
newHead = _quickSort(newHead, temp);
temp = getLastNode(newHead);
temp.next = part;
}
part.next = _quickSort(part.next, newTail);
return newHead;
}
private Node partition(Node low, Node high, Node newHead, Node newTail){
Node pivot = high;
Node previous = null, current = head, tail = pivot;
while(current != pivot){
if (current.data < pivot.data){
if (newHead == null)
newHead = current;
previous = current;
current = current.next;
}else{
if(previous != null)
previous.next = current.next;
Node temp = current.next;
current.next = null;
tail.next = current;
tail = current;
current = temp;
}
}
if(newHead == null){
newHead = pivot;
}
newTail = tail;
return pivot;
}
public static void main(String[] args){
QuickSortInSLinkedList list = new QuickSortInSLinkedList();
list.push(5);
list.push(35);
list.push(7);
list.push(8);
list.push(34);
list.push(23);
System.out.println("Linked list before sorting");
list.printList(list.head);
System.out.println("\n Linked list after sorting");
list.quickSort(list.head);
list.printList(list.head);
}
}
I understand that since in java we have pass by reference value, this code should work but in line 62 i.e. variables newHead and newTail is always received as null after the call to partition method.
below is the error
Exception in thread "main" java.lang.NullPointerException
23 ,34 ,8 ,7 ,35 ,5 ,
at implementation.sorting.QuickSortInSLinkedList$Node.access$100(QuickSortInSLinkedList.java:6)
Linked list after sorting
at implementation.sorting.QuickSortInSLinkedList._quickSort(QuickSortInSLinkedList.java:62)
at implementation.sorting.QuickSortInSLinkedList.quickSort(QuickSortInSLinkedList.java:47)
at implementation.sorting.QuickSortInSLinkedList.main(QuickSortInSLinkedList.java:123)
Please help me understand why is it so.
Thanks
Java does manipulate objects by reference, and all object variables are references. However, Java doesn't pass method arguments by reference; it passes them by value.
Related
I have a sorted doubly linked list in which the first and last elements are null. This means when I insert the values a, b, c. The result should look as follows: {null, a, b, c, null}
The empty sorted doubly linked list should look like this: {null, null} in which the first and last elements are always are null.
The problem is that when I insert data in the sorted doubly linked list, the data is not sorted correctly and the 2 null values are always at the end of the list. How can I fix this?
Here is my current insert method:
public void addElement(String element) {
// new node which will be inserted in the list
Node newNode = new Node();
newNode.data = element;
// if the list is empty
if (size == 0) {
last = newNode;
newNode.next = first;
first = newNode;
size++;
} else {
Node current = first;
// if the element should be at the beginning of the list
if (current.data.compareTo(element) > 0) {
newNode.next = current;
newNode.previous = null;
current.previous = newNode;
first = newNode;
} else {
while (current != null) {
if (current.data.compareTo(element) <= 0) {
if (current.next == null) {
newNode.next = current.next;
newNode.previous = current;
current.next = newNode;
break;
}
newNode.next = current.next;
newNode.previous = current;
current.next.previous = newNode;
current.next = newNode;
break;
} else {
current = current.next;
}
}
}
size++;
}
}
It is not so clear what you are doing in your code, so I modified it a bit and made more OO style, so here it is:
class Node {
String data;
Node next, previous;
}
public class SortedDLL {
private Node first;
private Node last;
private int size = 0;
public SortedDLL() {
size = 0;
first = new Node();
last = new Node();
first.next = last;
last.previous = first;
}
public void addElement(String element) {
Node newNode = new Node();
newNode.data = element;
if (size == 0) {
first.next = newNode;
newNode.previous = first;
newNode.next = last;
last.previous = newNode;
} else {
Node node = first;
while (node.next.data != null && node.next.data.compareTo(newNode.data) < 0) {
node = node.next;
}
newNode.next = node.next;
node.next.previous = newNode;
node.next = newNode;
newNode.previous = node;
}
size++;
}
public void print() {
Node node = first;
while (node != null) {
System.out.print(node.data != null ? node.data + " " : "null ");
node = node.next;
}
}
public void printReverse() {
Node node = last;
while (node != null) {
System.out.print(node.data != null ? node.data + " " : "null ");
node = node.previous;
}
}
public static void main(String[] args) {
SortedDLL sortedDLL = new SortedDLL();
sortedDLL.addElement("c");
sortedDLL.addElement("a");
sortedDLL.addElement("b");
sortedDLL.addElement("c");
System.out.println("list: ");
sortedDLL.print();
System.out.println("\nlist reverse: ");
sortedDLL.printReverse();
}
Output:
list:
null a b c c null
list reverse:
null c c b a null
the problem starts at the first call when size == 0
you push the first null to the end.. and the first node becomes the new node.
then, if you fix this you will get null pointer exception at the row :
if (current.data.compareTo(element) > 0) {
because the current will be null and the will not have data.
you should ignore the first null in the first insert and every insert after that.
Depending on implementation I think you're just doing the right thing in the wrong place.
while (current != null) {
if (current.next == null) {
newNode.next = null;
newNode.previous = current;
current.next = newNode;
break;
}
if (current.next.data.compareTo(element) > 0) {
newNode.next = current.next;
newNode.previous = current;
current.next.previous = newNode;
current.next = newNode;
break;
} else {
current = current.next;
}
}
Instead of checking if the currently selected node is smaller you need to check if the node after is bigger because then you can place the node.
And checking if current.next is null needs to be done outside of that comparison.
This question already has answers here:
Delete Last Node of a Linked List
(15 answers)
Closed 5 years ago.
I am trying to create a double linked list and am having trouble with the removeLast method.
public class Node<E> {
E data;
public Node<E> next;
public Node<E> prev;
public Node(E d)
{
data = d;
}
public E getData()
{
return data;
}
}
public class TestList<E> {
Node<E> head;
Node<E> tail;
public void addLast(E data)
{
Node<E> newData = new Node<E>(data);
if (head == null)
{
head = newData;
tail = newData;
}
else
{
Node<E> current = head;
while (current.next != null)
current = current.next;
current.next = newData;
tail = current.next;
}
}
public void removeLast()
{
if (head == null)
System.out.println("List is empty!");
else
{
Node<E> current = tail;
}
}
If for example I had a list of integers with the values 1, 3, 5 with 1 being the head and 5 being the tail, in my removeLast method I would like to know how I could make current.prev point to 3 and current.prev.prev point to 1 as right now it would just point to the next values which in this case would be null.
You have to modify both addLast() and removeLest() with check 3 different situations in both methods.
public final class TestList<E> {
private Node<E> head;
private Node<E> tail;
public void addLast(E data) {
Node<E> node = new Node<>(data);
if (head == null)
head = tail = node;
else if (head == tail) {
tail = node;
head.next = tail;
tail.prev = head;
} else {
tail.next = node;
node.prev = tail;
tail = node;
}
}
public void removeLast() {
if (tail == null)
System.err.println("List is empty!");
else if (head == tail)
head = tail = null;
else {
Node<E> prev = tail.prev;
tail.prev = null;
tail = null;
tail = prev;
tail.next = null;
}
}
private static final class Node<E> {
E data;
Node<E> next;
Node<E> prev;
public Node(E data) {
this.data = data;
}
}
}
You can do:
If the list is already empty, do nothing
Or else, if head is the same as the tail (there is only one element in list), then clear the list
Or else, make tail.prev.next point to null, and then make tail = prev
Like this:
public void removeLast() {
if (head == null) {
System.out.println("List is empty!");
return;
}
if (head == tail) {
head = tail = null;
return;
}
Node<E> prev = tail.prev;
prev.next = null;
tail = prev;
}
I am trying to rearrange a Singly linked list. The initial list will be 1,2,3,4,5
and they have to be sorted in 1,5,2,4,3. I have the code and I am trying to understand how it works. Basically I am stuck at the concept of pass by value in java.
The complete code
public class Test {
public static void main(String[] args) {
LinkedLists linkedList = new LinkedLists();
linkedList.append(1);
linkedList.append(2);
linkedList.append(3);
linkedList.append(4);
linkedList.append(5);
linkedList.reorderList();
}}
class Node {
int data;
Node next;
public Node(int data) {
this.data = data;
}}
class LinkedLists {
Node head;
public void reorderList() {
if (head == null) {
System.out.println(head);
return;
}
Node slowPointer = head;
Node fastPointer = head.next;
System.out.println(slowPointer.hashCode());
System.out.println(head.hashCode());
while (fastPointer != null && fastPointer.next != null) {
fastPointer = fastPointer.next.next;
slowPointer = slowPointer.next;// why head value did not change
}
Node head2 = slowPointer.next;
slowPointer.next = null;// why did the head value change here
LinkedList<Node> queue = new LinkedList<Node>();
while (head2 != null) {
Node temp = head2;
head2 = head2.next;
temp.next = null;
queue.push(temp);
}
while (!queue.isEmpty()) {
Node temp = queue.pop();
temp.next = head.next;
head.next = temp;
head = temp.next;
}
}
public void append(int data) {
if (head == null) {
head = new Node(data);
return;
}
Node current = head;
while (current.next != null) {
current = current.next;
}
current.next = new Node(data);
}}
The value of head does not get changed at line
slowPointer = slowPointer.next;// why head value did not change
But at line
slowPointer.next = null;// why did the head value change here
Why does it change here. Thanks.
Because in the first case you are assigning the object pointed by next to the slowPointer.
But in second case you are modifying the value of 'next' of the object being pointed by the reference slowPointer. So the head object is directly modified.
I am trying to implement the reverse function of my own LinkedList implementation. Using my implementation of LinkedList:
public class LinkedList<T> {
public Node head;
public LinkedList(){
// Add HEAD
head = new Node(null);
}
public void add(T data){
getLastNode().next = new Node(data);
}
public void insert(int index, T data){
if(index == 0){
throw new Error(); // TODO: What is the Error Type?
}
Node current = head;
for (int i = 0; i != index - 1 ; i ++) {
current = current.next;
if (current == null){
throw new IndexOutOfBoundsException();
}
}
Node next = current.next;
Node newNode = new Node(data);
current.next = newNode;
newNode.next = next;
}
public T get(int index){
return getNode(index).data;
}
public void delete(int index){
if (index == 0){
throw new IndexOutOfBoundsException("Cannot delete HEAD node");
}
Node prev = getNode(index - 1);
Node next = prev.next.next;
prev.next = null;
prev.next = next;
}
public void reverse(){ // TODO: Last node links to a null node
Node prev = null;
Node current = head;
Node next = null;
while(current != null){
next = current.next;
current.next = prev;
prev = current;
current = next;
}
head = new Node(null);
head.next = prev;
}
public void display(){
Node current = head;
String diagram = String.format("head->");
while(current.next != null){
current = current.next;
diagram += String.format("%s->", current.data);
}
System.out.println(diagram);
}
private Node getNode(int index){
Node node = head;
for(int i = 0; i != index; i++){
node = node.next;
if(node == null){
throw new IndexOutOfBoundsException();
}
}
return node;
}
private Node getLastNode(){
Node current = head;
while(current.next != null){
current = current.next;
}
return current;
}
public class Node {
private Node next;
private T data;
public Node(T data){
this.data = data;
}
public Node getNext(){
return this.next;
}
}
}
And this main function:
LinkedList list = new LinkedList();
list.add("e1");
list.add("e2");
list.add("e3");
list.add("e4");
list.display();
list.reverse();
list.display();
The displayed result is:
head->e1->e2->e3->e4->
head->e4->e3->e2->e1->null->
This has happened due to the fact that e1 is still connected to the head. If I use the implementation of reverse available online:
Node prev = null;
Node current = head;
Node next = null;
while(current != null){
next = current.next;
current.next = prev;
prev = current;
current = next;
}
head = prev;
Then the result will ditch e4: head->e3->e2->e1->null->
What am I doing here? Why is my implementation different than everybody else's?
Also: Why does everyone use a reverse function that has head as an argument which could be problematic if the developer enters a different node?
You are using a first node as a head of your list. The solution for the reverse function is this:
head.next = prev;
You have to preserve the 'head' node, but change its 'next' field.
The rest of the function don't change at all:
public void reverse(){ // TODO: Last node links to a null node
Node prev = null;
Node current = head.next;
Node next = null;
while(current != null){
next = current.next;
current.next = prev;
prev = current;
current = next;
}
head.next = prev; // *** The only change ***
}
In your constructor you have:
public LinkedList(){
// Add HEAD
head = new Node(null);
}
then, 'head' is a Node that points to nothing initially.
In the reverse function, the 'head' node don't change, you don't need to create another out. But it has to point to the correct first Node.
If the list was empty, this 'head' points to null.
If the list has only one Node, this 'head' points to it yet.
If the list has more than one Node, this 'head' has to point to the last node.
Because of this, you need to change its 'next' field.
I searched for this alot found alota similar answers but nothing to help my exact problem.
I'm doing a push method for my double linked list, while the pointers on the head work fine, the tail next and previous pointers do not work please help.
public class MyStack<E> implements MyDeque {
private Node<E> head;
private Node<E> tail;
private int size;
public MyStack() {
head = null;
tail = null;
size = 0;
}
public void push(Object element) {
Node<E> newNode = new Node(element);
if(size == 0) {
Node temp = new Node(head);
head = newNode;
head.next = head;
head.previous = head;
tail = head;
tail.next = head;
tail.previous = temp;
}
else {
newNode.previous = head;
head = newNode;
newNode.next = tail;
(tail.next).previous = tail;
}//else statement
size++;
}//push()
public Object peek() {
if (size==0) return null;
else
return head;
}
public Object pop() {
size--;
if(size == 0)
return null;
else {
Node temp = new Node(head.previous);
head = head.previous;
head.next = tail;
head.previous = temp;
return head;
}//else
}//pop()
#Override
public int size() {
return size;
}
private class Node<E> {
private E data;
private Node<E> next;
private Node<E> previous;
public Node(E data) {
this.data = data;
this.next = null;
this.previous = null;
}
public Node(E data, Node<E> next, Node<E> previous) {
this.data = data;
this.next = next;
this.previous = previous;
}//constructor
public String toString() {
return data+"";
}
}//class Node<E>
public String toString() {
return (head+" Head\n" + head.next +" Head.Next\n" + head.previous+ " Head.previous\n"
+ tail+" Tail\n" + tail.next+" tail.next\n" + tail.previous+" tail.previous\n");
}
}
The case where you push an object when the stack is empty does not look correct. The first node added should be assigned to head. Then the tail becomes the new node's head, this new node becomes the tail node's tail, and the new node itself becomes the tail.
Usually in a stack you add and remove elements at the end (the tail). The code doesn't make it very clear what you are trying to do with the head and tail members. Maybe it would be clearer for you if you name them firstNode and lastNode.
I can actually see a few issues with this code
public class MyStack<E> implements MyDeque {
private Node<E> head;
private Node<E> tail;
private int size;
public MyStack() {
head = null;
tail = null;
size = 0;
}
This looks fine
public void push(Object element) {
Node<E> newNode = new Node(element);
if(size == 0) {
Node temp = new Node(head);
head = newNode;
head.next = head;
head.previous = head;
tail = head;
tail.next = head;
tail.previous = temp;
}
else {
newNode.previous = head;
head = newNode;
newNode.next = tail;
(tail.next).previous = tail;
}//else statement
size++;
}//push()
Bit confused why you are taking in an object instead of your generic E.
You really don't need the temp value here, in fact it looks like you are breaking your previous when you set tail.previous = temp
In your else you aren't setting the tail.previous correctly. The last line should be tail.previous = head. You also missed the head.next
So cleaned up a bit
public void push(E element) {
Node newNode = new Node(E);
if(size == 0) {
head = newNode;
head.next = head;
head.previous = head;
tail = head;
} else {
newNode.previous = head;
head.next = newNode;
newNode.next = tail;
tail.previous = newNode;
head = newNode;
}
size++;
}
In your pop method you probably want to move your size decrement after your size check, otherwise a 1 element stack will return null when popped.
edit: This would probably be easier with a singly linked list, or at least not a circular doubly linked list.
and adding at the end would probably be the more conventional way to do things.