C programming: how to implement an insertion sort? - c

Say I have a list of numbers:
89 12 18 4 6
and I want to implement an insertion sort and have it print every step of the sort onto the screen:
Sort 1. 12 89 18 4 6
Sort 2. 4 12 89 18 6
Sort 3. 4 6 12 89 18
Sort 4. 4 6 12 18 89
here's the code that I have so far, I'm confused as to where to insert the printf inside the loop.
void insertion_sort(FILE *fp, int ar[15])
{
int i, j, temp;
for (i = 0; i < 15; i++)
printf("%d\n", ar[i]);
for(i = 0; i < 15; i++) {
temp = ar[i];
for(j = i - 1; j >= 0 && ar[j] > temp; j--)
ar[j + 1] = ar[j];
ar[j + 1] = temp;
}

your scheme of sorting is actually Selection sort:
Sort 1. 12 89 18 4 6
Sort 2. 4 12 89 18 6
Sort 3. 4 6 12 89 18
Sort 4. 4 6 12 18 89
it finds the smallest number and places it at the beginning of the list.
A normal insertion sort would do the following:
Sort 1. 12 89 18 4 6
Sort 2. 12 18 89 4 6
Sort 3. 4 12 18 89 6
Sort 4. 4 6 12 18 89
and that is it finds 18 being less than 89 but greater than 12 and inserts 18 between 12 and 89 and the first iteration is done. Then repeat the process.
Here is my code:
void insertion(int *x,int n){ // int *x - array, n- array's length
int i,j,k,temp,elem; // i,j,k - counters, elem - to store the element at pos x[i]
for(i=0;i<n;i++){
elem=x[i]; // store the element
j=i;
while(j>0 && x[j-1]>elem){ // the magic(actual sorting)
x[j]=x[j-1];
j--;
}
x[j]=elem; // swap the elements
if(i>=1){ // here begins printing every sorting step, i>=1 because first time j is not greater than 0 so it just run through the loop first time
printf("sort %d. ",i); // printing the step
for(k=0;k<n;k++) // loop through array
printf("%d ",x[k]); // display the elements already sorted
printf("\n"); // when the array is displayed, insert a \n so that the next display will be on a new line
}
}
}

Put it at the end of the outer for statement just after ar[j + 1] = temp; and before the for loop ends

Related

Partition a Array

Given a randomly ordered array (arr) of n elements, function partitionArray(int arr[], int n, int x) partition the elements into two subsets such that elements <= x are in left subset and elements > x are in the right subset.
The first line of the test case will contain two numbers n (number of elements in a list ) and x (number to use for partition) separated by space.
The next line will contain N space-separated integers.
I am getting the wrong output for certain cases from the following Function.
Here's my code:
void partitionArray(int arr[], int n, int x)
{
int i, j, temp;
i = 0;
j = n-1;
while (i < j)
{
while (arr[i] <=x)
i++;
while (arr[j] > x)
j--;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
j--;
}
}
For the cases I am getting the right output is:
10 6
28 26 25 5 6 7 24 29 6 10
For the cases I am not getting the right output is:
10 17
28 26 25 11 16 12 24 29 6 10
The output I am getting in this:
10
6
12
11
25
16
24
29
26
28
Expected Output:
10
6
12
11
16
25
24
29
26
28
10 6
28 26 25 11 5 7 24 29 6 10
The output I am getting in this:
6
25
5
11
26
7
24
29
28
10
Expected Output:
6
5
25
11
26
7
24
29
28
10
Can Anyone help me this
Below change will do:
if(i < j){
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
When swapping when the value of j is i+1 and arr[i]<x and arr[j]>x, after i++ and j-- from while loops, the value of j is i-1 in your code. Hence checking i<j before swapping is important.
Suppose input is
2 5
1 10
Your output will be
10 1
And the index has to be checked as index may run out of the size of the array.
while (i<n && arr[i]<=x)
i++;
while (j>=0 && arr[j]>x)
j--;
Example inputs:
5 7
5 3 2 4 1
5 3
7 6 9 5 6

Eratosthenes prime numbers

I have created a program to search for prime numbers. It works without problems until the entered number is smaller than 52, when it is bigger output prints out some blank (0) numbers and I don't know why. Also other numbers have blank output.
My code is:
#include <stdio.h> //Prime numbers
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <unistd.h>
int c[100], n, a[50], d, e, b = 1;
void sort() {
for (int i = 1; i < n; i++) {
if (c[i] > 1) {
a[b] = c[i];
printf("%d %d %d\n", a[1], b, i);
b++;
e = 2;
d = 0;
while (d <= n) {
d = c[i] * e;
c[d - 1] = 0;
e++;
}
}
}
}
int main() {
printf("Enter number as an limit:\n");
scanf("%d", &n);
for (int i = 0; i < n; i++) {
c[i] = i + 1;
}
sort();
printf("Prime numbers between 1 and %d are:\n", n);
for (int i = 1; i < b; i++) {
printf("%d ", a[i]);
}
return 0;
}
Here is output for 25:
Enter number as an limit:
25
2 1 1
2 2 2
2 3 4
2 4 6
2 5 10
2 6 12
2 7 16
2 8 18
2 9 22
Prime numbers between 1 and 25 are:
2 3 5 7 11 13 17 19 23
But for 83 is:
Enter number as an limit:
83
2 1 1
2 2 2
2 3 4
2 4 6
2 5 10
2 6 12
2 7 16
2 8 18
2 9 22
2 10 28
2 11 30
2 12 36
2 13 40
2 14 42
2 15 46
2 16 52
0 17 58
0 18 60
0 19 66
0 20 70
0 21 72
0 22 78
0 23 82
Prime numbers between 1 and 83 are:
0 3 5 7 11 0 17 19 23 29 31 37 0 43 47 53 0 61 67 71 73 79 83
Blank spots always spots after 17th prime number. And always the blank numbers are the same. Can you help me please what is the problem?
The loop setting entries in c for multiples of c[i] runs too far: you should compute the next d before comparing against n:
for (d = c[i] * 2; d <= n; d += c[i]) {
c[d - 1] = 0;
}
As a matter of fact you could start at d = c[i] * c[i] because all lower multiples have already been seen during the previous iterations of the outer loop.
Also note that it is confusing to store i + 1 into c[i]: the code would be simpler with an array of booleans holding 1 for prime numbers and 0 for composite.
Here is a modified version:
#include <stdio.h>
int main() {
unsigned char c[101];
int a[50];
int n, b = 0;
printf("Enter number as a limit:\n");
if (scanf("%d", &n) != 1 || n < 0 || n > 100) {
printf("invalid input\n");
return 1;
}
for (int i = 0; i < n; i++) {
c[i] = 1;
}
for (int i = 2; i < n; i++) {
if (c[i] != 0) {
a[b] = i;
//printf("%d %d %d\n", a[0], b, i);
b++;
for (int d = i * i; d <= n; d += i) {
c[d] = 0;
}
}
}
printf("Prime numbers between 1 and %d are:\n", n);
for (int i = 0; i < b; i++) {
printf("%d ", a[i]);
}
printf("\n");
return 0;
}
Output:
chqrlie$ ./sieve4780
Enter number as a limit:
25
Prime numbers between 1 and 25 are:
2 3 5 7 11 13 17 19 23
chqrlie$ ./sieve4780
Enter number as a limit:
83
Prime numbers between 1 and 83 are:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79
Your problem seems to be caused by the fact that you have declared an array with size 50, but in fact it goes further than that: imagine you want to use Eratosthenes' procedure to find the first 10,000 prime numbers. Does this mean that you need to declare an array of size 10,000 first (or even bigger), risking to blow up your memory?
No: best thing to do is to work with collections where you don't need to set the maximum size at declaration time, like a linked list, a vector, ..., like that you can make your list grow as much as you like during runtime.

Applying a left shift in C [duplicate]

This question already has answers here:
Function to left shift a 2D array in C
(3 answers)
Closed 8 years ago.
I am learning how to manipulate a 2D array in C and I have to apply a left shift to a matrix, so A[0][0] becomes the value at A[0][1] etc. This is the code and output that I got after a few tries; I think I may be getting close:
void LeftShift2D(int A[M][N]){
int i;
int j;
int temp;
for(i = 0; i < M; i++){
for(j = 0; j < N; j++){
temp = A[0][0];
A[i][j] = A[i+1][j+1];
}
}
A[i][j] = temp;
}
Given this as the input:
14 17 28 26 24
26 17 13 10 2
3 8 21 20 24
17 1 7 23 17
12 9 28 10 3
21 3 14 8 26
this is the desired output:
17 28 26 24 26
17 13 10 2 3
8 21 20 24 17
1 7 23 17 12
9 28 10 3 21
3 14 8 26 14
but this is the actual output I'm getting:
14 17 28 26 24
26 17 13 10 2
3 8 21 20 24
17 1 7 23 17
12 9 28 10 3
21 3 14 8 26
4
17 13 10 2 3
8 21 20 24 17
1 7 23 17 12
9 28 10 3 21
3 14 8 26 4
-1218716075 -1217196044 0 -1079502888 134514340
What's wrong?
By far the easiest way to do what you want is:
void LeftShift2D(int A[M][N])
{
int i;
int temp = A[0][0];
int *base = &A[0][0];
for (i = 0; i < M * N - 1; i++)
base[i] = base[i+1];
A[i] = temp;
}
This treats the array as a vector and shifts the data down one space, rotating the value originally at the start to the end. If you wanted to rotate each row separately, you'd use different code, more closely related to what you show:
void LeftShift2D(int A[M][N])
{
int temp;
for (int i = 0; i < M; i++)
{
int j;
int temp = A[i][0]
for (j = 0; j < N - 1; j++)
A[i][j] = A[i][j+1];
A[i][j] = temp;
}
}
Your code has various problems. The A[i][j] = A[i+1][j+1]; assignment accesses data out of bounds, and copies data 'diagonally', copying the cell to the bottom-right (or south-east) of the current cell, not the cell to the right (east) of the current cell. It has problems wrapping, too.
You have a buffer overflow here
A[i][j] = A[i+1][j+1];
you need to iterate to i < M - 1 and j < N - 1.
You are accessing invalid memory which explains the observed values, that also invokes undefined behavior so you could observe some strange behavior eventually.

Iterative divide and conquer

This code, in every loop cycle creates twice smaller segment that it adds to number 0. Problem is that, if you split 50 you get 25 and 25 and if you split 51 you also get 25. This x and y should represent array index so they start from 0. If you know better iterative algorithm (must not use recursion) I'll be glad to see it but I really wnat to solve this problem this way(unless it can't be done).
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int n;
int a, b, x, r, y;
printf("Enter N: ");
scanf("%d", &n);
a = 0;
b = n - 1;
x = a;
y = b;
r = b;
printf(" %2d %2d\n", a, b);
while(b > 1)
{
r /= 2;
while(x < n - 1)
{
printf(" %2d ", x);
y = x + r; //if(something) y = x + r - 1;
printf("%2d", y); //else y = x + r;
x = y + 1;
}
x = a;
b = r;
y = b;
putchar('\n');
}
return 0;
}
output:
Enter N: 50
0 49
0 24 25 49
0 12 13 25 26 38 39 51
0 6 7 13 14 20 21 27 28 34 35 41 42 48
0 3 4 7 8 11 12 15 16 19 20 23 24 27 28 31 32 35 36 39 40 43 44 47 48 51
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
Press [Enter] to close the terminal ...
This is a breadth-first traversal problem and should be implemented with a queue. I do not think that there is a simple way to implement breadth-first recursion, so an iterative approach will have to do. The following is a rough algorithm:
1) Create two queues, q and p, containing your initial range [a, b].
2) While p is not empty, dequeue an element from p and print it.
3) While q is not empty, dequeue an element [i, j] from q and enqueue two new ranges [i, (i + j) / 2] and [(i + j) / 2 + 1, j] into p.
4) Copy p to q.
5) If q has a size of a + b + 1, then you are done. Otherwise, go back to step 2.
Here is my implementation in C#:
using System;
using System.Collections.Generic;
struct Pair
{
public int a;
public int b;
public Pair(int a, int b)
{
this.a = a;
this.b = b;
}
}
class Program
{
static void Main()
{
Console.Write("Enter a number: ");
int size = int.Parse(Console.ReadLine());
Queue<Pair> queue = new Queue<Pair>();
queue.Enqueue(new Pair(0, size));
bool lastRound = false;
do
{
if (queue.Count == size + 1)
{
lastRound = true;
}
Queue<Pair> temporary = new Queue<Pair>(queue);
while (temporary.Count > 0)
{
Pair pair = temporary.Dequeue();
if (pair.b - pair.a == 0)
{
Console.Write("{0} ", pair.a);
}
else
{
Console.Write("{0}-{1} ", pair.a, pair.b);
}
}
Console.WriteLine();
while (queue.Count > 0)
{
Pair pair = queue.Dequeue();
if (pair.b - pair.a == 0)
{
temporary.Enqueue(new Pair(pair.a, pair.b));
}
else
{
temporary.Enqueue(new Pair(pair.a, (pair.a + pair.b) / 2));
temporary.Enqueue(new Pair((pair.a + pair.b) / 2 + 1, pair.b));
}
}
queue = temporary;
} while (!lastRound);
}
}
Here is its output:
Enter a number: 20
0-20
0-10 11-20
0-5 6-10 11-15 16-20
0-2 3-5 6-8 9-10 11-13 14-15 16-18 19-20
0-1 2 3-4 5 6-7 8 9 10 11-12 13 14 15 16-17 18 19 20
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Do a google search for quicksort. You will find many examples of code that use this technique.
When you're splitting the number, you'll need to decide whether there is a remainder or not (depending on whether the number you are splitting is odd or even).
You will need to handle the two different scenarios differently. You will also have to decide where to put the extra number (on the first half or the second half).
Perhaps a possible modification is to have two r's to track the two halves.
The root of problem is that a fixed jump size (r) cannot be calculated for each iteration. A constant
r for each iteration will work only when the starting number
is a power of two (try starting with 64 and you will see that it all works as you want). For any other number the
jump size (r) may be either r or r+1 depending on whether
the prior iteration divided the current range being split into an even or odd number of elements. Consequently
the value of r may not be a constant throughout the entire iteration.
As soon as you see that the current iteration depends on results from a prior iteration the words "stack" or "recursion" pop up
as immediate solutions. This is because prior state information is needed to solve the problem.
There may be a purely iterative solution to your problem, but I think that it will either take some interesting
math or extra memory to maintain state information.

Error in scanf()

first of all, I've got a logical error in my code. Well, this is the code
#include <stdio.h>
int main()
{
long i,j,t;
scanf("%ld",&t);
long n[t],d[t][t];
for(i = 0; i < t;i++){
scanf("%ld",&n[i]);
for(j = 0; j < n[i] ;j++){
scanf("%ld",&d[j][i]);
}
}
for(i = 0; i < t;i++){
for(j = 0; j < n[i] ;j++){
printf("%ld ",d[j][i]);
}
printf("\n");
}
return 0;
}
And I input the data
2
4
25 20 30 90
3
45 50 55
And the result is
25 20 30 90
45 50 55
Well, that's what I expected. However, when the input become like this
3
5
12 67 89 34 56
6
34 56 78 90 12 34
7
12 34 89 23 56 78 89
The result become like this
12 34 89 23 56 78 89
12 67 89 34 56 4206692 7 2293472 1982002386 16 3 2293344 2293408 0 2293552 0 0 4
198585 8918456 1982106837 1982010910 8918456 2293640 0 0 1985286516 2009576437 0
0 2293664 2009323341 2293740 2147348480 0
34 56 78 90 12 34 4199405 1982595752 8 12 2293424 2 2 1982356412 2147348480 2293
608 2147348480 1 -1 297753669 1982010784 1982015505 4199044 0 0 2147348480 21473
48480 0 0 0 7273647 2009576392 0 0 0 1 0 20 52 0 0 438759246 736 -214797894 1420
760826203 2272 852421325 3108 944791496 4028 -1322777276 4988 9 1 1 1204 7168 4
2 152 11832 7 1 40 12316 1682469715 1 140 44 0 0 0 2 0 7209065 5701724 6029427
12 34 89 23 56 78 89
Well, the simple question, why the output become like the above?? When I input above 2, the same result will be happened. Any possible answers and links if you don't mind it?? Thanks
You are writing outside your 2D array in many cases, sometimes you don't get errors, but that's just by chance.
You determine the size of the 2D array by the number of arrays to be inputted, but you also determine the size of the inner arrays at the same time:
scanf("%ld",&t);
long n[t],d[t][t];
So for example, let's take the first example:
2 >> create array n[2], and array d[2][2]
4 >> number of values to d[0]
25 20 30 90 >> d[0][1] = 25 d[0][2] = 20 you access d[0][3] and d[0][4] but you are not allowed to do that.
3 >> number of values to d[1]
45 50 55 >> d[1][0] = 45 d[1][1] = 50 you access d[1][2] but you are not allowed to do that
You build a matrix with size t*t, then fill in rows with more or less elements.
If you fill a row with too few elements, the rest remain uninitialized, and you get strange numbers. It's OK in your case, because you don't print these elements.
If you fill a row with too many elements, the excess overlaps into the next row. It may also exceed the whole matrix and corrupt your stack.
I guess this is what's going on - your n array is overrun, and your code goes crazy.
I believe that you can use malloc.
#include <stdio.h>
#include <stdlib.h>
int main()
{
long i,j,t;
printf("Rows : ");
scanf("%ld",&t);
long *n;
long **d;
n = (long* )malloc(sizeof(long) * t); // add malloc
d = (long** )malloc(sizeof(long *) * t); // add malloc
for(i = 0; i < t;i++){
printf("Column : ");
scanf("%ld",&n[i]);
d[i] = (long* )malloc(sizeof(long) * n[i]); //add malloc
if(d[i] == NULL)
printf("ERROR\n");
for(j = 0; j < n[i] ;j++){
scanf("%ld", &d[i][j]); // change from &d[j][i]
}
}
printf("\n\n");
for(i = 0; i < t;i++){
for(j = 0; j < n[i] ;j++){
printf("%ld ",d[i][j]); // change from d[j][i]
}
printf("\n");
}
return 0;
}
Well, the simple question, why the output become like the above?? When
I input above 2, the same result will be happened. Any possible
answers and links if you don't mind it?? Thanks
because you allocate less memory than used.
scanf("%ld", &d[j][i]); you have to exchange the "i" and "j".

Resources