Trying to implement insertion sort inc - c

I'm trying to implement insertion sort but I don't seem to be able to correctly swap the values into their right place.
Here's what I have so far:
void insertion(int ar[], int n) {
for (int i = 1; i < n; i++) {
int temp = ar[i];
int j = i;
while (ar[j - 1] > ar[i] && (j - 1) >= 0) {
ar[i] = ar[j - 1];
ar[j - 1] = temp;
}
}
}

This source summarizes the steps of the insertion-sort algorithm as follows:
Algorithm : To sort an array of size n in ascending order:
1: Iterate from arr[1] to arr[n] over the array.
2: Compare the current element (key) to its predecessor.
3: If the key element is smaller than its predecessor, compare it to the elements before. Move the greater elements one position up to make space for the swapped element.
The first step you got it right:
void insertion(int ar[], int n) {
for (int i = 1; i < n; i++) {
// ..
}
}
however you completely miss the second step, and your while loop:
int j = i;
while (ar[j - 1] > ar[i] && (j - 1) >= 0) {
ar[i] = ar[j - 1];
ar[j - 1] = temp;
}
has some issues, namely 1) it is stuck in an infinite loop because the variable j is never decremented; 2) its conditionals should be swapped, so instead of ar[j - 1] > ar[i] && (j - 1) >= 0 it should be (j - 1) >= 0 && ar[j - 1] > ar[i]. Otherwise, you would be accessing the position -1 of the array ar
SPOILER
A possible implementation of the insertion sort could look like:
void insertionSort(int arr[], int n)
{
int j = 0;
for (int i = 1; i < n; i++) {
int key = arr[i];
for (j = i - 1; j >= 0 && arr[j] > key;) {
arr[j + 1] = arr[j];
j = j - 1;
}
arr[j + 1] = key;
}
}
Lets us see how it works with the input [8, 6, 4, 20, 10] (the key is represented by '()')
i = 1, j = 0, key = 6; In the inner loop [<8>, (6), 4, 20, 10]; 6 < 8 true arr[j + 1] = arr[j]; which leads to [<8>, (8), 4, 20, 10]. j = -1, the inner loop stops and arr[j + 1] = key; turns the array into [(6), 8, 4, 20, 10].
At this point, we know that the smallest element is in the first position. Therefore, we do not have to consider it in the next iterations
[6, <8>, (4), 20, 10]; 4 < 8 true so let's move 4 before 6; -> [(4), 6, 8, 20, 10];
At this point, we know that the two smallest elements are in the first two positions. Therefore, we do not have to consider them in the next iterations
[4, 6, <8>, (20), 10]; 20 < 8 false so let's move on;
At this point, we know that the three smallest elements are in the first three positions. Therefore, we do not have to consider them in the next iterations
[4, 6, 8, <20>, (10)]; 10 < 20 true so let us move 20 before 10 -> [4, 6, 8, (10), 20];
At this point, we know that the four smallest elements are in the first four positions. Therefore, we do not have to consider them in the next iterations
i < n is false, we exit the outer loop and the array is sorted.

Related

To sort an array in required manner

I need to sort the elements in the odd positions in the descending order and elements in the even position in ascending order. Here is my code, I'm unable to break the first loop.
#include<stdio.h>
int main()
{
int n, t;
printf("Enter the size of the array\n");
scanf("%d", &n);
int i, a[n];
if ((n > 20) || (n <= 0))
printf("Invalid Size");
else
{
printf("Enter the values\n");
for (i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
for (i = 0; i < n; i + 2)
{
if (a[i] > a[i + 2])
{
t = a[i];
a[i] = a[i + 2];
a[i + 2] = t;
}
}
for (i = 1; i < n; i + 2)
{
if (a[i] < a[i + 2])
{
t = a[i];
a[i] = a[i + 2];
a[i + 2] = t;
}
}
for (i = 0; i < n; i++)
{
printf("%d\n", a[i]);
}
}
}
For starters according to the C Standard the function main without parameters shall be declared like
int main( void )
There is no great sense to declare the variable n as having the type int that after that to check whether its value is less than zero. It is much better to declare it as having the type size_t.
And the array should be declared after the check
if ((n > 20) || (n <= 0))
printf("Invalid Size");
else
{
int a[n];
//...
In loops like this
for (i = 0; i < n; i + 2)
the variable i is not increased. It is obvious that you mean i += 2.
And the loops only moves the first minimum even and the first maximum odd elements to the end of the array. You need additional loops that will do the same operation for other elements of the array. That is the implementation of the bubble sort algorithm is incorrect.
Here is a demonstrative program that shows how the array can be sorted according to the requirements for even and odd elements of the array.
#include <stdio.h>
#define N 20
int main(void)
{
int a[N] = { 18, 1, 16, 3, 14, 5, 12, 7, 10, 9, 8, 11, 6, 13, 4, 15, 2, 17, 0, 19 };
for ( size_t i = 0; i < N; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
for ( size_t n = N, last; !( n < 3 ); n = last )
{
for ( size_t i = last = 2; i < n; i++ )
{
if ( ( i % 2 == 0 && a[i] < a[i - 2] ) ||
( i % 2 == 1 && a[i - 2] < a[i] ) )
{
int tmp = a[i];
a[i] = a[i - 2];
a[i - 2] = tmp;
last = i;
}
}
}
for ( size_t i = 0; i < N; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
return 0;
}
The program output is
18 1 16 3 14 5 12 7 10 9 8 11 6 13 4 15 2 17 0 19
0 19 2 17 4 15 6 13 8 11 10 9 12 7 14 5 16 3 18 1
The most obvious problem is that your for never ends because i is never actually updated. The i+2 in for (i = 0; i < n; i + 2) does not update i which keeps its initia value forever.
Try something like for (i = 0; i < n; i=i+2) instead.
A second problem is that you are not really performing a sorting.
I guess that you are trying to implement some sort of bubble sort.
It sorts using comparison. It is impossible to sort an array using less than n logn operation (when sorting using comparison). You are sorting the array in linear time and this should look as a red flag to you.
Try adding another for as follows:
for (i = 0; i < n; i+= 2)
for (j = i+2; j < n; j+= 2)
if (a[i] > a[j])
{
t = a[i];
a[i] = a[j];
a[j] = t;
}
and most importantly then read about why you need it.
And if you feel brave you can swap the intgers without using an intermediate variable t as follows (read more on the topic here: XOR swap):
if (a[i] > a[j])
{
a[i] = a[i]^a[j];
a[j] = a[j]^a[i];
a[i] = a[i]^a[j];
}
Hope it helps.

Insertion Sort C programming

Since this year I'm starting studying C programming at university.
In particular today I was trying to understand the insertion sort.
I wrote this code that is perfectly working:
void insertionSort (int v[], int s)
{
int i;
int j;
int value;
for (i = 1; i < s; i++)
{
value = v[i];
for (j = i - 1; (j >= 0) && (value < v[j]); j --)
{
v[j + 1] = v[j];
}
v[j + 1] = value; // why v[j+1]?
}
}
My question is about the last code line: v[j + 1] = value. If I understand correctly, j (that decreases every time), at the end of the for cycle, has a value of -1 and that's why is correct to write v[j + 1] = value.
Am I right or am I missing something? Really thanks for anybody who wants to help me by explaining me better.
The way you have your code setup right now, you need v[j + 1] because j will always be one before where you want to insert.
For example:
int v[6] = {1, 34, 2, 50, 4, 10}
s = sizeof(v) / sizeof(v[0]) = 6
Stepping through your code:
i = 1, j = 0
value = v[i] = 34
34 < 1 is false so it doesn't go into the inner
for loop
v[j + 1] = 34 which is right where 34 should be
Looping your entire code a second time: value = 2, j = 1, i = 2
Both conditions are met where j = 1 && 2 < 34 and you go into your inner loop
Since you already stored v[2] earlier when you did value = v[i], v[2] = 34 at this point is where you decrease j by 1 making j = 0
Looking at your array, it looks like this:
1, 34, 34
The inner for loop will try to loop again but fail the second check
At this point, j is 0 and when you do v[j + 1] = value, you're storing value (2) in its proper place.
Your array at this point looks like 1, 2, 34
So again, the significance of v[j + 1] is to insert in the correct place. If the value is already in the correct place than you swap with itself.
This is the process of Insertion Sort. It will swap if the numbers are not ordered.
Over here you can find an visualized example: https://visualgo.net/en/sorting
Here you have an example in C:
#include <stdio.h>
int main()
{
int n, array[1000], c, d, t;
printf("Enter number of elements\n");
scanf("%d", &n);
printf("Enter %d integers\n", n);
for (c = 0; c < n; c++) {
scanf("%d", &array[c]);
}
// Insertion Sort
for (c = 1 ; c <= n - 1; c++) {
d = c;
while ( d > 0 && array[d] < array[d-1]) {
t = array[d];
array[d] = array[d-1];
array[d-1] = t;
d--;
}
}
printf("Sorted list in ascending order:\n");
for (c = 0; c <= n - 1; c++) {
printf("%d\n", array[c]);
}
return 0;
}
mark first element as sorted
for each unsorted element
'extract' the element
for i = lastSortedIndex to 0
if currentSortedElement > extractedElement
move sorted element to the right by 1
else: insert extracted element

Understanding this C-based bubble sort

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
main()
{
int ctr, inner, outer, didSwap, temp;
int nums[10];
time_t t;
srand(time(&t));
for (ctr = 0; ctr < 10; ctr++)
{
nums[ctr] = (rand() % 99) + 1;
}
puts("\nHere is the list before the sort:"); for (ctr=0; ctr < 10; ctr++) {
printf("%d\n", nums[ctr]); }
for(outer = 0; outer < 9; outer++) {
didSwap = 0;
for (inner = outer; inner < 10; inner++)
{
if (nums[inner] < nums[outer])
{
temp = nums[inner];
nums[inner] = nums[outer];
nums[outer] = temp;
didSwap = 1;
}
}
if (didSwap == 0)
{
break;
}
}
puts("\nHere is the list after the sort:"); for(ctr = 0; ctr < 10; ctr++) {
printf("%d\n", nums[ctr]);
}
return 0;
}
I don't understand this part:
for(outer = 0; outer < 9; outer++) {
didSwap = 0;
for (inner = outer; inner < 10; inner++) {
if (nums[inner] < nums[outer])
...
}
}
If outer = 0 and inner = outer then both inner and outer equal to 0. and if the loop FOR says if (nums[inner] < nums[outer])
then how can nums[0] can be smaller than nums[0] since both inner and outer = 0? Please help me to understand.
guys i think my text book code is faulty. what do you think?
now the prob is with the BREAK. Do u think its on a right place.
if (didSwap == 0) {
break; }
now the problem is what if the 1st two array values are in ascending order and rest of the element of NUMS[] are random, then after the 1st iteration of inner loop it will break the outer loop since the didSwap will still be equivalent to zero.
i tried to initialized the NUMS[] manually like this..
int nums[10]={4,6,8,65,47,74,21,22,65,36};
please have a look...thanks
1)
Here is pseudocode that will help you to understand:
FOR J=1 TO N-1 {
FOR I=1 TO N-J {
IF A[I]>A[I+1] THEN SWAP A[I],A[I+1]
NEXT I
}
NEXT J
}
2)
As for the Bubble sorting in process.. Here is a simple example:
1) At first we compare the first two elements.
If the 1st el. is bigger (or equal) than the next el. - we swap them.
If the 1st el. is smaller - we do nothing.
(The smallest elements will be closer to the top & biggets to the bottom)
Then we compare 2nd and 3rd elements, them 3rd and 4th etc.
Compare all the elements until the last in array.
/* In this cycle, the biggest element will go to the bottom. */
2) Then we "forget" the last (the biggest) element and repeat the same again.
3) Repeat 1) and 2) successively until the end.
/* After all, all the elements will be sorted now: */
/* from the smallest to the largest. */
EXAMPLE:
Suppose we have 4 elements: 8, 6, 2, 1. That's how we will sort them:
1st cycle:
8, 6, 2, 1
v v
8 is bigger than 6, so we swap them
6, 8, 2, 1
v v
8 is bigger than 2, so we swap them
6, 2, 8, 1
v v
8 is bigger than 1, so we swap them
6, 2, 1, 8
v
The biggest element is at the bottom now.
2nd cycle:
6, 2, 1, 8
v v
6 is bigger than 2, so we swap them
2, 6, 1, 8
v v
6 is bigger than 1, so we swap them
2, 1, 6, 8
v v
6 will always be smaller or equal to 8, so we use ...
for (inner = 0; inner < (N-outer); inner++)
^^^^^^^ ... this expression to avoid
unnecessary actions.
3rd cycle:
2, 1, 6, 8
v v
2 is bigger than 1, so we swap them
The are 4 elements but we do (4-1)= 3 cycles:
for(outer = 0; outer < (N-1); outer++)
^^^
3)
Now, imagine that N = 10, outer = J and inner = I:
for(J = 0; J < (N-1) ; J++) {
didSwap = 0;
for (I = 0; I < (N-J); I++)
{
if (nums[I] < nums[I + 1])// at the beginning, here J = 0 and I = 1;
{ // then J = 0 and I = 2 etc.
temp = nums[I]; // It compares the first element with the
nums[I] = nums[I + 1]; // othe ones and swaps them so more lightweight
nums[I + 1] = temp; // (smaller, light) element will move higher.
didSwap = 1; // Just like a bubble.
}
}
if (didSwap == 0)
{
break;
}
}
UPDATE:
4)
You can't break the sorting loop until it finishes!
Look at the following code. It does fit the Bubble-sorting pseudocode (at the top of this answer):
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 10 // Here you can change the number of elements that
// will be sorted.
int main()
{
int ctr, inner, outer, didSwap, temp;
int nums[N];
time_t t;
srand(time(&t));
for (ctr = 0; ctr < N; ctr++)
{
nums[ctr] = (rand() % 99) + 1; // Filling the elements with random
} // values from 1 to 99.
puts("\nHere is the list before the sort:");
for (ctr=0; ctr < N; ctr++) {
printf("%d\n", nums[ctr]);
}
didSwap = 0;
for(outer = 0; outer < (N-1); outer++) {
for (inner = 0; inner < (N-outer); inner++)
{
if (nums[inner] >= nums[inner + 1]) // notice that there is `>=`
{ // instead of `>`.
temp = nums[inner]; // This will exchange also
nums[inner] = nums[inner + 1]; // equal elements so the
nums[inner + 1] = temp; // sorting will work correctly.
}
}
didSwap = 1; // Change `didSwap` only once --> after all cycles
// and all swappings: changing it's value after each
// swapping is a waste of machine's resources.
}
/* I can't understand why do you want to use this variable, but here it is. */
printf(" >>> didSwap = %d <<<\n", didSwap);
puts("\nHere is the list after the sort:");
for(ctr = 0; ctr < N; ctr++) {
printf("%d\n", nums[ctr]);
}
return 0;
}
You're correct that in the first iteration of the inner loop that if condition will always be false.
That's inefficient, but it does not make the algorithm incorrect.
This would be better:
for (inner = outer+1; inner < 10; inner++)

C - bubble sort with decreased loops amount

I've written the function which bubble-sorts some given array, and stops execution when the array is already sorted.
int sort(int *arr, int size) {
int i, j, temp, st = 1, count = 0;
for(i = 0; (i < size - 1) && (st == 1); i++)
{
st = 0;
for(j = 0; j < size - 1; j++)
{
if(arr[j] < arr[j + 1])
{
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
st = 1;
}
count++;
}
}
return count;
}
As you can see, the loop should be broken when the array is sorted before size^2 move.
However, something is wrong, and the count variable is always size * size, no matter what array I pass, even {1, 2, 3, 4, 5} gives the same results.
What is wrong?
With the condition
if(arr[j] < arr[j + 1])
you are sorting the array in descending order. So if you pass it [5, 4, 3, 2, 1], you'll get a value of less than size*size.
Note that each iteration of the outer loop moves one element to its final place at the end of the array, so you can cut down the inner loop to run only
for(j = 0; j < size - 1 - i; j++)
If we run
#include <stdio.h>
int sort(int *arr, int size) {
int i, j, temp, st = 1, count = 0;
for(i = 0; (i < size - 1) && (st == 1); i++)
{
st = 0;
for(j = 0; j < size - 1; j++)
{
if(arr[j] < arr[j + 1])
{
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
st = 1;
}
count++;
}
}
return count;
}
int main(void) {
#ifdef ASCENDING
int ar[] = { 1, 2, 3, 4, 5 };
#else
int ar[] = { 5, 4, 3, 2, 1 };
#endif
int i, ct = sort(ar, sizeof ar / sizeof ar[0]);
printf("%d\n",ct);
for(i = 0; i < (int)(sizeof ar / sizeof ar[0]); ++i) {
printf("%d ", ar[i]);
}
printf("\n");
return 0;
}
compiled without ASCENDING defined, the output is
4
5 4 3 2 1
thus the outer loop breaks after the first iteration because the array is already sorted as desired. When compiled with -DASCENDING, the array is originally in ascending order and needs the complete cycle to become sorted, i.e. the output is
16
5 4 3 2 1
(with the count being reduced to 10 if the inner loop runs only for j < size - 1 - i).

Traverse Matrix in Diagonal strips

I thought this problem had a trivial solution, couple of for loops and some fancy counters, but apparently it is rather more complicated.
So my question is, how would you write (in C) a function traversal of a square matrix in diagonal strips.
Example:
1 2 3
4 5 6
7 8 9
Would have to be traversed in the following order:
[1],[2,4],[3,5,7],[6,8],[9]
Each strip above is enclosed by square brackets.
One of the requirements is being able to distinguish between strips. Meaning that you know when you're starting a new strip. This because there is another function that I must call for each item in a strip and then before the beginning of a new strip. Thus a solution without code duplication is ideal.
Here's something you can use. Just replace the printfs with what you actually want to do.
#include <stdio.h>
int main()
{
int x[3][3] = {1, 2, 3,
4, 5, 6,
7, 8, 9};
int n = 3;
for (int slice = 0; slice < 2 * n - 1; ++slice) {
printf("Slice %d: ", slice);
int z = (slice < n) ? 0 : slice - n + 1;
for (int j = z; j <= slice - z; ++j) {
printf("%d ", x[j][slice - j]);
}
printf("\n");
}
return 0;
}
Output:
Slice 0: 1
Slice 1: 2 4
Slice 2: 3 5 7
Slice 3: 6 8
Slice 4: 9
I would shift the rows like so:
1 2 3 x x
x 4 5 6 x
x x 7 8 9
And just iterate the columns. This can actually be done without physical shifting.
Let's take a look how matrix elements are indexed.
(0,0) (0,1) (0,2) (0,3) (0,4)
(1,0) (1,1) (1,2) (1,3) (1,4)
(2,0) (2,1) (2,2) (2,3) (2,4)
Now, let's take a look at the stripes:
Stripe 1: (0,0)
Stripe 2: (0,1) (1,0)
Stripe 3: (0,2) (1,1) (2,0)
Stripe 4: (0,3) (1,2) (2,1)
Stripe 5: (0,4) (1,3) (2,2)
Stripe 6: (1,4) (2,3)
Stripe 7: (2,4)
If you take a closer look, you'll notice one thing. The sum of indexes of each matrix element in each stripe is constant. So, here's the code that does this.
public static void printSecondaryDiagonalOrder(int[][] matrix) {
int rows = matrix.length;
int cols = matrix[0].length;
int maxSum = rows + cols - 2;
for (int sum = 0; sum <= maxSum; sum++) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (i + j - sum == 0) {
System.out.print(matrix[i][j] + "\t");
}
}
}
System.out.println();
}
}
It's not the fastest algorithm out there (does(rows * cols * (rows+cols-2)) operations), but the logic behind it is quite simple.
I found this here: Traverse Rectangular Matrix in Diagonal strips
#include <stdio.h>
int main()
{
int x[3][4] = { 1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12};
int m = 3;
int n = 4;
for (int slice = 0; slice < m + n - 1; ++slice) {
printf("Slice %d: ", slice);
int z1 = slice < n ? 0 : slice - n + 1;
int z2 = slice < m ? 0 : slice - m + 1;
for (int j = slice - z2; j >= z1; --j) {
printf("%d ", x[j][slice - j]);
}
printf("\n");
}
return 0;
}
output:
Slice 0: 1
Slice 1: 5 2
Slice 2: 9 6 3
Slice 3: 10 7 4
Slice 4: 11 8
Slice 5: 12
I found this a quite elegant way of doing it as it only needs memory for 2 additonal variables (z1 and z2), which basically hold the information about the length of each slice. The outer loop moves through the slice numbers (slice) and the inner loop then moves through each slice with index: slice - z1 - z2. All other information you need then where the algorithm starts and how it moves through the matrix. In the preceding example it will move down the matrix first, and after it reaches the bottom it will move right: (0,0) -> (1,0) -> (2,0) -> (2,1) -> (2,2) -> (2,3). Again this pattern is captured by the varibales z1 and z2. The row increments together with the slice number untill it reaches the bottom, then z2 will start to increment which can be used to keep the row index constant at it's position: slice - z2. Each slice's length is known by: slice - z1 - z2, perofrming the following: (slice - z2) - (slice - z1 -z2) (minus as the algorithm moves in ascending order m--, n++) results in z1 which is the stopping criterium for the inner loop. Only the column index remains which is conveniently inherited from the fact that j is constant after it reaches the bottom, after which the column index starts to increment.
Preceding algorithm moves only in ascending order from left to right starting at the top left (0,0). When I needed this algorithm I also needed to search through a matrix in descending order starting at the bottom left (m,n). Because I was quite smitten by the algorithm I decided to get to the bottom and adapt it:
slice length is again known by: slice -z1 - z2
The starting position of the slices are: (2,0) -> (1,0) -> (0,0) -> (0,1) -> (0,2) -> (0,3)
The movement of each slice is m++ and n++
I found it quite usefull to depict it as follows:
slice=0 z1=0 z2=0 (2,0) (column index= rowindex - 2)
slice=1 z1=0 z2=0 (1,0) (2,1) (column index= rowindex - 1)
slice=2 z1=0 z2=0 (0,0) (1,1) (2,2) (column index= rowindex + 0)
slice=3 z1=0 z2=1 (0,1) (1,2) (2,3) (column index= rowindex + 1)
slice=4 z1=1 z2=2 (0,2) (1,3) (column index= rowindex + 2)
slice=5 z1=2 z2=3 (0,3) (column index= rowindex + 3)
Deriving the following: j = (m-1) - slice + z2 (with j++)
using the expression of the slice length to make the stopping criterium:((m-1) - slice + z2)+(slice -z2 - z1) results into: (m-1) - z1
We now have the argumets for the innerloop: for (int j = (m-1) - slice + z2; j < (m-1) - z1; j++)
The row index is know by j, and again we know that the column index only starts incrementing when j starts being constant, and thus having j in the expression again is not a bad idea. From the differences between the above summation I noticed that the difference is always equal to j - (slice - m +1), testing this for some other cases I was confident that this would hold for all cases (I'm not a mathematician ;P) and thus the algorithm for descending movement starting from the bottom left looks as follows:
#include <stdio.h>
int main()
{
int x[3][4] = { 1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12};
int m = 3;
int n = 4;
for (int slice = 0; slice < m + n - 1; ++slice) {
printf("Slice %d: ", slice);
int z1 = slice < n ? 0 : slice - n + 1;
int z2 = slice < m ? 0 : slice - m + 1;
for (int j = (m-1) - slice + z2; j <= (m-1) - z1; j++) {
printf("%d ", x[j][j+(slice-m+1)]);
}
printf("\n");
}
return 0;
}
Now I leave the other two directions up to you ^^ (which is only important when the order is actually important).
This algorithm is quite a mind bender, even when you think you know how it works it can still bite you in the ass. However I think it is quite beautifull because it literally moves through the matrix as you would expect. I am interested if anyone knows more about the algorithm, a name for instance, so I can look if what I have done here actually makes sense and maybe there is a better solutions.
I think this can be a solution for any type of matrix.
#include <stdio.h>
#define M 3
#define N 4
main(){
int a[M][N] = {{1, 2, 3, 4},
{5, 6, 7, 8},
{9,10,11,12}};
int i, j, t;
for( t = 0; t<M+N; ++t)
for( i=t, j=0; i>=0 ; --i, ++j)
if( (i<M) && (j<N) )
printf("%d ", a[i][j]);
return 0;
}
I thought this problem had a trivial solution, couple of for loops and some fancy counters
Precisely.
The important thing to notice is that if you give each item an index (i, j) then items on the same diagonal have the same value j+n–i, where n is the width of your matrix. So if you iterate over the matrix in the usual way (i.e. nested loops over i and j) then you can keep track of the diagonals in an array that is addressed in the above mentioned way.
// This algorithm works for matrices of all sizes. ;)
int x = 0;
int y = 0;
int sub_x;
int sub_y;
while (true) {
sub_x = x;
sub_y = y;
while (sub_x >= 0 && sub_y < y_axis.size()) {
this.print(sub_x, sub_y);
sub_x--;
sub_y++;
}
if (x < x_axis.size() - 1) {
x++;
} else if (y < y_axis.size() - 1) {
y++;
} else {
break;
}
}
The key is to iterate every item in the first row, and from it go down the diagonal. Then iterate every item in the last column (without the first, which we stepped through in the previous step) and then go down its diagonal.
Here is source code that assumes the matrix is a square matrix (untested, translated from working python code):
#define N 10
void diag_step(int[][] matrix) {
for (int i = 0; i < N; i++) {
int j = 0;
int k = i;
printf("starting a strip\n");
while (j < N && i >= 0) {
printf("%d ", matrix[j][k]);
k--;
j++;
}
printf("\n");
}
for (int i = 1; i < N; i++) {
int j = N-1;
int k = i;
printf("starting a strip\n");
while (j >= 0 && k < N) {
printf("%d ", matrix[k][j]);
k++;
j--;
}
printf("\n");
}
}
Pseudo code:
N = 2 // or whatever the size of the [square] matrix
for x = 0 to N
strip = []
y = 0
repeat
strip.add(Matrix(x,y))
x -= 1
y -= 1
until x < 0
// here to print the strip or do some' with it
// And yes, Oops, I had missed it...
// the 2nd half of the matrix...
for y = 1 to N // Yes, start at 1 not 0, since main diagonal is done.
strip = []
x = N
repeat
strip.add(Matrix(x,y))
x -= 1
y += 1
until x < 0
// here to print the strip or do some' with it
(Assumes x indexes rows, y indexes columns, reverse these two if matrix is indexed the other way around)
Just in case somebody needs to do this in python, it is very easy using numpy:
#M is a square numpy array
for i in range(-M.shape[0]+1, M.shape[0]):
print M.diagonal(offset=i)
public void printMatrix(int[][] matrix) {
int m = matrix.length, n = matrix[0].length;
for (int i = 0; i < m + n - 1; i++) {
int start_row = i < m ? i : m - 1;
int start_col = i < m ? 0 : i - m + 1;
while (start_row >= 0 && start_col < n) {
System.out.print(matrix[start_row--][start_col++]);
}
System.out.println("\n")
}
}
you have to break the matrix in to upper and lower parts, and iterate each of them separately, one half row first, another column first.
let us assume the matrix is n*n, stored in a vector, row first, zero base, loops are exclusive to last element.
for i in 0:n
for j in 0:i +1
A[i + j*(n-2)]
the other half can be done in a similar way, starting with:
for j in 1:n
for i in 0:n-j
... each step is i*(n-2) ...
I would probably do something like this (apologies in advance for any index errors, haven't debugged this):
// Operation to be performed on each slice:
void doSomething(const int lengthOfSlice,
elementType *slice,
const int stride) {
for (int i=0; i<lengthOfSlice; ++i) {
elementType element = slice[i*stride];
// Operate on element ...
}
}
void operateOnSlices(const int n, elementType *A) {
// distance between consecutive elements of a slice in memory:
const int stride = n - 1;
// Operate on slices that begin with entries in the top row of the matrix
for (int column = 0; column < n; ++column)
doSomething(column + 1, &A[column], stride);
// Operate on slices that begin with entries in the right column of the matrix
for (int row = 1; row < n; ++row)
doSomething(n - row, &A[n*row + (n-1)], stride);
}
static int[][] arr = {{ 1, 2, 3, 4},
{ 5, 6, 7, 8},
{ 9,10,11,12},
{13,14,15,16} };
public static void main(String[] args) {
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < i+1; j++) {
System.out.print(arr[j][i-j]);
System.out.print(",");
}
System.out.println();
}
for (int i = 1; i < arr.length; i++) {
for (int j = 0; j < arr.length-i; j++) {
System.out.print(arr[i+j][arr.length-j-1]);
System.out.print(",");
}
System.out.println();
}
}
A much easier implementation:
//Assuming arr as ur array and numRows and numCols as what they say.
int arr[numRows][numCols];
for(int i=0;i<numCols;i++) {
printf("Slice %d:",i);
for(int j=0,k=i; j<numRows && k>=0; j++,k--)
printf("%d\t",arr[j][k]);
}
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int N = 0;
cin >> N;
vector<vector<int>> m(N, vector<int>(N, 0));
for (int i = 0; i < N; ++i)
{
for (int j = 0; j < N; ++j)
{
cin >> m[i][j];
}
}
for (int i = 1; i < N << 1; ++i)
{
for (int j = 0; j < i; ++j)
{
if (j < N && i - j - 1 < N)
{
cout << m[j][i - j - 1];
}
}
cout << endl;
}
return 0;
}
A simple python solution
from collections import defaultdict
def getDiagonals(matrix):
n, m = len(matrix), len(matrix[0])
diagonals = defaultdict(list)
for i in range(n):
for j in range(m):
diagonals[i+j].append(matrix[i][j])
return list(diagonals.values())
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
assert getDiagonals(matrix) == [[1], [2, 4], [3, 5, 7], [6, 8], [9]]

Resources