So I'm trying to get my Doubly Linked List to do an insertionSort
I'm having issues right now with just moving the nodes to their proper spot. I have gotten comparisons working but none of my nodes move.
public void insertionSort()
{
Node temp;
Node start = this.head.next;
Node next = start.next;
Node prev = this.head;
while(start != this.head)
{
if(start.data.compareTo(next.data) > 0) //start is larger than next
{
temp = start;
start = next;
next = temp;
}
start = start.next;
next = next.next;
prev = prev.next;
}
}
I was wondering if someone could help me in getting this algorithm right. I'm using a circular doubly linked list to try and test various sort routines for time complexity.
Fun puzzle!
The main problem I can see with your algorithm is that you only give the node being inserted the opportunity to move one place back.
Insertion sort looks from the second node in a list to the last one by one, swapping them backward until they are sorted in the preceding already sorted list. That might take several swaps, but your algorithm only allows for one (when your if condition is true) or zero (when it's false). For example, say we are sorting:
b c a
Your insertion sort would work when start is at b and c, then it would move to a. Here you say 'if a is before c, swap it with c', giving:
b a c
...but then your algorithm would terminate. Since there are an undetermined number of swaps you need to do for each node being inserted, you need another while loop there. Here is the pseudocode for an insertion sort algorithm:
function insertion_sort(items) {
while (i=1; i < items length; i++) { // for elements 1 to n
while (j=i; j >= 0; j--) { // look backward through all previously sorted items
if (items element at j < items element at j-1) {
swap element at j with element at j-1
} else {
break out of the loop
}
}
}
}
Related
public T removeAt(int index) {
// Make sure the index provided is valid
if (index < 0 || index >= size) {
throw new IllegalArgumentException();
}
int i;
Node<T> trav;
// Search from the front of the list
if (index < size / 2) {
for (i = 0, trav = head; i != index; i++) {
trav = trav.next;
}
// Search from the back of the list
} else
for (i = size - 1, trav = tail; i != index; i--) {
trav = trav.prev;
}
return remove(trav);
}
Explain how this traversal for the removal of a doubly linked list.
I don't understand the for loop
The only thing this function does is finding the specified element in the list. The actual removal is done by the other method in the last call (remove(trav)).
The first if just checks whether the specified index exists in the list.
After that, it iterates through the list until it finds the specified element. It uses a temporary Node trav. The iteration is simple: get the first object -> get next element if the index is not reached -> get next element etc.
There is a twist though: If the index is in the second half of the list, it iterates backwards from the end of the list. This is a small performance optimisation, since it only has size/2 iterations at max.
Let's take an example, imagine we had these elements LinkedList:
[1,5,9,11,3]
indexes-> 0 1 2 3 4
size -> 5
Now let's say you want to remove the last element, which has an index of 4, so we call removeAt(4). In order to not traverse all the LinkedList from the start, we instead check if the index is bigger then size/2. 4<2 ? false. Means we start from the tail.
Node trav is basically a pointer to traverse the LinkedList. When you got to that particular index you just call the method remove and pass the current node. remove(trav).
I was reading about circular linked lists. Here is a code which I do not understand how it works.
public int elementAt(int index){
if(index>size){
return -1;
}
Node n = head;
while(index-1!=0){ // this line is unclear for me
n=n.next;
index--;
}
return n.data;
}
I would write the same code but in this way :
public int elementAt(int index){
if(index>size){
return -1;
}
Node n = head;
while(n.size != index){ // here is my change in the code
n=n.next;
}
return n.data;
}
Here is the whole code : http://algorithms.tutorialhorizon.com/circular-linked-list-complete-implementation/
Am I doing right in the second code ?
Thanks
The example code uses a 1-based index: 1, 2, 3, ..., size. Which is strange in computer science, where one would expect: 0, .. , size-1.
Unfortunately size is a property of the entire list, not a single Node in the list. So their solution is fine.
Though when index <= 0 then nice things happen.
For a real circular list the Node has a previous field. And the last node is linked both ways to the first node.
In that case you can walk in both directions, following next or previous.
Then when index < size / 2 one would by next forwards to the index, or else go back by previous for about (size - index) steps. In order to take the least number of steps.
it is just doing a count. You can do it in various way. I assume that the size is the size of your LinkedList. In that case your code is wrong. you can do like following
public int elementAt(int index){
if(index>size){
return -1;
}
Node n = head;
int i = 0; // zero-indexing
while(i++ != index){ // you can increment i at the end too
n=n.next;
}
return n.data;
}
FIrst code is also counting, but instead of using another variable it used the existing one
The line which you do not understand is just counting "index" positions fordward, and it is starting at head. So the method is giving you back the element "index -1" positions from the head element
Other assumption is that the head element is at 1
Hey guys So I am studying programming interview questions and I got stuck in this one.
I am trying to do this recursively but I don't know where to start.
This is the algorithm I have so far:
makeTree(head, tail){
nodeMid = list/2
root = nodeMid
root.left = makeTree(head, nodeMid)
root.right = makeTree(nodeMid, tail)
Do I have the right idea? any input is highly appreciated. Thanks!
Below are some important points:
Get the Middle of the linked list and make it root.
Recursively do same for left half and right half.
Get the middle of left half and make it left child of the root
created in step 1.
Get the middle of right half and make it right child of the
root created in step 1.
Time complexity: O(nLogn) where n is the number of nodes in Linked List.
The major problem I see immediately and forgive me if I am wrong you are not changing the location of the list for each node.
each time you recursively call
makeTree(head, tail){
nodeMid = list/2;
as far as I can see inside the loop you do not change which part of the list goes with the recursive call. ie
you have an array of ints
myints which has (0,1,2,3,4,5,6,7,8,9)
every time the recursion is called it will infinitely fill the binary tree with the number at list/2
you need to change the value of nodeMid with each call, use the head/tail variables you are sending.
you do not want to keep resetting the root node either. you should be using the "this" operator to set the value of the current node you are looking at.
start being the start of the portion of the array you are looking at
and end being the end of the portion.
the recursive calls would be so.
you also need to add in the boundaries of the recursion
Using a BST with nodes when you create a new node in the tree the left and right nodes would be set to null to start with. you need to create a new node and call the recursion.
Node makeTree(int head, int tail){
nodeMid = (head+tail)/2;
this = new Node();
if(head < nodeMid-1)
{
this.left = makeTree(head, nodeMid-1);
}
if(nodeMid < tail)
{
this.right = makeTree(nodeMid, tail);
}
this.setValue(list[nodeMid]);
return this;
}
after all the recursion is done you need to set the value of the current node and return that node for the creation.
this will recursively turn a sorted array into a binary search tree. simply put in the proper list coding for your doubly linked list.
To start the recursion
root = makeTree(0, list.length());
Logic
1) Get the Middle of the linked list and make it root.
2) Recursively do same for left half and right half.
a) Get the middle of left half and make it left child of the root
created in step 1.
b) Get the middle of right half and make it right child of the
root created in step 1.
Code
public Node bstToDll(Node root ){
if(root!=null){
Node lefthead = bstToDll(root.left); // traverse down to left
Node righthead = bstToDll(root.right); // traverse down to right
Node temp = null;
/*
* lefthead represents head of link list created in left of node
* righthead represents head of link list created in right
* travel to end of left link list and add the current node in end
*/
if(lefthead != null) {
temp = lefthead;
while(temp.next != null){
temp = temp.next;
}
temp.next = root;
}else{
lefthead = root;
}
root.prev = temp;
/*
*set the next node of current root to right head of right list
*/
if(righthead != null){
root.next = righthead;
righthead.prev = root;
}else{
righthead = root;
}
return lefthead;// return left head as the head of the list added with current node
}
return null;
}
But this is not the most optimized way since the time complexity is O(nlogn). For a better optimized solution take a look at http://www.geeksforgeeks.org/sorted-linked-list-to-balanced-bst/
I'm trying to answer the following programming question:
In the heap.java program, the insert() method inserts a new node in the heap and ensures the heap condition is preserved. Write a toss() method that places a new node in the heap array without attempting to maintain the heap condition. (Perhaps each new item can simply be placed at the end of the array.) Then write a restoreHeap() method that restores the heap condition throughout the entire heap. Using toss() repeatedly followed by a single restoreHeap() is more efficient than using insert() repeatedly when a large amount of data must be inserted at one time. See the description of heapsort for clues. To test your program, insert a few items, toss in some more, and then restore the heap.
I've written the code for the toss function which successfully inserts the node at the end and doesn't modify the heap condition. I'm having problems with the restoreHeap function though and I can't wrap my head around it. I've included the two functions below.
The full code of heap.java is here (includes toss() and restoreHeap() )
toss() - I based this off the insert function
public boolean toss(int key)
{
if(currentSize==maxSize)
return false;
Node newNode = new Node(key);
heapArray[currentSize] = newNode;
currentSize++;
return true;
} // end toss()
restoreHeap() - I based this off the trickleUp function and I'm getting a StackOverflowError.
public void restoreHeap(int index)
{
int parent = (index-1) / 2;
Node bottom = heapArray[index];
while( index > 0 &&
heapArray[parent].getKey() < bottom.getKey() )
{
heapArray[index] = heapArray[parent]; // move it down
index = parent;
parent = (parent-1) / 2;
} // end while
heapArray[index] = bottom;
while(index != 0)
{
restoreHeap(parent++);
}
} // end restoreHeap()
Any ideas? Help appreciated.
I'll give it a shot. Here is a way to do what you asked with some explanation.
Since you know that half of all nodes in a heap are leafs and a leaf, by itself, is a valid heap, you only have to run through the other half of the nodes to make sure they also are valid. If we do this from the bottom and up, we can maintain a valid heap structure "below" as we go up through the heap. This can easily be accomplished by a for loop:
public void rebuildHeap()
{
int half = heapArray.length / 2;
for(int i = half; i >= 0; i--)
restoreHeap(i);
}
How is restoreHeap implemented then?
It's supposed to check the node at index against its children to see if it needs to relocate the node. Because we make sure that the trees below the index node are heaps, we only have to move the index node to the right position. Hence we move it down in the tree.
First we need to locate the children. Since each row in the three have twice as many nodes as the row before, the children can be located like this:
private void restoreHeap(int index)
{
int leftChild = (index * 2) + 1; //+1 because arrays start at 0
int rightChild = leftChild +1;
...
Now you just have to compare the childrens value against your index nodes value. If a child have a bigger value you need to swap the index node with the child node. If both children have a bigger value, you need to swap with the child with the biggest value of the two (to maintain the heap structure after the swap). When the nodes have been swapped you need to call the method again to see if you need to move the index node further down the tree.
...
int biggest = index;
if(leftChild < currentSize && heapArray[leftChild].getKey() > heapArray[index].getKey())
biggest = leftChild; //LeftChild is bigger
if(rightChild < currentSize && heapArray[rightChild].getKey() > heapArray[biggest].getKey())
biggest = rightChild; //RightChild is bigger than both leftChild and the index node
if(biggest != index) //If a swap is needed
{
//Swap
Node swapper = heapArray[biggest];
heapArray[biggest] = heapArray[index];
heapArray[index] = swapper;
restoreHeap(biggest);
}
}
I'm trying to get my head around a recursive quicksort on a singly linked list. What is the base case, and what do I need to do when I reach it in order for the function to 'rewind' and print a sorted list? Here is some code, but I think it's desperately wrong...
public static void qSort(SLLNode first, SLLNode last)
{
SLLNode pivot = first ;
SLLNode head = pivot.succ ;
if (first!=last)
{
while (head!=null)
{
if (head.data.compareToIgnoreCase(pivot.data)<0)
{
pivot.succ = head.succ ;
head.succ = first ;
first = head ;
qSort(first, pivot) ;
qSort(head, last) ;
}
qSort(first, pivot) ;
qSort(head, last) ;
}
}
}
To rephrase my question: When I reach the base case first==last, what do I need to do? How can I make the recursion rewind and produce the sorted list?
Here's my updated code:
public static void qSort(SLLNode first, SLLNode last)
{
if (first==last)
{
return ;
}
SLLNode pivot = first ;
SLLNode head = pivot.succ ;
while (head!=null)
{
if (head.data.compareToIgnoreCase(pivot.data)<0)
{
pivot.succ = head.succ ;
head.succ = first ;
first = head ;
qSort(first, pivot) ;
qSort(head, last) ;
}
qSort(first, pivot) ;
qSort(head, last) ;
}
}
In General
For a general review on quick-sort, you should probably review the quick-sort algorithm on Wikipedia. In short, it's easier if you use a partition helper function to get your list into a state where everything less than your pivot point is to the left of it, and everything greater than the pivot point is to the right of it. You then call quick-sort recursively with both sides of the pivot.
EJP also has a very good point. I haven't seen quick-sort on a linked list.
Let's Do It Anyway
The way I see a quick-sort with a linked-list, the algorithm would be something like
def qsort(head, tail)
if head == tail
return
pivot = tail
current = head
while current != pivot
if current.value < pivot.value
move/prepend current to head of the list
else
move/append current to tail of the list
current = current.next
qsort(head, pivot-1)
qsort(pivot, tail)
It gets a little tricky because you have to keep track of pivot - 1, which isn't very natural to do with a singly linked list. Also, the above algorithm doesn't really account for elements that are equal. But the general idea is that you end up with everything less than pivot being before it, and everything greater than it being after, and then you call qsort again for both sides.
Your Code
Let's run through your program with a simple case.
A->B->C->D
F L
Is our start.
SLLNode pivot = first ;
SLLNode head = pivot.succ ;
Gives us
A->B->C->D
F H L
P
Let's say if (head.data.compareToIgnoreCase(pivot.data)<0) is true for each element given the current state of the list.
So we enter the if statement, and do
pivot.succ = head.succ ;
A->C->D B->C
F L H
P
head.succ = first ;
B->A->C->D
H F L
P
first = head ;
B->A->C->D
H P L
F
This gives us
A->B->C->D
F H L
P
B->A->C->D
H P L
F
If I have that right, then the call to
qSort(head, last);
Should probably instead be
qSort(pivot, last);
So you're not calling qSort over the whole list again. It also seems like you might want to instead keep going through your list until everything that is less than the pivot is to the left of it, before recursively calling qSort.
Investigating Quicksort for a linked list is a useful thing. In studying any algorithm it is important to understand what is absolutely required.
In the case here one discovers that random access iterators are not required. Indeed forward iterators are sufficient.
A lot of Stepanov's work with the STL was to distill such information.
Here is a simple implementation in C++. Sorry for the change of language.
I'm just swapping data instead of node pointers. Doing the latter has nothing to do with Quicksort.
And yes, I know my choice of pivot element can cause problems.
One could find the distance, d, between first and last and then pick a random number x in the range [0, d). Now advance a pointer initialized to first x times, and swap its data with the data pointed to by first.
struct Node
{
Node(int d) : data(d), next(0) {}
~Node() { delete next; }
Node* next;
int data;
};
void Quicksort(Node* first, Node* last)
{
if (first == last)
{
return;
}
Node* pivot = first;
Node* boundary = first;
for (Node* it = first->next; it != last; it = it->next)
{
// Invariant:
// The iterators in the range [first, boundary->next)
// point to nodes with data less than the pivot
// element's.
// The iterators in the range [boundary->next, it)
// point to nodes with data greater or equal to
// the pivot element's.
if (it->data < pivot->data)
{
// Swap the data to maintain the invariant
boundary = boundary->next;
std::swap(it->data, boundary->data);
}
}
// Put the pivot data in its right place
std::swap(pivot->data, boundary->data);
Quicksort(first, boundary);
Quicksort(boundary->next, last);
}
The initial call would be something like
Quicksort(head, 0);
The base case is a list with 0 or 1 elements.
You don't need to "rewind." When you make a recursive call, it goes back up the recursion stack when the call finishes.
if(first==last) return;
Conceptually, note that in a base case where first==last, you have a linked list of one element and thus it is already sorted.
I think your algorithm may be slightly off?. You want a loop that moves everything less than the pivot to the first half, and everything greater to the second half. Then (after the loop is done!) you can recursively sort the halves. I see that yours is doing it a little differently, but I'm not convinced it's right....
Finally, as stated by others, sorting a linked list is not a very useful task. You wouldn't use a bike to tow a trailer....