I'm junior in C language and algorithms.
I try to use recursion for binary search and I can't understand how to check if number doesn't exist in array.
Here my code:
#include <stdio.h>
#define SIZE 15
#define midpoint(start, end) (start + end) / 2
void fill_array(int array[]);
int find(int target, int array[], int start, int end);
int main() {
int array[SIZE];
fill_array(array);
return find(2, array, 0, SIZE);
}
void fill_array(int array[]) { //here I just fill array
for (int i = 0, number = 0; i <= SIZE; ++i) {
array[i] = number++;
number++;
}
}
int find(int target, int array[], int start, int end) {
int mid;
mid = midpoint(start, end);
if (target > array[mid]) {
find(target, array, mid + 1, end);
}
if (target < array[mid]) {
find(target, array, start, mid - 1);
}
if (target == array[mid]) {
printf("%d\n", mid);
}
}
I want to return (-1) if number doesn't exist in array.
There are multiple issues in your code:
Defining midpoint() as a macro is error prone. Your definition is not properly parenthesized, it should read:
#define midpoint(start, end) (((start) + (end)) / 2)
Written as half the sum, it actually would invoke undefined behavior for large values of start and end, a much safer version would be start + (end - start) / 2, but should not be used in a macro as it evaluates start twice. Just write the code in the function directly.
Your initialization function iterates one step too far, the loop should read:
for (int i = 0, number = 0; i < SIZE; i++) {
array[i] = number;
number += 2;
}
find() should indeed return the index of the value found or -1 if not found. You do not return anything. make it return -1 upon failure and the value of the recursive call when recursing.
the arguments to find are start, the starting index of the range, included in the search, and end the upper bound, excluded from the search. You should not pass mid - 1 when recursing on the left part.
Here is a corrected version:
#include <stdio.h>
#define SIZE 15
void fill_array(int array[], int size) {
// here I just fill array with even numbers
for (int i = 0, number = 0; i < SIZE; i++) {
array[i] = number;
number += 2;
}
}
int find(int target, const int array[], int start, int end) {
if (start >= end) {
// empty range: not found
return -1;
}
int mid = start + (end - start) / 2;
if (target == array[mid]) {
return mid;
}
if (target > array[mid]) {
return find(target, array, mid + 1, end);
} else {
return find(target, array, start, mid);
}
}
void locate(int value, const int array[], int size) {
int res = find(value, array, 0, size);
if (res < 0) {
printf("%d was not found in the array\n", value);
} else {
printf("%d was found at offset %d\n", value, res);
}
}
int main(void) {
int array[SIZE];
fill_array(array, SIZE);
locate(1, array, SIZE);
locate(2, array, SIZE);
return 0;
}
Output:
1 was not found in the array
2 was found at offset 1
Note that find() can be implemented as a loop with less code:
int find(int target, const int array[], int start, int end) {
while (start < end) {
int mid = start + (end - start) / 2;
if (target == array[mid]) {
return mid;
}
if (target > array[mid]) {
start = mid + 1;
} else {
end = mid;
}
}
return -1;
}
I have written a BinarySearch C code for you to inspect and see where is your problem.
This part: int BinarySearch is doing BinarySearch via loops,
This part: int BinarySearchRec is doing BinarySearch via recursion.
#include <stdio.h>
#include <stdlib.h>
int BinarySearch(int*,int,int);
int BinarySearchRec(int*,int,int,int);
int main(void){
int length;
int searchElement;
int* list;
printf("Enter the length of the list\n");
scanf("%d",&length);
list = malloc(length*sizeof(int));
printf("Enter the search element for this list");
scanf("%d",&searchElement);
printf("Enter the elements for this list\n");
for(int i=0;i<length;i++){
scanf("%d",list+i);
}
int result1 = BinarySearch(list,length,searchElement);
int result2 = BinarySearchRec(list,0,length-1,searchElement);
printf("Result from loopy BinarySearch : %d\n",result1);
printf("Result from recursive BinarySearch: %d\n",result2);
return 0;
}
int BinarySearch(int* list, int length, int searchElement){
int found=0;
int min = 0;
int max = length-1;
int mid=0;
while(found != 1 && max > min){
mid = (max+min)/2;
if(searchElement == list[mid]){
found = 1;
}else if(searchElement > list[mid]){
min = mid+1;
}else if(searchElement < list[mid]){
max = mid;
}
}
if(max > min){
return mid;
} else{
return -1;
}
}
int BinarySearchRec(int* list,int min,int max,int searchElement){
int mid = (min+max)/2;
if(max > min){
if(searchElement == list[mid]){
return mid;
}else{
if(searchElement < list[mid]){
return BinarySearchRec(list,min,mid,searchElement);
}else if(searchElement > list[mid]){
min = mid+1;
return BinarySearchRec(list,mid+1,max,searchElement);
}
}
}else{
return -1;
}
}
Related
So I have been tasked from school with writing a function that gets an int size parameter, an array of integers and an int flag, and returns an array of pointers, that holds pointers to the cells of the original int array in a sorted manner (ascending if flag==1, else descending).
I wrote it basically on the principle of merge sort, but for some reason I am getting a runtime error that occurs when the program tries to execute line 123 (free a temp int** array)
any idea why it happens and if its fixable?
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#define SIZE 100
int **pointerSort(int *arr, unsigned int size, int ascend_flag);
void ptrMerge(int arr[], int start, int mid, int end, int *ptrArr[], int flag);
void pmergeSort(int arr[], int start, int end, int *ptrArr[], int flag);
void main() {
unsigned int size, i;
int arr[SIZE];
int **pointers;
int ascend_flag;
printf("Please enter the number of items:\n");
scanf("%u", &size);
for (i = 0; i < size; i++)
scanf("%d", &arr[i]);
scanf("%d", &ascend_flag);
pointers = pointerSort(arr, size, ascend_flag);
printf("The sorted array:\n"); //Print the sorted array
//printPointers(pointers, size);
for (i = 0; i < size; i++)
printf("d%\t%d", *pointers[i], pointers[i]);
free(pointers);
}
int **pointerSort(int *arr, unsigned int size, int ascend_flag) {
int **sortedArr;
sortedArr = (int**)malloc(size * sizeof(int*));
pmergeSort(arr, 0, size - 1, sortedArr, ascend_flag);
return sortedArr;
}
void pmergeSort(int arr[], int start, int end, int *ptrArr[], int flag) {
if (start < end) {
int mid = (start + end) / 2;
pmergeSort(arr, start, mid, ptrArr, flag);
pmergeSort(arr, mid + 1, end, ptrArr, flag);
ptrMerge(arr, start, mid, end, ptrArr, flag);
}
}
void ptrMerge(int arr[], int start, int mid, int end, int *ptrArr[], int flag) {
int i, k = 0;
int p = start, q = mid + 1;
int **tempArr;
tempArr = (int**)malloc((end - start + 1) * sizeof(int*));
for (i = start; i <= end; i++) {
if (arr[p] < arr[q]) {
tempArr[k] = &arr[p];
k++;
p++;
} else { //(arr[p] > arr[q])
tempArr[k] = &arr[q];
k++;
q++;
}
}
while (p <= mid) {
tempArr[k] = &arr[p];
k++;
p++;
}
while (q <= end) {
tempArr[k] = &arr[q];
k++;
p++;
}
if (flag == 1) {
for (i = 0; i < k; i++)
ptrArr[start] = tempArr[i];
start++;
}
} else {
for (i = k - 1; i >= start; i--) {
ptrArr[start] = tempArr[i];
start++;
}
}
for (i = 0; i < k; i++)
printf("%x\t%d\n", ptrArr[i], *ptrArr[i]);
printf("\n");
free(tempArr);
}
You get a segmentation fault because the ptrMerge function corrupts the memory by writing past the end of the tempArr allocated array.
The first loop iterates end - start + 1 times, potentially accessing arr beyond the end of the slices.
The loop continues until p >= mid and q >= end, writing to tempArr[k] with k greater or equal to the number of elements allocated with malloc().
The logic is flawed: you compare the elements of arr at offsets p and q instead of indirecting through the array ptrArr.
Here is a modified version:
int **pointerSort(int *arr, int size, int ascend_flag) {
int **sortedArr = (int**)malloc(size * sizeof(int*));
for (int i = 0; i < size; i++) {
sortedArr[i] = &arr[i];
}
pmergeSort(sortedArr, 0, size - 1, ascend_flag);
return sortedArr;
}
void pmergeSort(int *ptrArr[], int start, int end, int flag) {
if (start < end) {
int mid = start + (end - start) / 2;
pmergeSort(ptrArr, start, mid, flag);
pmergeSort(ptrArr, mid + 1, end, flag);
ptrMerge(ptrArr, start, mid, end, flag);
}
}
void ptrMerge(int *ptrArr[], int start, int mid, int end, int flag) {
int i, k, n = end - start + 1;
int p = start, q = mid + 1;
int **tempArr = (int**)malloc(n * sizeof(int*));
for (k = 0; k < n; k++) {
if (p <= mid && (q >= end || *ptrArr[p] <= *ptrArr[q])) {
tempArr[k] = ptrArr[p++];
} else {
tempArr[k] = ptrArr[q++];
}
}
if (flag == 1) {
for (k = 0; k < n; k++)
ptrArr[start + k] = tempArr[k];
}
} else {
for (k = 0; k < n; k++) {
ptrArr[end - k] = tempArr[k];
}
}
free(tempArr);
}
Also note that main() must be defined with a return type int and the loop that prints the values is broken. It should read:
for (i = 0; i < size; i++)
printf("%d\t", *pointers[i]);
printf("\n");
So you should use :
int main(void)
In this while q is never updated so i guess infinite loop?
while (q <= end)
{
tempArr[k] = &arr[q];
k++;
p++;
}
Can you provide me your inputs and output you want?
I have tried your code and i'm not getting your error.
I need write a function that return the longest sequence of either 1s or 0s for a given array (of 1s and 0s). It also needs to return in a pointer the index at which this longest sequence begins.
Say for example I have the array
a[]={1, 0, 0, 0, 1, 0, 0, 1}
The function returns
3, 1
where 3 is the longest sequence (in this case of 0s) and 1 is the index at which it begins.
What I did was this:
int longestSequence(int a[], int n, int* begin)
{
int count=1;
int max_length=1;
int i;
for(i=1;i<n;i++)
{
if(a[i]==a[i-1])
{
count+=1;
}
else if (count>max_length)
{
max_length=count;
count=1;
}
else
{
count=1;
}
}
if(count>max_length)
{
max_length=count;
}
return max_length;
}
I tried a couple of examples to see if the function returns the longest sequence and it works. However, I'm unable to find a way to return the right index at which it begins.
Any help would be much appreciated.
try this:
int longestSequence(int a[], int n, int *begin){
int i, count, max_length = 1;
*begin = 0;
for(i = 0; i + max_length < n; i += count){
for(count = 1; i + count < n && a[i] == a[i + count]; ++count)
;
if(count > max_length){
max_length = count;
*begin = i;
}
}
return max_length;
}
your code nearly works.
add max_index = i - count; just below max_length=count; (both places)
also define int max_index; near the top.
Try this small edit:
int longestSequence(int a[], int n, int* begin)
{
int count=1;
int max_length=1;
int out_index = 0;
int i;
for(i=1;i<n;i++)
{
if(a[i]==a[i-1])
{
count+=1;
}
else if (count>max_length)
{
max_length=count;
out_index = i - count;
count=1;
}
else
{
count=1;
}
}
if(count>max_length)
{
max_length=count;
out_index = i - count;
}
*begin = out_index;
return max_length;
}
I got the task to write a recursive selectionsort algorithm, which i did.
The algorithm works fine until i increase the array size to more than 150 elements.
After i increased the elements, the algorithm stops working and exits with a "strange" (-1073741571 (0xC00000FD)) exit code.
I guess that somewhere i exceed the data range. But even after staring an hour at my code i cannot find where. Using the debugging fuction does not give me any hint.
Can someone help me why this code isn't working with more than 150 elements?
#include <stdio.h>
#include <string.h>
#include <limits.h>
#define MAX 500
// print the array and count the number of reoccurring characters and print it.
void ausgabe(int *array, size_t size)
{
int i;
int prev_char = INT_MAX, cur_char, count = 0;
for (i = 0; i < size; i++)
{
cur_char = array[i];
if (cur_char == prev_char)
{
printf("%c", array[i]);
prev_char = cur_char;
count++;
}
else
{
printf(" Count = %i\n%c", count, array[i]);
prev_char = cur_char;
count = 0;
}
}
printf(" Count = %i", count);
}
//Fill the array with characters from A to Z and start over
void fill_field(int *array, size_t size)
{
int i, j = 0;
for (i = 0; i < size; i++)
{
if ( j > 25)
j = 0;
array[i] = 65 + j++;
}
}
//Recursive selectionsort algorithm.
void selection_sort(int *source, size_t size)
{
static int min = INT_MAX, position = 0, start_pos = 0, temp, found;
if ( position < size)
{
if (min > source[position])
{
min = source[position];
found = position;
}
position++;
selection_sort(source, size);
}
else
{
temp = source[start_pos];
source[start_pos] = min;
source[found] = temp;
position = start_pos + 1;
start_pos++;
min = INT_MAX;
if ( position < size )
selection_sort(source, size);
}
}
int main(void)
{
int array[MAX];
fill_field(array, MAX);
ausgabe(array, MAX);
selection_sort(array, MAX);
ausgabe(array, MAX);
return 0;
}
So my recursion selection sort calls two functions max_index and the swap and at the same time it should recursively swap the stuff, but for some reason it seems to break and explode into fire for certain arrays like the one I have set in main. Does anyone know why this is so? Can someone explain and show me why this isn't working?
int max_index(int arr[], int start, int end)
{
if ( start >= end ) {
return 0;
}
else if ( end - start == 1 ) {
return start;
}
else {
int greatest = max_index(arr, start + 1, end);
if( arr[start] > arr[greatest])
{
return start;
}
else
{
return greatest;
}
}
}
void swap(int arr[], int i, int j) {
int temp;
temp = arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
void rec_ssort(int arr[], int len) {
int start = 0;
int last = len - 1;
//int n = len;
int maxindex = max_index(arr, start, last);
//if(arr[maxindex]>0 || arr[maxindex]<n)
{
if(arr[maxindex]>arr[last])
{
swap(arr, maxindex, last);
return rec_ssort(arr, last);
}
if(arr[maxindex] == arr[last])
{
return rec_ssort(arr, last);
}
}
}
int main(void)
{
int i = 0;
int arr[7] = {2,3,4,1,5,6,7};
int start = 0;
int end = 7;
int stuff = 5;
rec_ssort(arr, end);
for(i = 0; i<7; i++)
printf("%d\n", arr[i]);
}
All recursive methods need a base case (to exit the recursion). Additionally it helps if you can see progress on the recursion happening at every step. Note that you weren't recursing when the maxindex pointed to a value less than last.
This is one way to correct your issues in rec_ssort:
void rec_ssort(int arr[], int len) {
// base case: if we're looking at an empty array we're done.
if (len <= 0) return;
int last = len - 1;
int maxindex = max_index(arr, 0, last);
if (arr[maxindex] > arr[last]) {
swap(arr, maxindex, last);
}
// recursively call with a shorter len
rec_ssort(arr, last);
}
I am trying to implement a simple tournament in C.
#include <stdio.h>
int main(void) {
int tourn[100], n, i;
printf("Give n:");
scanf("%d", &n);
printf("\n n = %d \n", n);
for(i = n; i <= (2*n)-1; i++)
scanf("%d", &tourn[i]);
build(tourn, n);
printf("\n Max = %d \n",tourn[1]);
printf("\n Next Max = %d \n",nextmax(tourn, n));
}
void build(int tourn[], int n) {
int i;
for(i = 2*n-2; i > 1; i = i-2)
tourn[i/2] = max(tourn[i], tourn[i+1]);
}
int nextmax(int tourn[],int n) {
int i = 2;
int next;
next = min(tourn[2], tourn[3]);
while(i <= 2*n-1) {
if(tourn[i] > tourn[i+1]) {
next = max(tourn[i+1], next);
i = 2*i;
}
else {
next = max(tourn[i], next);
i = 2*(i+1);
}
}
return(next);
}
int max(int i,int j) {
if(i > j)
return i;
else
return j;
}
int min(int i,int j) {
if(i < j)
return i;
else
return j;
}
The output for n = 5 and
1 2 3 4 5
is
Max = 4195048
Next Max = 32588
and this output varies each time by a small amount!
if I place a test printf command before the build function, it doesn't execute.
Can someone find the error/explain the output?
Thanks :)
Your code seems pretty broken to me. you don't mind to address beyond your array boundaries, which is a good way of producing random results:
while(i <= 2*n-1){
if(tourn[i]>tourn[i+1]){
next = max(tourn[i+1],next);
i=2*i;
} else {
next = max(tourn[i],next);
i=2*(i+1);
}
}
Your (logical) array is of size 2n. if i reaches the "highest" value, you test tourn[i + 1], which is tourn[2n].