How does recursion of Quick sort work? - algorithm

The functions below are an implementation of Quick sort. Here we take the last element as a pivot.
I understood the partition function(where the pivot comes to its sorted position) but I can't understand the recursive function qs. The function qs calls itself recursively to solve the left side by qs(a,start,pi-1) and the right of the partition by qs(a,pi+1,end).
Does it the solve the left and then the (left of the left) then (the left of(the left of the left), etc, and then left, left...right, etc. Or does it alternate by solving the left side and then right side.
PS: I want to know whats happening inside the computer, the mechanism of this recursion of quick sort. The program is working but I want to know how it works.
int partition(int *a, int start, int end)
{
int pivot=a[end];
int pi=start;
for(int i=start; i<end; i++)
{
if(a[i]<=pivot)
{
swap(a[i],a[pi]);
pi++;
}
}
swap(a[pi], a[end]);
return pi;
}
void qs(int*a, int start, int end)
{
if(start<end)
{
int pi=partition(a,start,end);
qs(a,start,pi-1);
qs(a,pi+1,end);
}
}

Example of the order of operations for Lomuto partition scheme, where pivot = array[high].
quicksort(array, low, pivot-1), quicksort(array, pivot+1, high).
A vertical bar used to show left sub-array, pivot, right sub-array.
11 13 14 12 10 8 9 5 6 4 2 0 1 3 7
5 6 4 2 0 1 3 11 13 14 12 10 8 9 7
5 6 4 2 0 1 3| 7|13 14 12 10 8 9 11
2 0 1 5 6 4 3
2 0 1| 3| 6 4 5
0 2 1
0| 1| 2
4 6 5
4| 5| 6
10 8 9 13 14 12 11
10 8 9|11|14 12 13
8 10 9
8| 9|10
12 14 13
12|13|14
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14

The best way for understanding the order in which things are happening that I can suggest you, is by printing some debugging info in your qs method. To achieve that, I would add an additional argument by ref, in which I would count the number of times the qs function is called, and print that info next to the bounds of the partition being solved. e.g.
void qs(int*a, int start, int end, int &stepCount)
{
if(start<end)
{
int currentStep = stepCount++;
cout << "Solving step " << currentStep << " partition from " << start << " to " << end << endl;
int pi=partition(a,start,end);
qs(a,start,pi-1,stepCount);
qs(a,pi+1,end,stepCount);
cout << "Finished solving step " << currentStep << endl;
}
}
Don't understand your PS question. It's very broad. You mean specifically in the partitioning? In how recursion is handled? How the bits move around in memory?

Related

How to make a N×N matrix each of i-th row and i-th column having all the elements 1 to 2N-1?

This question was asked as a puzzle in one Book of Puzzles by RS AGGARWAL, which stated the problem as to build an order N matrix where each i'th row and i'th column combined have all the elements from 1 to 2N-1.
For instance, for N=2
[3,2]
[1,3]
I want to know when is an answer possible for it for which values of N it is possible to make a matrix and how to make it? and write code for it
this has simple solution for square matrices where n is power of 2 so n=1,2,4,8,16,... do not ask me why there surely is some math proof for it ...
The algorithm to create such matrix is easy:
clear matrix (with 0)
loop i through all values i=1,2,3...2n-1
for each i find all locations where i matrix is not yet filled (0) and there is not i present in row and column
fill the position with i and repeat until no such location found.
In C++ something like this:
//---------------------------------------------------------------------------
const int n=8;
int m[n][n];
//---------------------------------------------------------------------------
// compute histogram u[n+n] of values per ith row,col of m[n][n]
void hist_rst(int *u ) { for (int j=0;j<n+n;j++) u[j]=0; }
void hist_row(int *u,int m[n][n],int i) { for (int j=0;j<n;j++) u[m[j][i]]=1; }
void hist_col(int *u,int m[n][n],int i) { for (int j=0;j<n;j++) u[m[i][j]]=1; }
//---------------------------------------------------------------------------
void matrix_init(int m[n][n])
{
int i,x,y,h[n][n+n];
// clear matrix (unused cells)
for (x=0;x<n;x++)
for (y=0;y<n;y++)
m[x][y]=0;
// clear histograms
for (i=0;i<n;i++) hist_rst(h[i]);
// try to fill values 1..2n-1
for (i=1;i<n+n;i++)
{
// find free position
for (x=0;x<n;x++) if (!h[x][i])
for (y=0;y<n;y++) if (!h[y][i])
if (!m[x][y])
{
// set cell
m[x][y]=i;
h[x][i]=1;
h[y][i]=1;
break;
}
}
}
//---------------------------------------------------------------------------
here few outputs:
1
1 3
2 1
1 5 6 7
2 1 7 6
3 4 1 5
4 3 2 1
1 9 10 11 12 13 14 15
2 1 11 10 13 12 15 14
3 4 1 9 14 15 12 13
4 3 2 1 15 14 13 12
5 6 7 8 1 9 10 11
6 5 8 7 2 1 11 10
7 8 5 6 3 4 1 9
8 7 6 5 4 3 2 1
for non power of 2 matrices you could use backtracking but take in mind even 4x4 matrix will have many iterations to check ... so some heuristics would need to be in place to make it possible in finite time... as brute force is (n+n)^(n*n) so for n=4 there are 281474976710656 combinations to check ...
[edit1] genere&test solution for even n
//---------------------------------------------------------------------------
const int n=6;
int m[n][n];
//---------------------------------------------------------------------------
// compute histogram u[n+n] of values per ith row,col of m[n][n]
void hist_rst(int *u ) { for (int j=0;j<n+n;j++) u[j]=0; }
void hist_row(int *u,int m[n][n],int i) { for (int j=0;j<n;j++) u[m[j][i]]=1; }
void hist_col(int *u,int m[n][n],int i) { for (int j=0;j<n;j++) u[m[i][j]]=1; }
//---------------------------------------------------------------------------
void matrix_init2(int m[n][n]) // brute force
{
int x,y,a,ax[(n*n)>>1],ay[(n*n)>>1],an,u[n+n];
// clear matrix (unused cells)
for (x=0;x<n;x++)
for (y=0;y<n;y++)
m[x][y]=0;
// main diagonal 1,1,1,1...
for (x=0;x<n;x++) m[x][x]=1;
// 1st row 1,2,3...n
for (x=1;x<n;x++) m[x][0]=x+1;
// cells for brute force
for (an=0,x=0;x<n;x++)
for (y=0;y<x;y++)
if (!m[x][y])
{
ax[an]=x;
ay[an]=y;
an++;
m[x][y]=2;
}
// brute force attack values 2,3,4,5,...,n-1
for (;;)
{
// increment solution
for (a=0;a<an;a++)
{
x=ax[a];
y=ay[a];
m[x][y]++;
if (m[x][y]<=n) break;
m[x][y]=2;
}
if (a>=an) break; // no solution
// test
for (x=0;x<n;x++)
{
hist_rst(u);
hist_col(u,m,x);
hist_row(u,m,x);
for (y=1;y<=n;y++) if (!u[y]) { y=0; x=n; break; }
}
if (y) break; // solution found
}
// mirror other triangle
for (x=0;x<n;x++)
for (y=0;y<x;y++)
m[y][x]=m[x][y]+n-1;
}
//---------------------------------------------------------------------------
however its slow so do not try to go with n>6 without more optimizations/better heuristics... for now it is using triangle+mirror and diagonal + first row hard-coded heuristics.
maybe somehow exploit the fact that each iterated value will be placed n/2 times could speed this up more but too lazy to implement it ...
Here output for n=6:
[ 52.609 ms]
1 2 3 4 5 6
7 1 6 5 3 4
8 11 1 2 4 5
9 10 7 1 6 3
10 8 9 11 1 2
11 9 10 8 7 1
iterating through 5^10 cases ...
As requested by Spektre, here is the 6x6 matrix.
I an interesting property that may be used as heuristic. We need only to solve a triangular matrix because the other half can be easily deduced. We fill the upper (or lower) half of the matrix by values from 1 to n only. We can then complete the matrix by using the property that a[j][i] = 2n + 1 - a[i][j].
Another property I found is that there is a trivial way to place 1, 2 and N in the matrix. The values 1 are all on the diagonal, the values 2 and N are next to the diagonal at a step 2.
Finally, another thing I found is that matrix with odd N have no solutions. It is because the value in a[i][j] belongs to row and column i and row and column j. We thus need an even number of row and columns to store all values.
Here is the 6x6 matrix I found manually.
1 2 3 4 5 6
11 1 6 5 3 4
10 7 1 2 4 5
9 8 11 1 6 3
8 10 9 7 1 2
7 9 8 10 11 1
As we can see 2 + 11 = 6 + 7 = 3 + 10 = 13 = 2*6+1.
Here is a 4x4 matrix
1 2 3 4
7 1 4 3
6 5 1 2
5 6 7 1
Here again 2 + 7 = 4 + 5 = 3 + 6 = 9 = 2*4+1
It is possible to have other permutations of values >N, but with the 2N+1 property we can trivially deduce one triangular matrix from the other.
EDIT
Here is a solution for power two sized matrix. The matrix of size 2048x2048 is generated in 57ms (without printing).
#include <stdio.h>
int **newMatrix(int n) {
int **m = calloc(n, sizeof(int*));
m[0] = calloc(n*n, sizeof(int));
for (int i = 1; i < n; i++)
m[i] = m[0]+i*n;
return m;
}
void printMatrix(int **m, int n) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++)
printf("%3d ", m[i][j]);
printf("\n");
}
}
void fillPowerTwoMatrix(int **m, int n) {
// return if n is not power two
if (n < 0 || n&(n-1) != 0)
return;
for (int i = 0; i < n; i++)
m[0][i] = i+1;
for (int w = 1; w < n; w *= 2)
for (int k = 0; k < n; k += 2*w)
for (int i = 0; i < w; i++)
for (int j = k; j < k+w; j++) {
m[i+w][j] = m[i][j+w];
m[i+w][j+w] = m[i][j];
}
int k = 2*n+1;
for (int i = 1; i < n; i++)
for (int j = 0; j < i; j++)
m[i][j] = k - m[j][i];
}
int main() {
int n = 16;
int **m = newMatrix(n);
fillPowerTwoMatrix(m, n);
printMatrix(m, n);
return 0;
}
Here is the matrix 16x16. As can be seen there is a symmetry that is exploited to efficiently generate the matrix.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
31 1 4 3 6 5 8 7 10 9 12 11 14 13 16 15
30 29 1 2 7 8 5 6 11 12 9 10 15 16 13 14
29 30 31 1 8 7 6 5 12 11 10 9 16 15 14 13
28 27 26 25 1 2 3 4 13 14 15 16 9 10 11 12
27 28 25 26 31 1 4 3 14 13 16 15 10 9 12 11
26 25 28 27 30 29 1 2 15 16 13 14 11 12 9 10
25 26 27 28 29 30 31 1 16 15 14 13 12 11 10 9
24 23 22 21 20 19 18 17 1 2 3 4 5 6 7 8
23 24 21 22 19 20 17 18 31 1 4 3 6 5 8 7
22 21 24 23 18 17 20 19 30 29 1 2 7 8 5 6
21 22 23 24 17 18 19 20 29 30 31 1 8 7 6 5
20 19 18 17 24 23 22 21 28 27 26 25 1 2 3 4
19 20 17 18 23 24 21 22 27 28 25 26 31 1 4 3
18 17 20 19 22 21 24 23 26 25 28 27 30 29 1 2
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 1

How to sort a vector of structure belonging to same category/set in c++

While solving a competitive coding problem I got stuck with the the following sorting scenario.
I have a vector of following structure
struct Data{
int p;
int val;
int ll;
};
Defined as :
vector<Data> a(N);
Now p field in the structure tells the set number to which val belong.
e.g if values are 1 2 3 4 5 6 7 8 9
(1,4,7) belong to group/set 3 i.e p is 3 , (2,5,8) belong to group/set 4 i.e p is 4 and (3,6,9) belong to group/set 5 i.e p is 5
i have p and val field in structure as
p as 3 4 5 3 4 5 3 4 5
val as 1 2 3 4 5 6 7 8 9
Now the problem is I have to sort the vector set wise in descending order
i.e 7 8 9 4 5 6 1 2 3
here 1 4 and 7 belong to set 3 so they are sorted in their respective places.
I tried with the selection sort as below which worked fine but it gave Time limit exceeded because of O(N^2) complexity.
for(int i=0;i<N;i++)
{
int mi=i;
Data max=a[i];
for(int j=i+1;j<N;j++)
{
if((a[i].p==a[j].p)&&(a[j].val>max.val))
{
max=a[j];
mi=j;
}
}
a[mi]=a[i];
a[i]=max;
}
Please help me find the best (time complexity) way to sort this scenario (if possible using STL sort).
Thanks in advance.
Modifying http://www.cplusplus.com/reference/algorithm/sort/, the key bit is:
#include <algorithm>
...
bool mycomparison (Data i, Data j) {
if (i.p != j.p)
return j.p < i.p;
else
return j.val < i.val;
}
...
// Sort vector a
a.std::sort( a.begin(), a.end(), mycomparison );
...
Note that reversing i and j in the return lines causes things to be in descending order.

Quicksort algorithm with element in the middle as pivot

I had to do this little task where I had to sort an array 'by hand' like quicksort does. There is one specific point (the recursive one) where I am not sure if my solution is
right. Would be nice if anyone could look through this!
Initial sequence: 7 4 6 8 9 1 3 2
Solution (i = left index, x = pivot, j = right index):
[Pivot-index = (i+j)/2]
Sort for positions 0 to 7:
i x j
7 4 6 8 9 1 3 2
(swap 8 and 2)
i j
7 4 6 8 9 1 3 2
i j
7 4 6 2 9 1 3 8
(swap 9 and 3)
i
j
7 4 6 2 3 1 9 8
Sort for positions 0 to 5:
i x j
7 4 6 2 3 1 9 8
(swap 7 and 1)
i j
1 4 6 2 3 7 9 8
(swap 6 and 3)
i
j
1 4 3 2 6 7 9 8
Sort for positions 0 to 3:
i x j
1 4 3 2 6 7 9 8
(swap 4 and 2)
i
j
1 2 3 4 6 7 9 8
Sort for positions 0 to 2:
i x j
1 2 3 4 6 7 9 8
(swap 2 'and' 2)
j i
1 2 3 4 6 7 9 8
Sort for positions 6 to 7 (from first split - not sure here!)
i j
x
1 2 3 4 6 7 9 8
(swap 9 and 8)
j i
1 2 3 4 6 7 8 9
Used code:
public class QuickSort {
public static void sort (int[] a) { // public method
quicksort(a, 0, a.length-1); // starts private method
}
private static void quicksort (int[] a, int left, int right) {
int tmp; // temporary param
int i = left; // left index
int j = right; // right index
int middle = (left + right) / 2; // middle position
int x = a[middle]; // pivot element
do {
while (a[i] < x) i++; // x works as break
while (a[j] > x) j--; // x works as break
if (i <= j) {
tmp = a[i]; // temporary storage
a[i] = a[j]; // a[i] and
a[j] = tmp; // a[j] get swapped
i++;
j--;
}
} while (i <= j);
// all elements on the left side of the array are smaller than
// all elements in the right side of the array
if (left < j) quicksort(a, left, j); // sort left side
if (i < right) quicksort(a, i, right); // sort right side
}
}

Number Pyramid Algorithm

I was searching around the internet trying to find the algorithm of the following pyramid:
1
2 3 2
3 4 5 4 3
4 5 6 7 6 5 4
5 6 7 8 9 8 7 6 5
6 7 8 9 10 11 10 9 8 7 6
7 8 9 10 11 12 13 12 11 10 9 8 7
8 9 10 11 12 13 14 15 14 13 12 11 10 9 8
9 10 11 12 13 14 15 16 17 16 15 14 13 12 11 10 9
10 11 12 13 14 15 16 17 18 19 18 17 16 15 14 13 12 11 10
I wasn't able to find the algorithm, my question is: Does anyone know the algorithm and/or name for this type of pyramid?
Any help is greatly appreciated. I'm sorry if anything in the post is wrong in some way, new posting here.
Here's one solution .... but you should not be lazy, this isn't so hard :)
It is written in Java ....
What you see in the System.out.print() is "Ternary operator". You need to check if it is two digit number, to reduce the number of empty spaces.
public static void Pyramid(int rows) {
int r = 1; // r is current row
int emptySpaces = rows;
while(r <= rows) {
//print the empty spaces (3 empty spaces in one iteration)
for(int i = 1; i < emptySpaces; i++) {
System.out.print(" ");
}
//print the numbers to the middle including the middle number
for(int i = 0; i < r; i++) {
System.out.print((r+i)/10 == 0 ? (r+i + " ") : (r+i + " "));
}
//print the numbers from the middle to the end
for(int i = r-2; i >= 0; i--) {
System.out.print((r+i)/10 == 0 ? (r+i + " ") : (r+i + " "));
}
//print new line, reduce empty spaces
System.out.println("");
emptySpaces--;
r++;
}
}

StackOverflow after 27 runs

When running my Sudoku Generator, after 27 times getting stack overflow.
void start(int todel){
int number;
for (int x=0; x<9; x++) {
for (int y=0; y<9; y++) {
number = GenN(x, y);
osudoku[x][y]=number;
}
}
replace(todel);
output();
}
int GenZ(int x, int y){
int number;
bool duplication = true;
Randomize();
number = Random(9)+1;
duplication = check(number,x,y);
if (duplication==true){
return GenZ(x,y);
}
else if (duplication==false) {
return number;
}
}
I think its something with this code.
It generates things like:
758 431 629
913 267 485
642 985 317
Stack Overflow
So I get 1/3 Sudoku.
You need to add backtracking to your solution.
Consider this scenario: (which may occur at some point in your algorithm)
1 2 3 | 4 5 6 | 7 8 9
4 5 6 | 1 2 3 | ? _ _
...
Your program will just keep trying to find a value that fits at the ?, but no such value exists.
Instead, your program needs to see that no values fits, and try a different value for 3, which also won't work, then 2, then 1 in which case it should eventually put 7, 8 and 9 in the second block like:
1 2 3 | 4 5 6 | 7 8 9
4 5 6 | 7 8 9 | ? _ _
...
in which case it can continue successfully.
And this:
zahl = Random(9)+1;
won't really work as you may keep on getting values that don't fit (as in the above example). You won't know when to backtrack. It's better to loop through all 9 values. After you've looped through all 9 values, you'll know that no value fits and you'll know you must backtrack.
if duplication==true in GenZ it will call it again with the same x,y , which will again produce duplication==true? especially since I cant see you modifying "number" , so it might be at it's initialized value like 0.
if (duplication==true){
return GenZ(x,y);
}
I am not sure if that is a viable way to create a sudoku, brute-forcing might take a while no matter how you implement it, but you can probably get rid off the stackoverflow error by not using recursion and having a loop.
while (duplication){

Resources