Doubly Linked List logic - java

I am trying to run a test for a getPrevious() method in JUnit.
public void getPrev(){
for (int i = 0; i < 1000; i++) {
list.add(i);
}
list.reset();
for (int i = 999; i >= 0; i--) {
int info = list.getPrevious();
assertEquals(i, info);
}
}
Every other method seem to work, except for this one. After running some printing tests, I realized that the reset method
...reset(){
if (list != null)
location = list.getPrev();//returns the last node's previous node -- head node.
}
(which should make the location node the head node) was not returning the correct information. It returned null instead of the head node.
Thus, my logic led me to believe that the add method was not working as it should be. And this is also my question. I have been trying multiple things to see where the error is but nothing seem to work. I am looking to see if anyone can help spot the logic error in this code.
public void add(Object elem) {
LLNode<T> newNode = new LLNode(elem);
if(list == null){
tail = list = newNode;
}
list.setPrev(newNode);
newNode.setNext(list);
newNode.setPrev(tail);
tail.setNext(newNode);
list = newNode;
size++;
}

Try This
public int add(Object elem) {
Node node = new Node(elem);
if (head == null) {
head = node;
} else {
tail.setNext(node);
node.setPrevious(tail);
}
tail = node;
return value;
}

Related

Removing an element by index in a linked list

A method for removing an element from a linked list has been implemented:
public void remove(T e) {
Node<T> node = first;
Node<T> prevNode = null;
while(node != null){
if(e.equals(node)){
if(prevNode == null) {
first = node.next;
}
else {
prevNode.next = node.next;
}
size--;
}
else {
prevNode = node;
}
node = node.next;
}
}
How to correctly implement deleting an element by index? Using the capabilities of the remove method.
public void removeByIndex(int i) {
remove(i);
}
Something like this should work:
public void remove(int i) {
if (i >= size || i < 0) {
throw new ArrayIndexOutOfBoundsException();
}
Node<T> remove;
if (i == 0) {
remove = first;
first = first.next;
first.prev = null; // <- For double linked list
} else {
Node<T> node = first;
for (int j = 0; j < i - 1; ++j) {
node = node.next;
}
remove = node.next;
if (i == size - 1) {
node.next = null;
} else {
node.next.next.prev = node; // <- For double linked list
node.next = node.next.next;
}
}
// Clear links from removed Node
remove.next = null;
remove.prev = null; // <- For double linked list
size--;
}
Find the node before position i. Point that node to the "over next" node.
Edit
The original code example was a rough sketch at best. Updated with a more complete version.
Edit #2
Slight improvements:
Clears links from the removed node
Also handles double linked lists
remove(get(i));
This is not the most efficient solution, but a simple one which uses the remove(T) method. You call it with get(i) as the object to be removed - which is the element at the specified index.
Note: This solution has some issues if the list has duplicate values, but in that case you shouldn't use the remove(T) method anyway. If you want it to be safe, iterate to the specified index:
Node<T> node = first;
for(int i=0;i<index;i++){
prevNode=node;
node=node.next;
}
and do this:
node.prev.next=node.next;
node.next.prev=node.prev;
size--;
Of course, this is just a rough implementation. To ensure full compability, you should check if the index is valid and use the unlink(Node) method of LinkedList.
The LinkedList also has an implementation for the remove(int) method:
checkElementIndex(index);
return unlink(node(index));

Add method java

I want to add a method add(int index, E element) in Java, that inserts a specified element at a specified index in the list and shifts the element currently at that position (if any) and any subsequent elements to the right (adds one to their indices). But I guess something is wrong with the indices in my code in the for-loop. Any ideas how to solve it?
public class SingleLinkedList<E> implements ISingleLinkedList<E> {
Node head;
int size = 0;
#Override
public void add(int index, E element) throws IndexOutOfBoundsException {
Node newNode = new Node(element);
if(head == null && index == 0) {
head = newNode;
}
else if (index == 0 && head != null) {
Node tempNode = new Node(element);
tempNode.setmNextNode(head);
head = tempNode;
}
else {
Node tempNode = head;
for(int i = 1; i<index; i++) {
tempNode = tempNode.getmNextNode();
}
/**Node newNode = new Node(element);**/
newNode.setmNextNode(tempNode);
tempNode.setmNextNode(newNode);
}
size++;
}
}
My code for the Node class is:
public class Node<E> {
private E mElement;
private Node<E> mNextNode;
Node(E data) {
this.setmElement(data);
}
public E getmElement() {
return this.mElement;
}
public void setmElement(E element) {
this.mElement = element;
}
public Node<E> getmNextNode()
{
return this.mNextNode;
}
public void setmNextNode(Node<E> node)
{
this.mNextNode = node;
}
The problem is that I have a JUnit test that fails when adding this method and I do not know what more I need to add in order to pass the test.
#Test
public void testAddWithIndexesToListWith5Elements() {
int listSize = 5;
// First create an ArrayList with string elements that constitutes the test data
ArrayList<Object> arrayOfTestData = generateArrayOfTestData(listSize);
// Then create a single linked list consisting of the elements of the ArrayList
ISingleLinkedList<Object> sll = createSingleLinkedListOfTestData(arrayOfTestData);
// Add new elements first, in the middle and last to the ArrayList of test data
// and the single linked list
try {
arrayOfTestData.add(0, 42);
arrayOfTestData.add(3, "addedElement1");
arrayOfTestData.add(7, "addedElement2");
sll.add(0, 42);
sll.add(3, "addedElement1");
sll.add(7, "addedElement2");
}
catch (Exception e) {
fail("testAddWithIndexesToListWith5Elements - add() method failed");
}
// Check that the contents are equal
for (int i = 0; i < sll.size(); i++) {
assertEquals(arrayOfTestData.get(i), sll.get(i));
}
}
newNode.setmNextNode(tempNode);
tempNode.setmNextNode(newNode);
This is just going to create a cycle. It looks like your newNode should point to tempNode.getmNextNode() or something along those lines.
Your question is pretty unclear but I think I can see a problem.
If index is not 0, the you will iterate through the nodes until the index is reached.
If there are not enough elements in the list, you will reach the end of the list before the index where you want to insert the element.
In this case,
tempNode = tempNode.getmNextNode();
will set tempNode to null.
In the next iteration, this line will throw a NullPointerException.
You can bypass this issue by testing if tempNode.getmNextNode(); is null.
If that is the case, the element will just be inserted at the end/that point or will not be inserted.

Recursively insert at the end of doubly linked list

I have a doubly linked list, and I want to insert an element at the end of the list recursively. I have a method now that does this without recursion, and it works. I just can't seem to understand how to do it with recursion. Inserting at the end of a singly linked list with recursion is quite easy to understand I think, so I hope that someone can explain how to it do it when the list is doubly linked. Here is my normal insertion method that I want to make recursive:
public void insert(T element) {
Node in = new Node(element);
if (in == null) {
first = in;
} else {
Node tmp = first;
while (tmp.next != null) {
tmp = tmp.next;
}
tmp.next = in;
in.prec = tmp;
}
}
The idea is just to re-write the while loop with a function call:
public void insert(T element) {
insert(element, first); // initialization
}
private void insert(T e, Node n) {
if(n == null) { // if the list is empty
first = new Node(e);
} else if(n.next == null) { // same condition as in the while loop
None newNode = new Node(e);
n.next = newNode;
newNode.prec = n;
} else {
insert(e, n.next); // looping
}
}

Recursion - Reverse LinkedList with void function return type

I was trying to reverse a linked list using recursion. I got the solution, but can't get it to work for below question found on internet.
Reverse a linked list using recursion but function should have void
return type.
I was able to implement the function with return type as Node. Below is my solution.
public static Node recursive(Node start) {
// exit condition
if(start == null || start.next == null)
return start;
Node remainingNode = recursive(start.next);
Node current = remainingNode;
while(current.next != null)
current = current.next;
current.next = start;
start.next = null;
return remainingNode;
}
I cannot imagine if there will be such a solution to this problem.
Any suggestions ?
Tested, it works (assuming you have your own implementation of a linked list with Nodes that know the next node).
public static void reverse(Node previous, Node current) {
//if there is next node...
if (current.next != null) {
//...go forth and pwn
reverse(current, current.next);
}
if (previous == null) {
// this was the start node
current.next= null;
} else {
//reverse
current.next= previous;
}
}
You call it with
reverse(null, startNode);
public void recursiveDisplay(Link current){
if(current== null)
return ;
recursiveDisplay(current.next);
current.display();
}
static StringBuilder reverseStr = new StringBuilder();
public static void main(String args[]) {
String str = "9876543210";
reverse(str, str.length() - 1);
}
public static void reverse(String str, int index) {
if (index < 0) {
System.out.println(reverseStr.toString());
} else {
reverseStr.append(str.charAt(index));
reverse(str, index - 1);
index--;
}
}
This should work
static void reverse(List list, int p) {
if (p == list.size() / 2) {
return;
}
Object o1 = list.get(p);
Object o2 = list.get(list.size() - p - 1);
list.set(p, o2);
list.set(list.size() - p - 1, o1);
reverse(list, p + 1);
}
though to be efficient with LinkedList it should be refactored to use ListIterator
I am not familiar with Java, but here is a C++ version. After reversing the list, the head of list is still preserved, which means that the list can still be accessible from the old list head List* h.
void reverse(List* h) {
if (!h || !h->next) {
return;
}
if (!h->next->next) {
swap(h->value, h->next->value);
return;
}
auto next_of_next = h->next->next;
auto new_head = h->next;
reverse(h->next);
swap(h->value, new_head->value);
next_of_next->next = new_head;
h->next = new_head->next;
new_head->next = nullptr;
}
Try this code instead - it actually works
public static ListElement reverseListConstantStorage(ListElement head) {
return reverse(null,head);
}
private static ListElement reverse(ListElement previous, ListElement current) {
ListElement newHead = null;
if (current.getNext() != null) {
newHead = reverse(current, current.getNext());
} else {//end of the list
newHead=current;
newHead.setNext(previous);
}
current.setNext(previous);
return newHead;
}
public static Node recurse2(Node node){
Node head =null;
if(node.next == null) return node;
Node previous=node, current = node.next;
head = recurse2(node.next);
current.next = previous;
previous.next = null;
return head;
}
While calling the function assign the return value as below:
list.head=recurse2(list.head);
The function below is based on the chosen answer from darijan, all I did is adding 2 lines of code so that it'd fit in the code you guys want to work:
public void reverse(Node previous, Node current) {
//if there is next node...
if (current.next != null) {
//...go forth and pwn
reverse(current, current.next);
}
else this.head = current;/*end of the list <-- This line alone would be the fix
since you will now have the former tail of the Linked List set as the new head*/
if (previous == null) {
// this was the start node
current.next= null;
this.tail = current; /*No need for that one if you're not using a Node in
your class to represent the last Node in the given list*/
} else {
//reverse
current.next= previous;
}
}
Also, I've changed it to a non static function so then the way to use it would be: myLinkedList.reverse(null, myLinkedList.head);
Here is my version - void ReverseWithRecursion(Node currentNode)
- It is method of LinkListDemo Class so head is accessible
Base Case - If Node is null, then do nothing and return.
If Node->Next is null, "Make it head" and return.
Other Case - Reverse the Next of currentNode.
public void ReverseWithRecursion(Node currentNode){
if(currentNode == null) return;
if(currentNode.next == null) {head = currentNode; return;}
Node first = currentNode;
Node rest = currentNode.next;
RevereseWithRecursion(rest);
first.next.next = first;
first.next = null;
}
You Call it like this -
LinkListDemo ll = new LinkListDemo(); // assueme class is available
ll.insert(1); // Assume method is available
ll.insert(2);
ll.insert(3);
ll.ReverseWithRecursion(ll.head);
Given that you have a Node class as below:
public class Node
{
public int data;
public Node next;
public Node(int d) //constructor.
{
data = d;
next = null;
}
}
And a linkedList class where you have declared a head node, so that it can be accessed by the methods that you create inside LinkedList class. The method 'ReverseLinkedList' takes a Node as an argument and reverses the ll.
You may do a dry run of the code by considering 1->2 as the linkedList. Where node = 1, node.next = 2.
public class LinkedList
{
public Node? head; //head of list
public LinkedList()
{
head = null;
}
public void ReverseLinkedList(Node node)
{
if(node==null)
{
return;
}
if(node.next==null)
{
head = node;
return;
}
ReverseLinkedList(node.next); // node.next = rest of the linkedList
node.next.next = node; // consider node as the first part of linkedList
node.next = null;
}
}
The simplest method that I can think of it's:
public static <T> void reverse( LinkedList<T> list )
{
if (list.size() <= 1) {
return;
}
T first = list.removeFirst();
reverse( list);
list.addLast( first );
}

Manually sorting a linked list in Java (lexically)

I am implementing my own linked list in Java. The node class merely has a string field called "name" and a node called "link". Right now I have a test driver class that only inserts several names sequentially. Now, I am trying to write a sorting method to order the nodes alphabetically, but am having a bit of trouble with it. I found this pseudocode of a bubblesort from someone else's post and tried to implement it, but it doesn't fully sort the entries. I'm not really quite sure why. Any suggestions are appreciated!
private void sort()
{
//Enter loop only if there are elements in list
boolean swapped = (head != null);
// Only continue loop if a swap is made
while (swapped)
{
swapped = false;
// Maintain pointers
Node curr = head;
Node next = curr.link;
Node prev = null;
// Cannot swap last element with its next
while (next != null)
{
// swap if items in wrong order
if (curr.name.compareTo(next.name) < 0)
{
// notify loop to do one more pass
swapped = true;
// swap elements (swapping head in special case
if (curr == head)
{
head = next;
Node temp = next.link;
next.link = curr;
curr.link = temp;
curr = head;
}
else
{
prev.link = curr.link;
curr.link = next.link;
next.link = curr;
curr = next;
}
}
// move to next element
prev = curr;
curr = curr.link;
next = curr.link;
}
}
}
I spent some minutes eyeballing your code for errors but found none.
I'd say until someone smarter or more hard working comes along you should try debugging this on your own. If you have an IDE like Eclipse you can single-step through the code while watching the variables' values; if not, you can insert print statements in a few places and hand-check what you see with what you expected.
UPDATE I
I copied your code and tested it. Apart from the fact that it sorts in descending order (which may not be what you intended) it worked perfectly for a sample of 0, 1 and 10 random nodes. So where's the problem?
UPDATE II
Still guessing what could be meant by "it doesn't fully sort the entries." It's possible that you're expecting lexicographic sorting (i.e. 'a' before 'B'), and that's not coming out as planned for words with mixed upper/lower case. The solution in this case is to use the String method compareToIgnoreCase(String str).
This may not be the solution you're looking for, but it's nice and simple. Maybe you're lazy like I am.
Since your nodes contain only a single item of data, you don't really need to re-shuffle your nodes; you could simply exchange the values on the nodes while leaving the list's structure itself undisturbed.
That way, you're free to implement Bubble Sort quite simply.
you should use the sorting procedures supplied by the language.
try this tutorial.
Basically, you need your element class to implement java.lang.Comparable, in which you will just delegate to obj.name.compareTo(other.name)
you can then use Collections.sort(yourCollection)
alternatively you can create a java.util.Comparator that knows how to compare your objects
To obtain good performance you can use Merge Sort.
Its time complexity is O(n*log(n)) and can be implemented without memory overhead for lists.
Bubble sort is not good sorting approach. You can read the What is a bubble sort good for? for details.
This may be a little too late. I would build the list by inserting everything in order to begin with because sorting a linked list is not fun.
I'm positive your teacher or professor doesn't want you using java's native library. However that being said, there is no real fast way to resort this list.
You could read all the nodes in the order that they are in and store them into an array. Sort the array and then relink the nodes back up. I think the Big-Oh complexity of this would be O(n^2) so in reality a bubble sort with a linked list is sufficient
I have done merge sort on the singly linked list and below is the code.
public class SortLinkedList {
public static Node sortLinkedList(Node node) {
if (node == null || node.next == null) {
return node;
}
Node fast = node;
Node mid = node;
Node midPrev = node;
while (fast != null && fast.next != null) {
fast = fast.next.next;
midPrev = mid;
mid = mid.next;
}
midPrev.next = null;
Node node1 = sortLinkedList(node);
Node node2 = sortLinkedList(mid);
Node result = mergeTwoSortedLinkedLists(node1, node2);
return result;
}
public static Node mergeTwoSortedLinkedLists(Node node1, Node node2) {
if (null == node1 && node2 != null) {
return node2;
} else if (null == node2 && node1 != null) {
return node1;
} else if (null == node1 && null == node2) {
return null;
} else {
Node result = node1.data <= node2.data ? node1 : node2;
Node prev1 = null;
while (node1 != null && node2 != null) {
if (node1.data <= node2.data) {
prev1 = node1;
node1 = node1.next;
} else {
Node next2 = node2.next;
node2.next = node1;
if (prev1 != null) {
prev1.next = node2;
}
node1 = node2;
node2 = next2;
}
}
if (node1 == null && node2 != null) {
prev1.next = node2;
}
return result;
}
}
public static void traverseNode(Node node) {
while (node != null) {
System.out.print(node + " ");
node = node.next;
}
System.out.println();
}
public static void main(String[] args) {
MyLinkedList ll1 = new MyLinkedList();
ll1.insertAtEnd(10);
ll1.insertAtEnd(2);
ll1.insertAtEnd(20);
ll1.insertAtEnd(4);
ll1.insertAtEnd(9);
ll1.insertAtEnd(7);
ll1.insertAtEnd(15);
ll1.insertAtEnd(-3);
System.out.print("list: ");
ll1.traverse();
System.out.println();
traverseNode(sortLinkedList(ll1.start));
}
}
The Node class:
public class Node {
int data;
Node next;
public Node() {
data = 0;
next = null;
}
public Node(int data) {
this.data = data;
}
public int getData() {
return this.data;
}
public Node getNext() {
return this.next;
}
public void setData(int data) {
this.data = data;
}
public void setNext(Node next) {
this.next = next;
}
#Override
public String toString() {
return "[ " + data + " ]";
}
}
The MyLinkedList class:
public class MyLinkedList {
Node start;
public void insertAtEnd(int data) {
Node newNode = new Node(data);
if (start == null) {
start = newNode;
return;
}
Node traverse = start;
while (traverse.getNext() != null) {
traverse = traverse.getNext();
}
traverse.setNext(newNode);
}
public void traverse() {
if (start == null)
System.out.println("List is empty");
else {
Node tempNode = start;
do {
System.out.print(tempNode.getData() + " ");
tempNode = tempNode.getNext();
} while (tempNode != null);
System.out.println();
}
}
}

Categories