I am trying to create a bubble sort on a doubly linked linked list in Java but am getting Null Pointer Exception errors. I believe it to have an issue with when I call the getPrevious method on the head which of course has a value of null. However, I cannot think how to do the bubble sort without accessing the getPrevious method for the other nodes.
I can implement an if statement to check if its the head or tail of the list first, but I feel like there is a smarter way to do this.
I also have been unable to run a successful build of this, so am not even sure the code will work. If you have a different idea of how to implement this please let me know.
Any suggestions are welcome!
public static void bubbleSort(DoubleLinkedList list) //static method used to sort the linked list using bubble sort
{
int i = 0;
int j = 0;
Node currentNode = list.head;
Node previousNode = currentNode;
Node tempNext = currentNode;
Node tempPrevious = currentNode;
for(i=0; i<list.getSize(); i++)
{
for(j=0; j<list.getSize()-1; i++)
{
if(currentNode.getData() > currentNode.getNext().getData())
{
tempNext = currentNode.getNext().getNext();
tempPrevious = currentNode.getPrevious();
currentNode.getPrevious().setNext(currentNode.getNext());
currentNode.getNext().setNext(currentNode);
currentNode.setPrevious(currentNode.getNext());
currentNode.setNext(tempNext);
}
currentNode = currentNode.getNext();
}
}
}
So you have a double linked list. I assume each element contains some information... say an integer. It must also contain two pointers: one to the previous element and one to the next element.
Assuming this is true, notice that you don't have to modify the pointers because they already point from one element to another. all you have to do is sort the values of the list elements so that the first item in the list has the lowest value, the second has the second lowest value and so on.
You can do it like this:
public static void bubbleSort(DoubleLinkedList list) //static method used to sort the linked list using bubble sort {
int i = 0;
Node currentNode = list.head;
Node auxNode;
int foundChange = 1;
while(foundChange) {
foundChange = 0;
for(i=0; i<list.getSize()-1; i++) {
if (currentNode.getData() > currentNode.getNext().getData()) {
auxNode.setData(currentNode.getData());
currentNode.setData(currentNode.getNext.getData());
currentNode.getNext.setData(auxNode.getData());
foundChange = 1;
}
currentNode = currentNode.getNext();
}
}
If you haven't defined the setData method yet, then do so. It must be similar to getData, but it will set the data of an object to the value it gets as a parameter instead of returning the value of the data in that object.
Related
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 am still a little confused on how to implement a doubly linked list. After researching and finding some information about them, I've got a good visual of how some of the basic functions work, such as add, remove etc. However, If I wanted to write a method for a DLList called countEquals (E check) that walks the entire list and counts the number of items in the list that are equal to the "Check" data item passed to the method, how would I write this. The instructions say I cannot use a for-each loop or an iterator, but a loop of some sort must be used. After the list is fully traversed, return the number of items that are equal to "check". Here is some code that I have tried to write for this:
internal references of DLList: Fields (next, data, prev) Members (size), head and tail.
public int countEquals(E Check){
currentNode = head;
int count = 0;
while (currentNode != null) {
if (currentNode.data == check) {
count ++;
else {
currentNode.next = currentNode;
}
return count;
}
I'm not too sure if this will correctly walk a doubly linked list, if I have to write more pointer assignments? I was thinking that because I'm not adding any nodes, but just walking a list, I wouldnt need to do the pointers.
Almost there, good effort. However, just a couple of things. First, you may want to look into using something.equals() rather than == since the latter is for object identity rather than value equality.
Second. the logic for traversing the list is slightly off. It needs to be done regardless of whether an item was found, and the sides of the assignment should be reversed.
Have a look at the following pseudo-code for guidance:
def countEquals(check):
currentNode = head
count = 0
while currentNode != null:
if currentNode.data == check:
count = count + 1
currentNode = currentNode.next
return count;
do it this way, if data is integer
while (currentNode != null) {
if (currentNode.data == check) {
count ++;
currentNode.next = currentNode;
}
else {
currentNode.next = currentNode;
}
}
return count;
I am working on a traveling salesman problem here and my p-queue isn't operating it is simply taking the last item added. I was wonder if anyone could help me figure out the error. here is my Node class (nodes which are added to the queue):
import java.util.*;
public class Node implements Comparable< Node >{
//level of node
int level;
//stores path of node
ArrayList< Integer > path = new ArrayList< Integer >();
//bound of node
int bound;
/** Over-rides compareTo for priority queue handling
* #return int desired sorting value
*/
public int compareTo(Node aNode)
{
if (this.bound<aNode.bound)
{
return 1;
}
if (this.bound>aNode.bound)
{
return -1;
}
else
{
return 0;
}
}
}
and here is the p-queue implementation:
PriorityQueue< Node > theQ = new PriorityQueue< Node >();
The algorithm is implemented correctly the p-queue simply is not putting the lowest bound as the head. I even reversed the the returns on the compareTo with no effect on the p-queue output (signifying to me that the queue is not sorting. I have wasted hours trying to figure it out and also asking some classmates (no-one can discern the problem) taking a shot here to see if anyone knows why the queue is acting like this..
Your code works perfectly fine for me.
What I suspect you're doing is changing the the bound value of a single object and repeatedly adding it, giving you a queue full of the same object (lots of references to it) which of course has the single (last) value you set it to.
public static void main(String[] args)
{
PriorityQueue< Node > theQ = new PriorityQueue< Node >();
Node n = new Node();
n.bound = 6;
theQ.add(n);
n = new Node();
n.bound = 9;
theQ.add(n);
n = new Node();
n.bound = 4;
theQ.add(n);
while ((n = theQ.poll()) != null)
System.out.println("Bound = " + n.bound);
}
Output:
Bound = 9
Bound = 6
Bound = 4
Make sure you are iterating through the PriorityQueue by using the methods provided by the Queue interface, ex. remove to pop an element off the top. In pseudo code:
for each element in some other collection
priorityQueue.add(element)
while priorityQueue is not empty
Set node to priorityQueue.remove()
Do stuff with node
If you are trying to iterate through a for-each loop or PriorityQueue.iterator:
The Iterator provided in method
iterator() is not guaranteed to
traverse the elements of the priority
queue in any particular order.
Alternatively, if you don't want to destroy/remove elements from your PriorityQueue to iterate in order, you could use, as the documentation suggests,
Arrays.sort(pq.toArray())
I am looking for a method that reverses the same instance of a given list, with O(1) additional space and O(n) time.
this is not HW nor I am looking for some library method to do the job for me, as this is only an exercise for myself, and out of pure curiousity.
any ideas how to do it with O(1) additional space and O(n) time? (and if possible without reflection as well)?
signature is public <T> void reverse(List<T> list).
(*)assume get() to the head and tail of the list is O(1), but to the middle of it is O(n).
I came up with a recursive solution, but it is O(n) space, O(n) time
public <T> void reverseAux(List<T> list,int size) {
if (size == 0) return;
T elem = list.remove(size-1);
reverseAux(list,size-1);
list.add(0,elem);
}
public <T> void reverse(List<T> list) {
reverseAux(list, list.size());
}
EDIT: I am looking for a java solution, for List<T>, only assumption on implementation is access time O(1) for head and tail, and using List<T> interface.
Just read one of the following. It is the thing you're talking about.
Please note that we're talking about singly 'linked' lists.
http://www.teamten.com/lawrence/writings/reverse_a_linked_list.html
http://www.mytechinterviews.com/reverse-a-linked-list
http://www.geekpedia.com/code48_Reverse-a-linked-list.html
http://www.codeproject.com/KB/recipes/ReverseLinkedList.aspx
Plus an extra question for you:
How would you find Nth element from the tail of a linked list assuming it is singly linked and you have only head pointer with O(1) space and O(N) time?
using ListIterators:
ListIterator<T> head = list.listIterator();
ListIterator<T> tail = list.listIterator(size);//assuming this can be done in O(1) though O(n) doesn't hurt that much and total is still O(n)
while(head.nextIndex()<tail.previousIndex()){
T tmp = head.next();
head.set(tail.previous());
tail.set(tmp);
}
You already know the length. So just use 1 temporary variable and start at index 0 and go on swapping list[0] and list[length -1], then list[1] and list[length-2], and so on. O(n) time and O(1) space for 1 temporary variable.
EDIT: Just noticed you assume O(n) for accessing the middle of the list. oh well. nevermind.
alternatively, store the next/previous pointers of the two elements you swapped to move towards the middle (assuming it's a doubly linked list). Then you get O(n) time.
The best performance you can get from comparison sorts like merge sort or quick sort is O(nlogn). You can get O(n) performance from non-comparison sorts like radix sort.
If you are reversing a linked-list, then you can reverse the list in O(n) time with using just 3 extra items. You need 3 pointers to keep track of what you're currently pointing to, what is before your current item and what is after your current item. The code is:
Node current = head;
Node next = null;
Node prev = null;
while (current != null) {
next = current.next;
current.next = prev;
prev = current;
current = next;
}
return prev;
As discussed, in the general case this is not doable, you need to assume something about the complexity of the individual operations. If you have constant-time next() and previous() for the iterators, use the solution already given. It should work for both LinkedList and ArrayList.
I thought about a solution which would work for a singly-linked list (but not for something like ArrayList), but sadly the ListIterators add method inserts the element before the cursor instead of after it, thus it is not doable with the List + ListIterator interfaces (if we can't patch the ListIterator implementation to cache the pre-insert element to allow a single previous() after add in O(1)).
Here, assuming a simple Node class with next-pointer:
/**
* reverses a singly linked list.
* #param first the fist node. This will be the new last node.
* #param last the last node. This will be the new first node.
*/
void reverseList(Node first, Node last) {
while(first != last) {
Node temp = first;
first = temp.next;
temp.next = last.next;
last.next = temp;
}
}
In index terms, this would be something like this:
public void reverseList(List<T> list) {
int index = list.size() -1;
while(n > 0) {
T element = list.remove(0);
list.add(n, element);
n--;
}
}
In ListIterator terms, this would be something like this:
public void reverseList(List<T> list) {
ListIterator<T> it = list.listIterator(list.size());
while(it.previousIndex() > 0) { // we could count ourself here, too
T element = list.remove(0);
it.add(element);
it.previous();
}
}
Of course, usual singly linked list implementations will not have a O(1) previous implementation, thus it will not work there, as said before. (And they might throw a ConcurrentModificationException, or return erronous previousIndex.)
Here is a solution in Java, with O(n) time complexity (just a single pass) and O(1) space complexity (Using just two temporary variables):
private static void reverseLinkedList() {//O(n) Time complexity, O(1) space complexity
//two temp pointers
Node next = null, previous = null;
while(head.next != null){
next = head.next;//move next to next address
head.next = previous; //previous node will be the next node for head, so that head will point reverse
previous = head; //incrementing previous to the current node
head = next; //incrementing head
}
//at this point head points to last node and previous has the remaining reversed array
head.next = previous;
System.out.println("\nReversed");
}
Full code goes like:
package com.test;
public class LinkedListReverse {
private static Node head;
public static void main(String[] args) {
for(int i = 0 ; i< 10 ; i++){
addToLinkedList(i);
}
System.out.println("Added Data");
printLinkedList();
reverseLinkedList();
printLinkedList();
}
private static void reverseLinkedList() {//O(n) Time complexity, O(1) space complexity
//two temp pointers
Node next = null, previous = null;
while(head.next != null){
next = head.next;//move next to next address
head.next = previous; //previous node will be the next node for head, so that head will point reverse
previous = head; //incrementing previous to the current node
head = next; //incrementing head
}
//at this point head points to last node and previous has the remaining reversed array
head.next = previous;
System.out.println("\nReversed");
}
/* Logic for adding and printing linked list*/
private static void printLinkedList() {
System.out.println("Printing linked list");
Node temp = head;
while(temp.next != null){
System.out.print(temp.value+" ");
temp = temp.next;
}
System.out.print(temp.value+" ");//print the value at the last node
}
private static void addToLinkedList(int value){
if(head == null){
head = new Node(value, null);
}else{
Node temp = head;
while(temp.next != null){
temp = temp.next;
}
temp.next = new Node(value, null);
}
}
}
//Linked List definition
class Node{
int value;
Node next;
public Node(int value, Node next){
this.value = value;
this.next = next;
}
}
Program's Output:
Added Data
Printing linked list
0 1 2 3 4 5 6 7 8 9
Reversed
Printing linked list
9 8 7 6 5 4 3 2 1 0
Hope it helps :)
The ListIterator interface is what you're looking for (under the reasonable assumption that the list in question fully supports it; both ArrayList and LinkedList do):
ListIterator<T> fwd = list.listIterator();
ListIterator<T> back = list.listIterator(list.size());
while (fwd.nextIndex() < back.previousIndex()) {
T tmp = fwd.next();
fwd.set(back.previous());
back.set(tmp);
}
Even on linked lists, this should be linear in time.
public LinkedList Reverse(LinkedList head)
{
if (head == null) return null; // first question
if (head.Next == null) return head; // second question
// third question
// so we grab the second element (which will be the last after we reverse it)
LinkedList secondElem = head.Next;
// bug fix - need to unlink list from the rest or you will get a cycle
head.Next = null;
// then we reverse everything from the second element on
LinkedList reverseRest = Reverse(secondElem);
// then we join the two lists
secondElem.Next = head;
return reverseRest;
}
I want to be able to access a certain node in my Doubly Linked List in O(1) time. I know that if i traverse the list to find a certain node it would take O(n) time so I want to map the nodes to an array list where I can access the nodes in O(1) time.
I'm really unsure how I would do this mapping. I would like to see an example of how this can be done.
Edit:
I would like to be able to access any node in the linked list so I can move the nodes around in O(1) time.
Example: Move node with ID 5 to end of list in O(1) time.
Edit 2: I uploaded a picture example of what I'm trying to accomplish
You can't do this with the built-in data structures ArrayList and LinkedList.
In general, it is not possible at all to have both of
O(1) indexing (by position in the list)
O(1) removing/adding/moving anywhere in the list.
The possibilities:
You can get to O(log(N)) for both these if you use a tree-based structure.
You can get to O(1) for indexing with a array-based structure, but then removing/adding in the middle takes O(n).
You can use a Hash-Map like-structure with adding/removing in O(1), but it only allows O(1) access by key, not access by index (other than iterating, i.e. O(n)). (This means, if you add/remove something in the middle, the indexes after it won't change.)
Even if you try to combine a linked list with an array, you'll have O(n) for removing/adding (since you still have to update the array).
Okay, with your added image to show what you want, it is doable. You are in fact reimplementing something like LinkedHashMap, but only with consecutive integer keys and with ability to manipulate the "Linked" part.
If your linked list consists of Node objects, you would have an ArrayList<Node>.
You would only add elements to the ArrayList when adding new nodes to the linked list, else use the ArrayList only for lookup.
Here is an example:
class FastIndexLinkedIntList<X> {
class Node {
Node next;
Node prev;
int key;
X value;
Node(int key, X val) { this.key = key; this.value = val; }
}
ArrayList<Node> indexedNodes = new ArrayList<Node>();
Node head;
Node tail;
public void add(X value) {
int key = indexedNodes.size();
Node node = new Node(key, value);
insertAtEnd(node);
indexedNodes.add(node);
}
private void insertAtEnd(Node n) {
if(tail == null) {
assert head == null;
head = n;
tail = n;
return;
}
n.prev = tail;
n.next = null;
tail.next = n;
tail = n;
}
private void removeNode(Node n) {
if(n.next == null) {
assert n == tail; // last node
tail = n.prev;
tail.next = null;
}
else {
n.next.prev = n.prev;
}
if(n.prev == null) {
assert n == head; // first node
head = n.next;
head.prev = null;
}
else {
n.prev.next = n.next;
}
}
public void moveNodeToEnd(int key) {
Node n = indexedNodes.get(key);
removeNode(n);
insertAtEnd(n);
}
}
You might want to add more operations here, but these are enough for the example in the question:
FastIndexedLinkedList<String> ll = new FastIndexedLinkedList<String>();
ll.add("0");
ll.add("1");
ll.add("2");
ll.add("3");
ll.moveNodeToEnd(2);
I'm not entirely sure of your purpose, do you simply wish to retrieve the object's index in O(1)?
This is how it would look:
LinkedList<Object> aList; // your LinkedList
Map<Object, Integer> mapper = new HashMap<Object, Integer>();
Object[] arr = aList.toArray();
for( int i = 0; i < arr.length; i++ ){
mapper.put( arr[i], i );
}
Now, if you want to find an object in your list, what you do is get its index from the mapper object with
mapper.get( o );
================================
Re: your edit
You can't (or there's none that I am aware of). You are essentially demanding the best of both worlds (linked lists and arrays).
LinkedHashMap: provides O(1) time and keys are doubly-linked list ordered.
Use the toArray() method to convert your LinkedList to an array for constant-time retrieval:
LinkedList.toArray(arr)