Time efficiency of Introduction to Database - c

I have a code that requires me to do this thing :
Input size of array and testcases.
A character of Operatiion such as (I,A,D,Q) and elements of array.
I : Adding an element into the array.
A : Will change data in the database to a new data that is not exist in
the database.
D : Delete data which has value X from database.
Q : Show all data that less than equal X from database.
Input :
<size of Array> <operations/testcase>
<I/A/D/Q> <elements of array with X value>
The example of input :
Input :
6 4
3 2 3 1 5 6
I 7
D 6
A 3 5
Q 7
Output :
6 (because only 1 Q operation)
I already created the program, but I think this is not efficient enough because it take a longer time to execute. My question is what should I do to make my program more efficient?
#include "stdio.h"
#define MAXSIZE 99999
void swap(int *a,int *b){
int temp = *a;
*a = *b;
*b = temp;
}
void printArr(int arr[]){
for(int i = 0; arr[i] != NULL; i++){
printf("%d ",arr[i]);
}
printf("\n");
}
void merge(int arr[], int l, int m, int r)
{
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;
int L[n1], R[n2];
for (i = 0; i < n1; i++)
L[i] = arr[l + i];
for (j = 0; j < n2; j++)
R[j] = arr[m + 1+ j];
i = 0; // Initial index of first subarray
j = 0; // Initial index of second subarray
k = l; // Initial index of merged subarray
while (i < n1 && j < n2)
{
if (L[i] <= R[j])
{
arr[k] = L[i];
i++;
}
else
{
arr[k] = R[j];
j++;
}
k++;
}
while (i < n1)
{
arr[k] = L[i];
i++;
k++;
}
while (j < n2)
{
arr[k] = R[j];
j++;
k++;
}
}
void mergeSort(int arr[], int l, int r)
{
if (l < r)
{
int m = l+(r-l)/2;
mergeSort(arr, l, m);
mergeSort(arr, m+1, r);
merge(arr, l, m, r);
}
}
int binarySearch(int arr[], int left, int right,int num){
if(right >= left){
int mid = (left + right) / 2;
if(num == arr[mid]) return mid;
if(arr[mid] > num) return binarySearch(arr, left, mid-1, num);
else return binarySearch(arr,mid+1,right, num);
}
return -1;
}
int main(int argc, char const *argv[])
{
int operations, sizeArr, numX, numY, arr[MAXSIZE];
char type;
scanf("%d %d",&sizeArr,&operations); getchar();
int index = 0, counter = 0;
for(index = 0; index < sizeArr; index++){
scanf("%d",&arr[index]); getchar();
}
mergeSort(arr, 0, sizeArr - 1);
int left = 0, deleted = 0;
for(int j = 0; j < operations; j++){
scanf("%c",&type); getchar();
if(type == 'I'){
scanf("%d",&numX); getchar();
arr[index++] = numX;
sizeArr++;
}
else if(type == 'A'){
scanf("%d %d",&numX, &numY); getchar();
mergeSort(arr, 0, sizeArr - 1);
for(int i = deleted; arr[i] != NULL ; i++){
if(arr[i] == numX){
int old = arr[i];
arr[i] = numY;
if(arr[i + 1] != old) break;
}
}
}
else if(type == 'D'){
scanf("%d",&numX); getchar();
for(int i = 0; arr[i] != NULL ; i++){
if(arr[i] == numX){
int old = arr[i];
arr[i] = -1;
deleted++;
if(arr[i + 1] != old) break;
// sizeArr--;
}
}
mergeSort(arr, 0, sizeArr - 1);
}
else if(type == 'Q'){
scanf("%d",&numX); getchar();
mergeSort(arr, 0, sizeArr - 1);
// printArr(arr);
for(int i = deleted; i < sizeArr ; i++){
if(arr[i] <= numX && arr[i] > -1){
counter++;
// printf("%d\n",arr[i]);
}
else break;
}
printf("%d\n",counter);
counter = 0;
}
// printf("Size Arr : %d\n", sizeArr);
// printf("Deleted : %d\n",deleted);
// printArr(arr);
}
return 0;
}
Could you please tell me my mistake to my program more efficient on time limit?
They didn't mention the time limit duration. It only gives 5/10 testcase that correct. So I need to find another efficient way to make my code goes faster.

Related

Having issues with outputting the number of searches of a Binary search algorithm

I'm stuck with trying to get the number of searches done within a Binary search algorithm.
The goal is to test how many searches are done depending on how much data is put into the algorithm.
The program in question
//CBinarysearch.c//
#include <stdio.h>
#include <time.h>
#define NUM 100
#define MAX 200
int binary_s(int a[], int n, int s) {
int lo, hi, mid;
int c = 0;
lo = 0;//loの初期化
hi = n-1;//hiの初期化
while (lo <= hi) {
mid = (lo + hi) / 2;//midの初期化
c++;
if (s == a[mid]) break;//探索値がmidと同じ値となればloopを終了
if (s > a[mid])//探索値がmidより大きい場合
lo = mid + 1;//loの値を;1してmidへ移動
else//探索値がmidより小さい場合
hi = mid - 1;//hiの値をー1してmidへ移動
}
if (lo <= hi)
printf("The numerical value %d is in array %d (array element %d)\n", s, mid+1, mid);
else
printf("Could not be located.\n");
return c;
}
void shuffle(int a[]) {
unsigned int i, j;
int tmp;
i = MAX - 1;
while (i > 0) {//シャッフルのためのLoop
j = rand() % (i + 1);//jの値をランダム化
tmp = a[j];
a[j] = a[i];
a[i] = tmp;
i--;
}
}
int quicksort(int a[], int first, int last) {
int i, j, temp, x;
i = first;
j = last;
x = (a[i] + a[j]) / 2;//基準値は平均
while (1) {
while (a[i] < x) i++;
while (a[j] > x) j--;
//iがjより大きくなればwhile loopが解除される
if (i >= j) break;
//a[i]とa[j]を入れ替える
temp = a[i];
a[i] = a[j];
a[j] = temp;
i++;
j--;
}
if (first < i-1) quicksort(a, first, i-1);
if (j + 1 < last) quicksort(a, j + 1, last);
return 0;
}
int main(void) {
int a[NUM];
int i;
int count;
int s;
srand((unsigned int)time(NULL));
i = rand() % NUM;
s = a[i];
for (i = 0; i < NUM; i++) {//整列数列の作成
a[i] = i + 1;
}
shuffle(a);//Fisher-Yates shuffle
quicksort(a, 0, NUM-1);//クイックソートの呼び出し
count = binary_s(a, NUM, s);
printf("\n%d ", count);//交換回数の出力
return 0;
}
I've been at this for an embarrassingly long time. And at this point I am adding more details just to make this post viable. It's been rough.
May I ask for some help, please?
You intialize s as s = a[i]; before initializing the array: this has undefined behavior. You should instead write:
s = rand() % NUM + 1;
Furthermore the shuffle function assumes the array has MAX elements whereas you define it with a length of NUM in main(). You should pass the length to shuffle().
Also note that x = (a[i] + a[j]) / 2 would have undefined behavior if the values in the array can be arbitrary large.
You should also consider adding some white space between the code and the comments to make the code more readable, especially to non Japanese readers.
Here is a modified version:
//CBinarysearch.c//
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define NUM 100
int binary_s(int a[], int n, int s) {
int lo, hi, mid;
int c = 0;
lo = 0; // loの初期化
hi = n - 1; // hiの初期化
while (lo <= hi) {
mid = lo + (hi - lo) / 2; // midの初期化
c++;
if (s == a[mid]) // 探索€¤がmidと同じ€¤となればloopを終了
break;
if (s > a[mid]) // 探索€¤がmidより大きい場合
lo = mid + 1; // loの€¤を;1してmidへ移動
else // 探索€¤がmidより小さい場合
hi = mid - 1; // hiの€¤をー1してmidへ移動
}
if (lo <= hi) {
printf("The numerical value %d is in array at index %d\n",
s, lo);
} else {
printf("value %d Could not be located in array.\n", s);
}
return c;
}
void shuffle(int a[], int len) {
int i, j;
int tmp;
for (i = len - 1; i > 0; i--) { // シャッフルのためのLoop
j = rand() % (i + 1); // jの€¤をラン€ム化
tmp = a[j];
a[j] = a[i];
a[i] = tmp;
}
}
void quicksort(int a[], int first, int last) {
int i, j, temp, x;
if (first >= last)
return;
i = first;
j = last;
x = ((long long)a[i] + a[j]) / 2; // 基準€¤は平均
while (1) {
while (a[i] < x) i++;
while (a[j] > x) j--;
//iがjより大きくなればwhile loopが解除される
if (i >= j) break;
//a[i]とa[j]を入れ替える
temp = a[i];
a[i] = a[j];
a[j] = temp;
i++;
j--;
}
quicksort(a, first, i - 1);
quicksort(a, j + 1, last);
}
int main(void) {
int a[NUM];
int i;
int count;
int s;
srand((unsigned int)time(NULL));
for (i = 0; i < NUM; i++) { // 整列数列の作成
a[i] = i + 1;
}
s = a[rand() % NUM];
shuffle(a, NUM); // Fisher-Yates shuffle
quicksort(a, 0, NUM - 1); // クイックソートの呼び出し
count = binary_s(a, NUM, s);
printf("iterations: %d\n", count); // 交換回数の出力
return 0;
}

the code of merge_sort doesn`t sort properly

i code the merge sort as below but it doesn't sort the Array. and i cant find the source of the problem.
void print_arr(int Arr[], int size)
{
int i;
for (i = 0;i < size;i++)
printf(" %d ", Arr[i]);
}
///////////////////////////////////////////
void merge(int Arr[], int left, int mid, int right)
{
int i = 0, j = 0, k = left;
int n_l = (mid - left + 1);
int n_r = (right - mid);
int* Arr_l = (int*)calloc(n_l , sizeof(int));
int* Arr_r = (int*)calloc(n_r , sizeof(int));
if (Arr_l == NULL)
return;
if (Arr_r == NULL)
return;
for (i = 0;i < n_l;i++)
Arr_l[i] = Arr[i];
for (j = 0;j < n_r;j++)
Arr_r[j] = Arr[mid + 1 + j];
while (i < n_l && j < n_r)
{
if (Arr_l[i] <= Arr_r[j])
{
Arr[k] = Arr_l[i];
i++;
k++;
}
else
{
Arr[k] = Arr_r[j];
j++;
k++;
}
}
while (i < n_l)
{
Arr[k] = Arr_l[i];
i++;
k++;
}
while (j < n_r)
{
Arr[k] = Arr_r[j];
j++;
k++;
}
free(Arr_l);
free(Arr_r);
}
////////////////////////////////////////////////////////////////////
void merge_sort_inc(int Arr[], int left, int right)
{
int mid = (int)((left + (right - 1)) / 2);
if (left < right)
{
merge_sort_inc(Arr, left, mid);
merge_sort_inc(Arr, mid + 1, right - 1);
merge(Arr, left, mid, right);
}
}
////////////////////////////////////////////////////////////////
int main()
{
int i;
time_t t;
srand((unsigned)time(&t));
int Array[10];
int size = sizeof(Array) / sizeof(int);
for (i = 0;i < size;i++)
Array[i] = rand() / 100;
printf(" The unsorted Arrar is : \n\n");
print_arr(Array, size);
printf("\n\n The sorted Array is : \n ");
merge_sort_inc(Array, 0, size);
print_arr(Array, size);
return 0;
}
int i = 0, j = 0, k = left;
you should reset the value of i, j before while loop
i = 0; j = 0; k = left;
while (i < n_l && j < n_r)
{...}
Then:
for (i = 0;i < n_l;i++)
Arr_l[i] = Arr[i];
change to
for (i = 0;i < n_l;i++)
Arr_l[i] = Arr[left+i];
Finally, the merge_sort_inc function should change to:
void merge_sort_inc(int Arr[], int left, int right) {
if (left < right)
{
int mid = left + (right - left) / 2;
merge_sort_inc(Arr, left, mid);
merge_sort_inc(Arr, mid + 1, right);
merge(Arr, left, mid, right);
}
}
Then in main function, when you call merge_sort_inc function in main:
merge_sort_inc(Array, 0, size-1); // change size to size-1
OT, your part of code below is not wrong:
while (i < n_l)
{
Arr[k] = Arr_l[i];
i++;
k++;
}
while (j < n_r)
{
Arr[k] = Arr_r[j];
j++;
k++;
}
But you can bring k++ to the end of condition to limit one line of code as:
while (i < n_l)
{
Arr[k] = Arr_l[i];
i++;
}
while (j < n_r)
{
Arr[k] = Arr_r[j];
j++;
}
k++;
The complete code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void print_arr(int Arr[], int size)
{
int i;
for (i = 0;i < size;i++)
printf(" %d ", Arr[i]);
}
void merge(int Arr[], int left, int mid, int right)
{
int i, j, k;
int n_l = (mid - left + 1);
int n_r = (right - mid);
int* Arr_l = calloc(n_l , sizeof(int));
int* Arr_r = calloc(n_r , sizeof(int));
if (Arr_l == NULL)
return;
if (Arr_r == NULL)
return;
for (i = 0;i < n_l;i++)
Arr_l[i] = Arr[left+i];
for (j = 0;j < n_r;j++)
Arr_r[j] = Arr[mid + 1 + j];
i = 0; j = 0; k = left;
while (i < n_l && j < n_r)
{
if (Arr_l[i] <= Arr_r[j])
{
Arr[k] = Arr_l[i];
i++;
}
else
{
Arr[k] = Arr_r[j];
j++;
}
k++;
}
while (i < n_l)
{
Arr[k] = Arr_l[i];
i++;
k++;
}
while (j < n_r)
{
Arr[k] = Arr_r[j];
j++;
k++;
}
free(Arr_l);
free(Arr_r);
}
void merge_sort_inc(int Arr[], int left, int right) {
if (left < right)
{
int mid = left + (right - left) / 2;
merge_sort_inc(Arr, left, mid);
merge_sort_inc(Arr, mid + 1, right);
merge(Arr, left, mid, right);
}
}
int main()
{
int i;
time_t t;
srand((unsigned)time(&t));
int Array[10];
int size = sizeof(Array) / sizeof(int);
for (i = 0;i < size;i++)
Array[i] = rand() % 100; // should use % instead of / to have smaller value to see easily
printf(" The unsorted Arrar is : \n\n");
print_arr(Array, size);
printf("\n\n The sorted Array is : \n ");
merge_sort_inc(Array, 0, size-1);
print_arr(Array, size);
return 0;
}
The output of test:
The unsorted Arrar is :
60 32 71 35 93 91 29 80 78 47
The sorted Array is :
29 32 35 47 60 71 78 80 91 93

Merge Sort Error : Segmentation Fault

I'm getting an error Segmentation Fault:11, please help.
variable info:(s:start, e:end, m:mid, n:array), testing for a sample array n[] = {4,3,2,1}. a1 and a2 are temporary arrays. I am guessing there's something with the calculation of m:mid and passing it.
#include <stdio.h>
void merge(int s, int e, int m, int n[]) {
int l1 = m - s;
int l2 = e - m + 1;
int a1[l1];
int a2[l2];
for (int i = 0; i < l1; i++) {
a1[i] = n[s + i];
}
for (int j = 0; j < l2; j++) {
a2[j] = n[s + m + j];
}
int i = 0, j = 0;
for (int k = 0; k < l1 + l2; k++) {
if (a1[i] <= a2[j] && i != l1 && j != l2) {
n[k] = a1[i];
i++;
} else if (a2[j] <= a1[i] && i != l1 && j != l2) {
n[k] = a2[j];
j++;
} else if (j == l2 && i != l1) {
n[k] = a1[i];
i++;
} else if(i == l1 && j != l2) {
n[k] = a2[j];
j++;
}
}
}
void mergeSort(int s, int e, int n[]) {
if (s < e) {
int m = (e - s) / 2;
mergeSort(s, m - 1, n);
mergeSort(m, e, n);
merge(s, e, m, n);
}
}
int main(void) {
int n[] = { 4, 3, 2, 1 };
int r = 4;
mergeSort(0, r - 1, n);
for(int i = 0; i < r; i++) {
printf("%i\n", n[i]);
}
}
The computation of m for the middle element is bogus: you get the offset of m from s, not its index into the array.
Here is a corrected version:
void mergeSort(int s, int e, int n[]) {
if (s < e) {
int m = s + (e - s + 1) / 2;
mergeSort(s, m - 1, n);
mergeSort(m, e, n);
merge(s, e, m, n);
}
}
There are other issues in your code, notably:
you should check the offsets i and j beforedereferencinga1[i]anda2[j]`.
the offset k should not be used directly in the merge phase, you should store to n[s + k].
in the initialization loop for a2, you should use a2[j] = n[m + j]; instead of a2[j] = n[s + m + j];
Note also that it is idiomatic to pass ranges in C with the first index included and the last index excluded. This allows for passing empty ranges, which your current method does not. It also makes the code much simpler and easier to read.
Here is a modified version:
#include <stdio.h>
void merge(int s, int e, int m, int n[]) {
int l1 = m - s;
int l2 = e - m;
int a1[l1];
int a2[l2];
for (int i = 0; i < l1; i++) {
a1[i] = n[s + i];
}
for (int j = 0; j < l2; j++) {
a2[j] = n[m + j];
}
for (int i = 0, j = 0, k = 0; k < l1 + l2; k++) {
if (i < l1 && (j >= l2 || a1[i] <= a2[j])) {
n[s + k] = a1[i];
i++;
} else {
n[s + k] = a2[j];
j++;
}
}
}
void mergeSort(int s, int e, int n[]) {
if (e > s + 1) {
int m = s + (e - s) / 2;
mergeSort(s, m, n);
mergeSort(m, e, n);
merge(s, e, m, n);
}
}
int main(void) {
int n[] = { 4, 3, 2, 1 };
int r = sizeof(n) / sizeof(n[0]);
mergeSort(0, r, n);
for(int i = 0; i < r; i++) {
printf("%i\n", n[i]);
}
return 0;
}
I've modified your code in several places. Try to use your debugger or pen & paper to understand what's going on under the hood.
void merge(int s, int e, int m, int n[]){
int l1 = m-s + 1;
int l2 = e - m;
int a1[l1];
int a2[l2];
for(int i = 0; i < l1; i++){
a1[i] = n[s+i];
}
for(int j = 0; j < l2; j++){
a2[j] = n[m+j + 1];
}
int i = 0, j = 0;
for(int k = 0; k < l1+l2; k++){
if(a1[i] <= a2[j] && i != l1 && j != l2){
n[k] = a1[i];
i++;
}else if(a2[j] <= a1[i] && i != l1 && j != l2){
n[k] = a2[j];
j++;
}else if(j == l2 && i != l1){
n[k] = a1[i];
i++;
}else if(i == l1 && j != l2){
n[k] = a2[j];
j++;
}
}
}
void mergeSort(int s, int e, int n[]){
if(s<e){
int m = s + (e-s)/2;
mergeSort(s, m, n);
mergeSort(m + 1, e, n);
merge(s,e,m, n);
}
You will be fine I guess.
I think you have a stack overflow problem because of infinite recursive calls. Look
void mergeSort(int s, int e, int n[]){
if(s<e){
int m = (e-s)/2;
mergeSort(s, m-1, n);
mergeSort(m, e, n);
merge(s,e,m, n);
}
}
You pass these values of s and e:
s e function
-------------
0 3 mergeSort
0 0 mergeSort -> end
1 3 mergeSort
0 0 mergeSort -> end
1 3 mergeSort
... (infinite calls)
Then the stack grows and grows while new functions called until in the end it exceeds the maximum possible size, which leads to SEGFAULT.

How to write single function for search in row wise and column wise sorted 2d array(limit is function should be like int search(int *A,int n,int key))

Hello guys I wrote a programm to generate random numbers and then sort those numbers row wise and column wise and at the end the function search to find key inside the 2d array but today my proff said you should send me just single function like this int search(int *A,int n,int key) so that I can test it in my program I have no idea how to do it the limits are columns and rows are between 2-5000 and elements are between 0 till int Max and problem said test if n is increasing and suppose matrix is n by n and every rows and column are sorted.
My previous program was this
#include <stdio.h>
#include <stdlib.h>
#define R 5000
#define C 5000
int arr[R][C];
int search(int arr[][C], int r, int c, int key) {
if(key < arr[0][0] || key > arr[r - 1][c - 1])
return -1;
r = 0;
c = c - 1;
while(r <= c - 1 && c >= 0) {
if(arr[r][c] < key)
r++;
else if(arr[r][c] > key)
c--;
else
return 1;
}
}
void sort_rows(int *arr, int n)
{
int i;
for(i = 1; i < n; i++)
{
int key = arr[i];
int j = i - 1;
while(j >= 0 && key < arr[j])
{
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = key;
}
}
void sort_column(int arr[][C], int r, int c)
{
int key, k;
int i, j;
for(i = 0; i < r; i++)
{
for(j = 1; j < c; j++)
{
key = arr[j][i];
k = j - 1;
while(k >= 0 && arr[k][i] > key)
{
arr[k + 1][i] = arr[k][i];
k--;
}
arr[k + 1][i] = key;
}
}
}
int main()
{
int r, c;
int key;
int i, j, size_row, size_column;
printf("Enter Number of rows and columns(2-%d,2-%d):", R, C);
scanf("%d%d", &r, &c);
for(i = 0; i < r; i++)
{
for(j = 0; j < c; j++)
arr[i][j] = rand() % (r * c) + 1;
}
printf("Original array:\n");
for(i = 0; i < r; i++)
{
for(j = 0; j < c; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
for(i = 0; i < r; i++)
{
sort_rows(arr[i], c);
}
sort_column(arr, r, c);
printf("Sorted Array:\n");
for(i = 0; i < r; i++)
{
for(j = 0; j < c; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
printf("Enter element to search:");
scanf("%d", &key);
if(search(arr, r, c, key) == -1) printf("the %d not found", key);
else printf("the %d is found", key);
}
So I dont know how to implement like that
any help would be great thank you so much
I'm assuming the that int* arr is cast from a 2D array, contiguously allocated, and that the functions signature is:
int search(int *arr,int n,int key))
if(key < arr[0] || key > arr[n*n-1])
return -1;
r = 0;
c = n - 1;
while(r <= c - 1 && c >= 0) {
if(arr[r*n+c] < key)
r++;
else if(arr[r*n+c] > key)
c--;
else
return 1;
}
return -1;
This should work, assuming the array is square (number of columns equals number of rows), this function will return -1 if element is not found and 1 if it is found.
int search(int *arr,int n,int key) {
if(key < arr[0] || key > arr[n*n-1])
return 0;
int r = 0;
int c = n - 1;
while(r <= c - 1 && c >= 0) {
if(arr[r*n+c] < key)
r++;
else if(arr[r*n+c] > key)
c--;
else
return 1;
}
return 0;
}
I changed -1 with zero just because limit of the programm and just declare r and c and nothing else but it did not work there was not compilation failed it is problem inside of programm so would you please tell me what could it be wrong

Merge sort algorithm in C not working as expected

I am trying to implement the merge sort algorithm in C. I understand how the algorithm is supposed to work however I am encountering some difficulties with the implementation.
I understand that there are hundreds of examples and source code for it's implementation but I was hoping someone could help me understand why mine is not working correctly.
My code is below and after the code I explain what I have tried so far.
#include <stdio.h>
void merge(int a[], int L[], int R[],int nL, int nR) //nL and nR are the lengths of L[] and R[]
{
int i = 0 , j = 0, k = 0;
while(i<nL && j <nR)
{
if(L[i] <= R[j]){
a[k] = L[i];
i++;
}
else{
a[k] = R[j];
j++;
}
k++;
}
while(i < nL){
a[k] = L[i];
i++;
k++;
}
while(j < nR) {
a[k] = R[j];
j++;
k++;
}
}
void mergesort(int a[],int n) //n is the length of a[]
{
if(n < 2) return; //BASE CASE
int mid = n / 2;
int left[mid];
int right[n-mid];
for(int i = 0; i < mid; i++)
{
left[i] = a[i];
}
for(int i = mid; i < n-1; i++)
{
right[i-mid] = a[i];
}
int nL = sizeof(left) / sizeof(left[0]);
int nR = sizeof(right) / sizeof(right[0]);
mergesort(left, nL);
mergesort(right, nR);
merge(a,left,right,nL,nR);
}
int main(void)
{
printf("Initial:\n");
printf("3 4 1 6\n");
int numbers[4] = {3,4,1,6};
int n = sizeof(numbers) / sizeof(int);
mergesort(numbers,n);
printf("Sorted:\n");
for(int i =0 ; i < 4; i++)
{
printf("%d ", numbers[i]);
}
return 0;
}
As it is and with the unsorted array [3,4,1,6] the output is 0 0 1 3.
Clearly the 1 and 3 are in the right order relative to each other but the two zeros at the beginning are clearly wrong. At first it seemed to me that I was inserting 4 and 6 to the right and out of bounds of the array.
I used some print statements to try and debug but I haven't been able to figure out what was going on. I even tried to follow my code with gdb but I still could not sort it.
Does any one have any ideas of what might be happening?
A more nearly idiomatic way of writing the merge() code would be:
void merge(int a[], int L[], int R[],int nL, int nR)
{
int i = 0, j = 0, k = 0;
while (i < nL && j < nR)
{
if (L[i] <= R[j])
a[k++] = L[i++];
else
a[k++] = R[j++];
}
while (i < nL)
a[k++] = L[i++];
while (j < nR)
a[k++] = R[j++];
}
That's about half the number of lines of your code, and within broad limits, the less code there is to read, the better. There are those who insist on having braces after each loop or conditional. I don't think that's necessary (or particularly helpful), but if that's the style you like, you can use it.
Your mergesort() code is less flabby, but could be changed to:
void mergesort(int a[],int n) //n is the length of a[]
{
if (n < 2)
return; //BASE CASE
int mid = n / 2;
int left[mid];
int right[n-mid];
for (int i = 0; i < mid; i++)
left[i] = a[i];
for (int i = mid; i < n; i++)
right[i-mid] = a[i];
mergesort(left, mid);
mergesort(right, n - mid);
merge(a, left, right, mid, n - mid);
}
This includes the fix for your main problem — the loop loading the right array was leaving the last element uncopied.
With a debugging function such as:
void dump_array(const char *tag, int n, int *a)
{
printf("%s:%d:", tag, n);
for (int i = 0; i < n; i++)
printf(" %3d", a[i]);
putchar('\n');
}
You can do a lot of effective debugging with:
void mergesort(int a[],int n)
{
if (n < 2)
return;
int mid = n / 2;
int left[mid];
int right[n-mid];
dump_array("-->>mergesort()", n, a);
for (int i = 0; i < mid; i++)
left[i] = a[i];
dump_array("left", mid, left);
for (int i = mid; i < n; i++)
right[i-mid] = a[i];
dump_array("right", n - mid, right);
mergesort(left, mid);
dump_array("merged-L", mid, left);
mergesort(right, n - mid);
dump_array("merged-R", n - mid, right);
merge(a, left, right, mid, n - mid);
dump_array("<<--mergesort()", n, a);
}
In your code, the output with the tag right would show 0 or semi-random data for the last element, rather than what you're expecting. This would be a hint as to where the trouble is. Keep the dump_array() function around; it is a useful creature to have. It's a simple-minded version; you can invent more complex versions which outputs a newline at intermediate positions for long arrays, for example.
The issue is in the following code:
for(int i = mid; i < n-1; i++)
{
right[i-mid] = a[i];
}
It should be:
for(int i = mid; i < n; i++) // right should range from mid to n - 1 *inclusive*
{
right[i-mid] = a[i];
}
This is simple implementation of merge sort without any complications. Just pass the array pointer and total number of entires in the array.
void merge(int *a, int top)// Array pointer and max entries
{
int l1, k, l2, u1, u2, size = 1, i, j;
int *sa;
sa = (int *)calloc(top, sizeof(int));
while (size < top)
{
l1 = 0;
k = 0;
while (l1 + size < top)
{
l2 = l1 + size;
u1 = l2 - 1;
u2 = ((l2 + size - 1) < top ? l2 + size - 1 : top - 1);
for (i = l1, j = l2; i <= u1 && j <= u2; )// Merging
{
sa[k++] = a[i] <= a[j] ? a[i++] : a[j++];
}
for ( ; i <= u1; )
sa[k++] = a[i++];
for ( ; j <= u2; )
sa[k++] = a[j++];
l1 = u2 + 1;
}
for (i = l1; i < top; i++) // For the left outs of the process
sa[k++] = a[i];
for (i = 0; i < top; i++)
a[i] = sa[i];
size *= 2;
}
}

Resources