Shell sort in C not giving required result - c

I am required to implement a Shell sort in C and use the optimised version (where the gap is first set to size of array/2 and then this number is repeatedly divided by 2.2). The problem is that the answer isn't always completely sorted and I am not sure whether this is because of some logic error in my code or some shortcoming of the Shell sort.
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#define MAX 7
void shellSort(int *a, int size);
void insert(int *a, int next_pos, int gap);
void shellSort(int *a,int size)
{
int gap = floor(size/2);
int next_pos;
while (gap>0)
{
for(next_pos = gap; next_pos < size; next_pos++)
insert(a, next_pos, gap);
if(gap == 2)
gap = 1;
else
gap = (int)(gap/2.2);
}
}
void insert(int *a, int next_pos, int gap)
{
int value = a[next_pos];
while(next_pos >= gap && a[next_pos] < a[next_pos-gap])
{
a[next_pos] = a[next_pos-gap];
next_pos = next_pos - gap;
}
a[next_pos] = value;
}
int main()
{
int nums[MAX];
time_t t;
srand((unsigned) time(&t)); // seed randomiser
printf("Array before sorting:\n");
int i;
for(i=0; i<MAX; i++)
{
nums[i] = rand() % 101; // filling array with random numbers
printf("%d\t", nums[i]);
}
shellSort(nums, MAX);
printf("\nArray after sorting:\n");
for(i=0; i<MAX; i++)
printf("%d\t", nums[i]);
return 0;
}
The following is my output:
Array before sorting:
74 26 1 12 38 81 94
Array after sorting:
12 1 26 38 74 81 94
edit: posted before I was done with my question oops

I think your problem lies here:
int value = a[next_pos];
while(next_pos >= gap && a[next_pos] < a[next_pos-gap])
Since you're changing next_pos in the lines below, i think those lines should read (if my understanding of shellsort is correct):
int value = a[next_pos];
while(next_pos >= gap && value < a[next_pos-gap])

Related

Trying to write a program to fill an array with random numbers in C

My issue is that I am getting segmentation fault (core dumped) each time I try, I have yet to clean up my code, but I am stumped.
I must enter the values in with the compiler e.g "./filename 0 100" whereby 0 is min and 100 is max.
It must then fill the array of 10 elements with random numbers (0-100). I am so close, just can't fathom the main function.
Also, how can I print the array {0,1,2,3} in format "[0,1,2,3]" including the commas, without it looking like "[0,1,2,3, ]"
#include <stdlib.h>
#include <stdio.h>
int getRandom(int min, int max);
void fillArray(int data[], int size, int min, int max);
void printArray(int data[], int size);
int main(int argc, char *argv[]) {
int a;
int b;
if (argc>=3){
a = atoi(argv[1]);
b = atoi(argv[2]);
int arr[10];
printf("\t An array with random values from 0 to 100 \n");
fillArray(arr,10 ,a, b);
printArray(arr, 10);
} else {
printf("Incorrect number of arguments - please call with assignment min max\n");
}
return 0;
}
int getRandom(int min, int max) {
int result = 0;
int low = 0;
int high = 0;
if (min<max) {
low = min;
high = max+1;
} else {
low = max + 1;
high = min;
}
result = (rand() % (high-low)) + low;
return result;
}
void fillArray(int data[], int size, int min, int max){
int i;
for(i=min ; i < max+1; i++){
data[i] = getRandom(min,max);
}
}
void printArray(int data[], int size){
int i;
printf("[");
for(i=0; i<size; i++){
printf("%d,", data[i]);
}
printf("]");
}
I agree with #Steve Friedl that the main problem with your program lies in the fillArray function. There i should run from 0 to size.
As for your second question, testing whether you're printing the last number helps to suppress the unwanted comma:
void printArray(int data[], int size) {
printf("[");
for (int i = 0; i < size; i++) {
printf("%d", data[i]);
if (i < size - 1)
printf(",");
}
printf("]");
}
If you prefer a more compact solution (although with an optimizing compiler there's not really a difference), you could write it as:
void printArray(int data[], int size) {
printf("[");
for (int i = 0; i < size; i++) {
printf("%d%c", data[i], i < size-1 ? ',' : ']');
}
}
Also, in your main function, you should include a and b in your printing:
printf("\t An array with random values from %d to %d \n", a, b);
I believe this is blowing things up for you:
void fillArray(int data[], int size, int min, int max){
int i;
for(i=min ; i < max+1; i++){ // <-- HERE
data[i] = getRandom(min,max);
}
}
The calling function allocates 10 items in the arr array, and that's passed as the size parameter, but you're not using that parameter to limit filling up the array. If the max value is 100, then it's trying to fill one hundred slots instead of just ten.
for (i = 0; i < size; i++)
data[i] = getRandom(min,max);
should fix at least this issue.
EDIT: The comma thing, I prefer to add commas before the items unless this is the first. In this case it doesn't matter much, but it's more general, especially for variable-length lists where you don't know you're at the end until you get there. Augmenting the helpful response from #JohanC :
void printArray(int data[], int size) {
printf("[");
for (int i = 0; i < size; i++) {
if (i > 0) printf(",");
printf("%d", data[i]);
}
printf("]");
}

c program finding call function

Two integers are stored in the arrays a 1 and a 2, respectively, and the product is calculated by the same procedure as the calculation, but it does not output the correct result.
question is : want to produce 312*321 = 1 0 0 1 5 2 but this first program produce
? 0 9 9 11 5 2
to produce right result 1 0 0 1 5 2, call function name func(c,N*2)
#include <stdio.h>
#include <stdlib.h>
#define N 3
int main()
{
int a1[N]={1,2,3};
int a2[N]={2,1,3};
int b[N][N];
int c[N*2];
int i,j;
for(i=0;i<N;i++){
for(j=0;j<N;j++)
b[i][j]=a1[j]*a2[i];
}
c[0]=b[0][0];
c[1]=b[0][1]+b[1][0];
c[2]=b[0][2]+b[1][1]+b[2][0];
c[3]=b[1][2]+b[2][1];
c[4]=b[2][2];
for(i=N*2-1;i>=0;i--)
{
printf("%d ",c[i]);
}
printf("\n");
return 0;
}
The result:0 9 9 11 5 2
  |0|1|2| ->A1
----------------
A2<-| 0|2|4|6|
| 1|1|2|3|
| 2|3|6|9|
this array is the same as 321*312 calculate using hand in paper
Problem: Define the function func () to output the correct result 1 0 0 1 5 2, call func (c, N * 2); below i post the code with the call function func() in bold. any idea?? and also what the logic behind func()? trial and error? is there algorithm behind this?
#include <stdio.h>
#include <stdlib.h>
#define N 3
int main()
{
int a1[N]={1,2,3};
int a2[N]={2,1,3};
int b[N][N];
int c[N*2];
int i,j;
for(i=0;i<N;i++){
for(j=0;j<N;j++)
b[i][j]=a1[j]*a2[i];
}
c[0]=b[0][0];
c[1]=b[0][1]+b[1][0];
c[2]=b[0][2]+b[1][1]+b[2][0];
c[3]=b[1][2]+b[2][1];
c[4]=b[2][2];
**func(c,N*2);**
for(i=N*2-1;i>=0;i--)
{
printf("%d ",c[i]);
}
printf("\n");
return 0;
}
**void func(int a[],int digit)
{
here no idea....
}**
Try with this;
void func(int a[], int digit)
{
int i, c = 0;
for(i = 0; i < digit; i ++)
{
a[i] += c;
c = a[i] / 10;
a[i] = a[i] % 10;
}
}
I think you should change two things:
First initialization the result array
int c[N * 2] = {0}; //initialize
Also the function looks like
void func(int a[], int size) {
int carry = 0;
for (int i = 0; i < size; i++) {
a[i] += carry;
carry = a[i] / 10;
a[i] = a[i] % 10;
}
}

Find partial sum of 'X' numbers in array in c

can you help me with code which returns partial sum of 'X' numbers in array in c?
Complete :
int arr_sum( int arr[], int n )//Recursive sum of array
{
if (n < 0) //base case:
{
return arr[0];
}
else
{
return arr[n] + arr_sum(arr, n-1);
}
}
void sum_till_last (int *ar,int si )
{
**int sum,i;// the problem some where here
ar=(int*) malloc(si*sizeof(int));
for (i=0; i<si;i++)
{
sum=arr_sum(ar,i);
ar [i]=sum;
}
free (ar);**
}
void main ()
{
int i;
int a [5];
for (i = 0; i < 5; i++)
scanf_s("%d", &a[i]);
sum_till_last(a,5);
printf("%d\n",a[5]);
}
\i want to create new array with this this legality:
My input :
4
13
23
21
11
The output should be (without brackets or commas):
4
17
40
61
72
Now when we can see the full code, it's quite obvious that the problem is in the sum_till_last function where you overwrite the pointer you pass to the function with some new and uninitialized memory you allocate.
Drop the allocation (and the call to free of course). And fix the logical bug in arr_sum that causes you to get arr[0] + arr[0] when i is zero.
Here you go:
#include <stdio.h>
int main () {
int in_arr[5] = {4,13,23,21,11};
int out_arr[5];
int p_sum =0;
int i;
for ( i=0;i<5;i++){
out_arr[i] = in_arr[i]+p_sum;
p_sum=p_sum+in_arr[i];
}
for (i=0;i<5;i++){
printf("%d", out_arr[i] );
}
}
Fix according to your policy
#include <stdio.h>
#include <stdlib.h>
int arr_sum(int arr[], int n){
if (n == 0){//Change to this
return arr[0];
} else {
return arr[n] + arr_sum(arr, n-1);
}
}
void sum_till_last(int *ar, int si){
int sum,i;
int *temp = malloc(si * sizeof(int));//variable name ar is shadowing parameter name ar.
for(i = 0; i < si; i++){
temp[i] = arr_sum(ar, i);
if(i)
putchar(' ');
printf("%d", temp[i]);//need print out :D
}
free(temp);
}
int main(void){
int i, a[5];
for (i = 0; i < 5; i++)
scanf_s("%d", &a[i]);
sum_till_last(a, 5);
//printf("%d\n",a[5]);<-- this print only one element. and It's out of bounds element XD
}
I just made it simple so it´s easy to understand :)
I´m assuming "n" is always equal or less then array element number. Then you just print the SUM.
#include <stdio.h>
int arr_sum( int arr[], int n ){
int i=0,SUM=0;
for(; i < n;i++){
SUM= SUM+ arr[i];
printf("%d ",SUM);
}
}
int main(void) {
int array[] = {4, 13, 23, 21, 11};
arr_sum(array,5);
return 0;
}

Change position of an exact number of elements in an array

Let's say we have an array of m elements and we want to change randomly the position of exactly n of them, where of course 2 <= n <= m.
For example: if we have this array of 10 ints {1 2 3 4 5 6 7 8 9 10} and we ask for 4 of its elements to change positions randomly, a result could be {3 2 1 4 5 6 10 8 9 7}
What is the simplest way to program this in ANSI C? (pseudocode will also be just fine)
Step1). Generate a list of n random unique numbers between 1 and m. This list should NOT be sorted. Eg, for your example, the list could have been [10,7,1,3]
Step 2) do something like :
int save = array[list[0]];
For (i=0; i<n-1; i++) {
Array[list[i]] = array[list[i+1]];
}
Array[list[n-1]] = save;
Edit: actually, you'll have to have subtract 1 from each list[whatever] to allow for zero-based arrays - but I'm sure you get the idea :)
since at least two numbers must be swapped, i would pick two random numbers from array first and then swap them. they are added to array that holds swapped indexes. if there's more to swap, pick another number different than swapped ones and swap it with one of the previously swapped numbers.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void print_arr(int a[], int size) {
int i;
for (i = 0; i < size; i++) {
printf("%d ",a[i]);
}
printf("\n");
}
void swap(int a[], int i, int j) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
int next_idx(int swapped[], int s_count, int size) {
int n, i;
char in_arr;
while (1) {
in_arr = 0;
n = rand() % size;
for (i = 0; i < s_count; i++) {
if (swapped[i] == n) {
in_arr = 1;
break;
}
}
if (!in_arr) {
break;
}
}
return n;
}
void swap2_or_more(int a[], int size,int count) {
srand(time(NULL));
int i, j, s_count = 0;
int swapped[size];
i = rand() % size;
swapped[s_count] = i;
s_count++;
do {
j = rand() % size;
} while (i == j); // make sure indexes are different
swapped[s_count] = j;
s_count++;
swap(a, i, j);
count -= 2;
while (count) {
i = next_idx(swapped, s_count, size);
j = rand() % s_count;
swap(a, i, swapped[j]);
swapped[s_count] = i;
s_count++;
count--;
}
printf("swapped indexes:\n");
print_arr(swapped, s_count);
}
int main(void)
{
int a[] = {1,2,3,4,5,6,7,8,9,10};
swap2_or_more(a, 10, 5);
printf("array after swap:\n");
print_arr(a, 10);
return 0;
}

Moving parts right in two - dimensional matrix

I would like to get your help to understand and finish my program.
This is what I have to do:
"You must exercise program that:
First. An absorbing two - dimensional integer arr [M] [N]. M - number of rows N - number of columns. (Matrix size was received from the user)
Two. The program uses auxiliary functions "shift" moves the values ​​of the matrix to the right one place, as shown in the picture (2 entered instead of 1, 3 instead of 2, 4 instead of 3, ... 20 instead of 19, first place 20).
Shift have to write a function and call her three times in the sample matrix loop .."
Example
My problems are:
I don't know how to do the matrix two - dimensional integer arrays that there size is entered by the user. I only know by DEFINE SIZE of the row and the cols
My function isn't close to the real deal so I would like to get help finish my function.
My output:
My code:
#include "stdio.h"
#include "conio.h"
#include "stdlib.h"
#define M 4
#define N 5
void shift (int arr[M][N], int length);
void main()
{
int arr[M][N];
int i,j,length;
printf("Enter %d rows \n",M);
for (i=0 ; i<M ; i++ )
{
printf("Enter %d numbers:\n",N);
for(j=0 ; j<N ; j++ )
{
scanf("%d" , &arr[i][j] );
}
length=N+M;
}
shift (arr,length);
system("pause");
return ;
}
void shift (int arr[M][N], int length)
{
int i,j,temp;
temp=arr[0][0];
for(i=0; i<M; i++)
{
for(j=0; j<N-1 ; j++)
{
printf("%d ",arr[i][j]);
}
arr[i][j]=temp;
printf("\n");
}
}
Edit: pictures resized
Shifts all columns to the right.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void shift_columns_right(int M[100][100], int rows, int cols) {
int tmp_lastcol;
int j, k;
for (j = 0; j<rows; j++){
tmp_lastcol = M[j][cols-1];
for (k = cols-1; k > 0; k-- ){
M[j][k] = M[j][k-1];
}
M[j][0] = tmp_lastcol;
}
}
int main(void){
int B[100] [100] = {
{1,2,3,4},
{5,6,7,8},
{9,10,11,12},
{13,14,15,16},
{17,18,19,20},
};
shift_columns_right(B,5,4);
return 0;
}
I will you give a hint as how to shift the elements. The logic is to swap the elements between the current and last element in the row as you iterate. I will show you a working example on 1D array.
#include <stdio.h>
#define ARRAY_SIZE 5
int main()
{
int a[ARRAY_SIZE] = {11,22,33,44,55};
int i;
for (i=0; i<ARRAY_SIZE; ++i)
{
int temp = a[i];
a[i] = a[ARRAY_SIZE-1];
a[ARRAY_SIZE-1] = temp;
}
for(i=0; i<ARRAY_SIZE; ++i)
{
printf("%d\t",a[i]);
}
return 0;
}
Output: 55 11 22 33 44
To dynamically allocate the memory for array, use malloc. Hope it helps !

Resources