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.
Related
Write a recursive function to find the smallest element in a vector.
We can not use loops but can use if statements.
Using RECURSION is a must.
I Could Not think of any solution, the main problem was if I define a function then I have to give it some value and if I do so then whenever recursion occur it will again reset the value of that variable.
function miminimumis=minimumval(k)
aa=k(1);
k=k(k<k(1));
if length(k)==0
miminimumis=aa;
else
% this line gives the recursion
miminimumis=minimumval(k);
end
end
here we create a new array which consists of elements only smaller than the first element. if this array is empty then it means that first element is min, if not we do the same for the new array unless we reach an empty array. the recursion is provided by using the same function in the definition of the function.
Solutions which in the worst case reduce the problem size by 1 will cause the recursive stack to have O(length(array)) growth. An example of this would be when you filter the array to yield values less than the first element when the array is in descending order. This will inevitably lead to stack overflow for sufficiently large arrays. To avoid this, you want to use a recursion which splits the problem of size n into two subproblems of size n/2, yielding O(log(length(array))).
I'm not a Matlab user/programmer, so I'll express the algorithm in pseudo-code. The following assumes that arrays are 1-based and that there is a built-in function min(a,b) which yields the minimum of two scalars, a and b. (If not, it's easy to replace min() with if/else logic.)
function min_element(ary) {
if length(ary) == 1 {
return ary[1]
}
split ary into first_half, second_half which differ in length by no more than 1
return min( min_element(first_half), min_element(second_half) )
}
This could alternatively be written using two additional arguments for the lo_index and hi_index to search between. Calculate the midpoint as the integer average of the low and high indices, and make the two recursive calls min_element(ary, lo_index, mid) and min_element(ary, mid+1, hi_index). The base condition is when lo_index == hi_index, in which case you return that element. This should be faster, since it uses simple integer arithmetic and avoids creating sub-arrays for the subproblems. It has the trade-off of being slightly less friendly to the end user, who has to start the process by calling min_element(ary, 1, length(ary)).
If the stack limit is 500, you'll be limited to arrays of length < 500 using linear stack growth algorithms. With the divide-and-conquer algorithm described above, you won't get stack overflow unless you have an array of length ~2500, much bigger than any array you could actually create.
For example,
A=[a,b,c,d]
B=[1,2,3,4]
my question is: how to generate all possible ways to merge A and B, such that in the new list we can have a appears before b, b appears before c,etc., and 1 appears before 2, 2 appears before 3,etc.?
I can think of one implementation:
We choose 4 slots from 8,then for each possible selection, there are 2 possible ways--A first or B first.
I wonder is there a better way to do this?
EDIT:
I've just learned a more intuitive way--use recursion.
For each spot, there are two possible cases, either taken from A or taken from B; keep recursing until A or B is empty, and concatenate the remaining.
If the relative order is different than what constitutes a sorted list (I assume it is, because otherwise it would not be a problem), then you need to formalize the initial order. Multiple ways to do that. the easiest being remembering the index of each element in each list. Example: valid position for a is 1 in the first array [...]
Then you could just go ahead and join the lists, then generate all the permutations of elements. Any valid permutation is one that keeps the order relationship of the new indexes with the order you have stored
Example of one valid permutation array
a12b3cd4
You can know and check that this is valid permutation because the index of element 'a' is smaller than the index of b, and so on. and you know the indexes must be smaller because this is what you have formulated at the first step
Similarly an invalid permutation array is
ba314cd2
same way of checking
I would like to know what the meaning of
col2=b1(1:end,lead);
is in MATLAB?
This is very basic stuff. We are led to assume that b1 is a 2-dimensional array. The contents of an array are indexed using brackets, so b1(1,1) will return the top left element of array b1. The first index in your example, 1:end is selecting every element in the first dimension (matlab indexes rows first, then columns). The second index, lead in your example, selects a particular column. We assume that lead has been allocated previously somewhere in the code.
Thence, b1(1:end,lead) returns to col2 a 1-dimensional array containing a subarray of b1. This could be accomplished more elegantly using col2=b1(:,lead);.
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).
I am creating a 1 dimensional row array via a calculation
Lt_p= totalLn_p - ln_p
Which returns
Lt_p =
4.4408 4.3482 3.9962 3.4517 2.9009 2.3447 2.0648 1.7837 1.5015 1.0676 0.8665 0.6739 0.4822 0.2818 0.0820 0
Due to the nature of the calculation the last element will always be 0, I then need to use Lt_p in another calculation (by dividing it by another array).
However the other array will always have one less element than Lt_p, so obviously can not be divided.
The 0 element is not needed though so how do I resize Lt_p to not include the last element?
Are you sure that you will not need it? Otherwise a zero element is a good way determining the end of the data. Either you do as Divakar in the comment, otherwise you define an array ind = Lt_p(1:end-1). And always calls Lt_p(ind). The latter is of course a waste of resources and computation time if you is completely sure you will only need elements Lt_p(1:end-1).