Quick sort with middle element as pivot - quicksort

My understanding of quick sort is
Choose a pivot element (in this case I am choosing middle element as
pivot)
Initialize left and right pointers at extremes.
Find the first element to the left of the pivot which is greater than pivot.
Similarly find the first element to the right of the pivot which is smaller than pivot
Swap elements found in 3 and 4.
Repeat 3,4,5 unless left >= right.
Repeat the whole thing for left and right subarray as pivot is now placed at its place.
I am sure I am missing something here and being very stupid. But above does not seems to be working fot this array:
8,7,1,2,6,9,10,2,11 pivot: 6 left pointer at 8, right pointer at 11
2,7,1,2,6,9,10,8,11 swapped 2,8 left pointer at 7, right pointer at 10
Now what ? There is no element smaller than 6 on it's right side.
How 7 is going to go to the right of 6 ?

There is no upfront division between the left and the right side. In particular, 6 is not the division. Instead, the division is the result of moving the left and right pointer closer to each other until they meet. The result might be that one side is considerably smaller than the other.
Your description of the algorithm is fine. Nowhere does it say you have to stop at the middle element. Just continue to execute it as given.
BTW.: The pivot element might be moved during the sorting. Just continue to compare against 6, even if it has been moved.
Update:
There are indeed a few minor problems in your description of the algorithm. One is that either step 3 or step 4 need to include elements that are equal to the pivot. Let's rewrite it like this:
My understanding of quick sort is
Choose a pivot value (in this case, choose the value of the middle element)
Initialize left and right pointers at extremes.
Starting at the left pointer and moving to the right, find the first element which is greater than or equal to the pivot value.
Similarly, starting at the right pointer and moving to the left, find the first element, which is
smaller than pivot value
Swap elements found in 3 and 4.
Repeat 3,4,5 until left pointer is greater or equal to right pointer.
Repeat the whole thing for the two subarrays to the left and the right of the left pointer.
pivot value: 6, left pointer at 8, right pointer at 11
8,7,1,2,6,9,10,2,11 left pointer stays at 8, right pointer moves to 2
2,7,1,2,6,9,10,8,11 swapped 2 and 8, left pointer moves to 7, right pointer moves to 2
2,2,1,7,6,9,10,8,11 swapped 2 and 7, left pointer moves to 7, right pointer moves to 1
pointers have now met / crossed, subdivide between 1 and 7 and continue with two subarrays

Quick Sort Given an array of n elements (e.g., integers):
-If array only contains one element, return
-Else
pick one element to use as pivot.
Partition elements into two sub-arrays:
Elements less than or equal to pivot
Elements greater than pivot
Quicksort two sub-arrays
Return results
Let i and j are the left and right pivots, then code for one array will look like this:
1) While data[i] <= data[pivot]
++i
2) While data[j] > data[pivot]
--j
3) If i < j
swap data[i] and data[j]
4) While j > i, go to 1.
5) Swap data[j] and data[pivot_index]
Position of index j is where array is to-be partitioned in two half and then same steps are applied to them recursively.
At last you gets an sorted array.

Your confusion is because you think the partition should be the landmark separating the two. This is not true (for middle element pivot)!
Lomuto's partition (pivot = most right partition).
Left: (lo ... p-1) (note the pivot is not included)
Right: (p+1 ... high)
middle element as the pivot. The segment is partitioned:
Left: (lo ... p)
Right: (p+1 ... high)
[https://en.wikipedia.org/wiki/Quicksort]

Related

Remove the cycles

I need to get rid of loops in my Matlab code. During this procedure, i encountered the following problem. Here is the part of the code
Nx=11; Ny=11;
A=rand(Ny,Nx);
A1=A;
for j=2:Ny-1
for i=2:Nx-1
A(j,i)=A(j,i-1);
end;
end;
A1(2:Ny-1,2:Nx-1)=A1(2:Ny-1,1:Nx-2);
A2=A-A1;
I get that A is not equal to A1. The situation is the same with the j-1 index on the right side. However, if we take the index i + 1 or j + 1, then everything works fine.
The problem is relatively simple: you are shifting the columns of A1 to the right all at once (copying over column 1 into 2 and discarding column Nx-1 in the process), whereas your for loop shifts the columns of A to the right one at a time, left to right. This means that first you overwrite column 2 with the contents of column 1, then 3 with 2, and so on, so that you finally end up with Nx-1 copies of the first column. (When I speak of copying/moving/discarding columns, I mean their values from row 2 to row Ny-1.)
As you have noticed, if you modify your loop to shift columns to the left, i.e.
for j=2:Ny-1
for i=2:Nx-1
A(j,i)=A(j,i+1);
%...
then this issue does not happen, since you have a chance to read the original contents of any given column and save them elsewhere before overwriting them with new values.
All of the above results apply when the for loop iterates over columns from left to right. If you reverse the direction of iteration, i.e.
%...
for i=Nx-1:-1:2
A(j,i)=%...
then right-shifting columns works as intended, while shifting them to the left produces bogus results.

How to "absolute-ly" take from a number? (How to offset a number?)

Essentially what I need to do is a - b, but I don't know what either will be and if a is positive then how can I take b from a in a "absolute" way?
What I mean is for example A = 10 and B = 5. Answer is obviously 5. If A was now -10, the answer is now -5. The answer leans towards 0 no matter what the numbers are. I heavily want to avoid using an if statement if I can.
My original idea was a - (b * (b / abs(b))). But b can be 0, and then div by 0 error occurs.
EDIT: A better way of saying it is I want to offset the result by an amount instead of math.
So do I understand correctly that whatever the value of A, you want it to bias towards zero (based on the initial value of A) by the value of B?
So given:
A=10 and B=5, the result will be 5.
A=-10 and B=5, the result will be -5.
A=-5 and B=-10, the result will be 5 (because it is offset by 10, towards zero from a starting point of -5).
Effectively the sign of B is immaterial because it specifies an offset towards zero in all cases.
What of the case where A=0 and B is non-zero? Is the result supposed to be undefined (because the appropriate direction of offset cannot be inferred), or is it supposed to be zero?
The formula for the latter case would be (ABS(A) - ABS(B)) * SIGN(A)) (assuming that the sign function returns 0 when A is zero).

K&R quicksort code

I examined the quick sort code in K&R book and after 2 hours I still fail to understand what the first swap (swap(a, left, (left+right)/2);) achieves. I tried removing it and the sorting still works.
can someone explain? is it a performance issue? and if so, why? this action seems random to me (that is that on some group of numbers it will improve performance and on some not).
thank you.
void qsort(int a[], int left, int right)
{
int i, last;
if (left >= right)
return;
swap(a, left, (left+right)/2);
last = left;
for (i = left + 1; i <= right; i++)
if(a[i] < a[left])
swap(a, ++last, i);
swap(a, left, last);
qsort(a, left, last-1);
qsort(a, last+1, right);
}
It puts the pivot element onto the very first position of the sub-array.
Then it continues to partition the sub-array around the pivot, so that after the partitioning is done, the sub-array looks like this: [pivot, [elements < pivot], [elements >= pivot]].
After that, the pivot is simply put into proper space, so the sub-array looks like this: [[elements < pivot], pivot, [elements >= pivot]].
And after that, the recursive call is made on two sub-sub-arrays.
Quick sort will always work, regardless of which element is chosen as a pivot. The catch is, if you choose the median element, then the time complexity will be linearithmic (O(nlogn)). However, if you choose, for example, the biggest element as a pivot, then the performance will degrade to quadratic (O(n^2)).
So, in essence, pivot selection is the key to performance of Quick-Sort, but it will work (and when I say work, I mean you'll get a sorted array, eventually).
K&R implementation chooses the middle index (i.e. (left+right)/2) for the pivot. Removing this line uses the leftmost element for the pivot instead. The implementation still works, but the performance degrades when the array is already sorted.
Wikipedia article explains this:
In the very early versions of quicksort, the leftmost element of the partition would often be chosen as the pivot element. Unfortunately, this causes worst-case behavior on already sorted arrays, which is a rather common use-case. The problem was easily solved by choosing either a random index for the pivot, choosing the middle index of the partition or (especially for longer partitions) choosing the median of the first, middle and last element of the partition for the pivot (as recommended by Sedgewick).

Insertion Sort Algorithm In place and loop variant

Part 1
I know that QuickSort can be used 'in place' but could someone explain to me how Insertion sort Algorithm does this using 'in place'.
From my understanding:
Insertion Sort starts at the first value and compares it to the next value, if that value is less than our value they switch positions. We continue this recursively. (Short explanation)
So would you say that this is 'in place' because we don't create a new array to do this, but just compare two elements in an array?
If my understanding was wrong could someone please explain the
algorithm for insertion sort in place.
Part 2
Also how would I use insertion sort to illustrate the idea of a loop invariant?
I know that a loop invariant is a condition that is immediately true before and after each iteration of a loop but I'm not sure how this would relate to an insertion sort.
Like Thorsten mentioned in the comments section, you have described bubble sort. Modified from Wikipedia, pseudocode for bubble sort is as follows:
procedure bubbleSort( A : list of sortable items )
n = length(A)
for i = 1 to n inclusive do // Outer Loop
for j = 1 to n-1-i inclusive do
/* if this pair is out of order */
if A[j] > A[j+1] then
swap(A[j], A[j+1])
end if
end for
end for
end procedure
The loop invariant in bubble sort (for the outer loop) would be that, after each iteration of the loop, the entire array until the current value of i would be sorted. This is because, each time one reaches the outer loop, it will be after going through all iterations of the inner loop (from i to n-1), finding the minimum element there and swapping that element with the ith one.
Bubble sort is, indeed, in place, since all the sorting happens within the original array itself, and does not require a separate external array.
Edit- now onto insertion sort:
Pseudo code is as follows (all hail Wikipedia):
for i = 1 to length(A) - 1
x = A[i]
j = i
while j > 0 and A[j-1] > x
A[j] = A[j-1]
j = j - 1
end while
A[j] = x[3]
end for
Here, at each step, what happens is that for each element, you select the appropriate location at which to insert it into the array, i.e., you insert it just after the first element that is smaller than it in the array. In a little more detail, what the inner loop does is that, it keeps shifting elements to the right till it encounter an element smaller than the element in consideration, at which point you insert the element just after the smaller element. What this will mean is that every element until the aforementioned element is sorted. the outer loop ensures that this is done for all elements within the array, which means that by the time the outer loop completes, the array is sorted.
The loop invariant for the outer loop is, like before, that after the ith iteration, all elements till the current i will be sorted. Just before the ith interation, however, all elements till i-1 will be sorted.
The insertion sort algorithm does not require an external array for sorting. More specifically, all operations are done on the array itself (except for the one variable we need to store the element that we are currently trying to insert into its appropriate location), and no external arrays are used- there is no copying from this array to another one, for example. So, the space complexity required by the algorithm (excluding, of course, the space the array itself occupies) will be O(1), as opposed to dependent on the size of the array, and the sort is in-place, much like bubble sort.

Turing Machine - Generate number sequences

http://morphett.info/turing/turing.html
How would I create a looping number sequence such as:
01011011101111011111...
So basically adding a zero, then adding 1, then a zero, then 1 on top of the previous number of ones.
Write 01 on the tape. Move one space to the right. If you're looking at a zero, scan back to the left until you see a zero. Move one space to the right. If you're looking at a one, replace it with a two and move to the right until you see a zero; then keep moving right until you another zero. Replace this zero with one. Then, move back until you see a two. Replace the two with a one. Move one to the right; if you're looking at a one, repeat the process of replacing with two and back again. Eventually, you'll exhaust the previous supply of 1s, so you're looking at a zero when you move one to the right. In that case, move right to the next zero, and replace it with one. Loop on this entire process (minus the "write 01 part) to get longer strings of ones.
The intuition behind this is straightforward. If you move to the right and see a zero, move two zeroes to the left, copy all the one's between the last and second-to-last zero after the zero you found, and then add one more one. The two is used as a way to keep track of your position in the string of ones you're copying. The basic idea is sound, but you should try to write out states and transitions for this to make it rigorous.
Example:
>
^
>0
^
>01
^
>010
^
>010
^
>010
^
>020
^
>0200
^
>0201
^
>0201
^
>0101
^
>0101
^
>01010
^
>010110
^