Binary Search Algo - c

I've implemented a binary search, the code is below, but I want to edit the code so that It print also the history of the algorithm
For exmaple:
Initial array:
1 1 2 4 4 5
Target element: 3
Search history: 2(2) 4(4)
No targets
#include <stdio.h>
int search(int array[], int x, int low, int high);
int main(void)
{
int array[] = {1, 1, 2, 4, 4, 5};
int n = sizeof(array) / sizeof(array[0]);
int x = 3;
printf("Initial array:\n");
for (int i = 0; i < n; i++)
{
printf("%d ", array[i]);
}
printf("\n");
printf("Target element: %d\n", x);
int result = search(array, x, 0, n - 1);
(result == -1) ? printf("No targets\n") : printf("Element found at index %d\n", result);
}
int search(int array[], int x, int low, int high)
{
if (high >= low)
{
int mid = low + (high - low) / 2;
if (array[mid] == x)
{
return mid;
}
if (array[mid] > x)
return search(array, x, low, high - 1);
else
return search(array, x, low + 1, high);
}
return -1;
}

well, even though the question is not clear to me by what do you mean history of algorithm, but I assumed you want to print the number (of times) your algorithm is failed to get the key.
If I guessed right, you could do it by using an extra variable, which holds the number, your algorithm miss the hit (or key).
#include <stdio.h>
int search(int array[], int x, int low, int high, int failed);
int main(void)
{
int array[] = {1, 1, 2, 4, 4, 5};
int n = sizeof(array) / sizeof(array[0]);
int x = 5;
int failed = 0;
printf("Initial array:\n");
for (int i = 0; i < n; i++)
{
printf("%d ", array[i]);
}
printf("\n");
printf("Target element: %d\n", x);
int result = search(array, x, 0, n - 1, failed);
(result == -1) ? printf("No targets\n") : printf("Element found at index %d\n", result);
}
int search(int array[], int x, int low, int high, int failed)
{
if (high >= low)
{
int mid = low + (high - low) / 2;
if (array[mid] == x)
{
return mid;
}else{
// number of times you, failed to hit the key (item to be searched)
failed += 1;
printf("%i(%i) ", failed, array[mid]);
}
if (array[mid] > x)
return search(array, x, low, high - 1, failed);
else
return search(array, x, low + 1, high, failed);
}
return -1;
}

Related

Quicksort with pointers causing segfault

I'm trying to take the standard quicksort algorithm and slightly modify it by taking the partition function and making it so that instead of taking the entire array, a low index and a high index, it takes in a pointer to the low'th element as well as how many elements I want to partition. However, I'm getting a segmentation fault and I can't figure it out. Thanks for the help.
#include <stdio.h>
void swap(int *a, int *b) {
int t = *a;
*a = *b;
*b = t;
}
int partition(int *array, int high) {
int pivot = array[high];
int i = 0;
for (int j = 0; j < high; j++) {
if (array[j] <= pivot) {
swap(&array[i++], &array[j]);
}
}
swap(&array[i], &array[high]);
return i;
}
void quickSort(int *array, int low, int high) {
if (low < high) {
int pi = partition(array + low, high - low);
quickSort(array, low, pi - 1);
quickSort(array, pi + 1, high);
}
}
void printArray(int array[], int size) {
for (int i = 0; i < size; ++i) {
printf("%d ", array[i]);
}
printf("\n");
}
int main() {
int data[] = {8, 7, 2, 1, 0, 9, 6};
int n = sizeof(data) / sizeof(data[0]);
printf("Unsorted Array\n");
printArray(data, n);
// perform quicksort on data
quickSort(data, 0, n - 1);
printf("Sorted array in ascending order: \n");
printArray(data, n);
}
Given the following in your code:
int pi = partition(array + low, high - low);
quickSort(array, low, pi - 1);
quickSort(array, pi + 1, high);
You're partitioning using a pointer-adjusted base (array+low), and segment pure length (high-low). That's fine if that is how your partition implementation works (most do). But you need to remember the resulting pivot location, pi, will be based on a position in that segment; not in the overall array. You need to adjust for that when recursing by putting back the original offset from whence that partition was configured:
int pi = partition(array + low, high - low);
quickSort(array, low, low + pi - 1); // <== LOOK
quickSort(array, low + pi + 1, high); // <== HERE
That change alone should get your implementation running. There are other ways to do this, and I'll update this answer with a couple of them when/if I find the time.
Alternate version of a pointer based quicksort using Hoare partition scheme:
void QuickSort(int *lo, int *hi)
{
int *i, *j;
int p, t;
if(lo >= hi)
return;
p = *(lo + (hi-lo)/2);
i = lo - 1;
j = hi + 1;
while (1){
while (*(++i) < p);
while (*(--j) > p);
if (i >= j)
break;
t = *i;
*i = *j;
*j = t;
}
QuickSort(lo, j);
QuickSort(j+1, hi);
}

Expression must have arithmetic type

While trying to write a code to find the intersection of two arrays,I came across a problem. I can't seem to modify a pointer inside a function.
Inside my find_intersection I get the error while doing the realloc function,compiler states that "counter" has no arithmetic value.
Any explanation on what went wrong here?
#include <stdio.h>
#include <stdlib.h>
int quick_sort(int*, int, int);
void swap(int*, int*);
int partition(int *, int, int);
int input_array_dyn(int*n);
int *find_intersection(int*, int*, int*, int, int,int *);
main()
{
int size1, size2, *counter, i=0;
int *arr1 = input_array_dyn(&size1);
int *arr2 = input_array_dyn(&size2);
quick_sort(arr1, 0, size1 - 1);
quick_sort(arr2, 0, size2 - 1);
int *arr3 = (int*)calloc(size2, sizeof(int));
arr3= find_intersection(arr1, arr2, arr3, size1, size2, &counter);
printf("The size of the new array is:%d\n", counter);
while (i < counter)
{
printf("%d\n", arr3[i]);
i++;
}
free(arr1);
free(arr2);
free(arr3);
}
int *find_intersection(int *arr1, int *arr2, int *arr3, int SA, int SB, int *counter)
{
int i = 0, j = 0, n = 0;
*counter = 0;
while (i < SA &&j < SB)
{
if (arr1[i] < arr2[j])
i++;
else if (arr2[j] < arr1[i])
j++;
else
{
arr3[n] = arr1[i];
i++;
n++;
j++;
}
}
counter = n;
arr3 = (int*)realloc(arr3, counter*sizeof(int));/*error here*/
return arr3;
}
int input_array_dyn(int*n)
{
int i;
int *a;
printf("Enter the size of the array:\n");
scanf("%d", n);
a = (int*)calloc(*n, sizeof(double));
assert(a);
printf("Enter the array elements:%d.\n", *n);
for (i = 0; i < *n; i++)
scanf("%d", a + i);
return a;
}
void swap(int* a, int* b)
{
int t = *a;
*a = *b;
*b = t;
}
int partition(int *arr, int low, int high)
{
int pivot = arr[high];
int i = (low - 1);
for (int j = low; j <= high - 1; j++)
{
if (arr[j] <= pivot)
{
i++;
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i + 1], &arr[high]);
return (i + 1);
}
int quick_sort(int *arr, int low, int high)
{
if (low < high)
{
int pi = partition(arr, low, high);
quick_sort(arr, low, pi - 1);
quick_sort(arr, pi + 1, high);
}
}
In find_intersection() counter is a pointer to an int. To change it's value you need to use *counter instead of counter.
return arr3; attempts to return a pointer to int while function is declared to return just int. counter is a pointer to an int while you are using it as an regular int setting to 0 and so on.

Recursive binary search function missing something? (C)

I'm trying to make a function that does a binary search on a sorted array. I've checked everything, and everything works correctly, except one thing:
If I don't put a return statement in the end of the function, not surrounded by If's, It won't build my program. If I put 'return 0', it would always return 0, no matter what. If I'll do the same with 1, it would always return 1, and I can't see where is my problem. Would love some help.
#include <stdio.h>
#define N 4
int search_matrix(int a[N][N], int x);
int binsearch(int a[], int x, int low, int high);
int main(){
int a[N][N];
printf("Please Enter Matrix : \n");
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
scanf("%d",&a[i][j]);
}//forj
}//fori
printf("Please enter x : \n");
int x;
scanf("%d",&x);
printf("%d\n",search_matrix(a,x));
return 0;
}
int search_matrix(int a[N][N], int x){
if(x>a[0][N-1]||x<a[N-1][0])
return 0;
int savedIndex=0;
for(int i=0;i<N;i++){
if(x>a[i][0]){
savedIndex=i;
break;
}
}//for
return(binsearch(a[savedIndex],x,0,N));
}//search_matrix
//------- THE PROBLEMATIC FUNCTION! ---------
int binsearch(int a[], int x, int low, int high) {
int mid;
if (low > high)
return 0;
mid = (low + high) / 2;
if (x == a[mid]) {
return 1;
} else if (x < a[mid]) {
binsearch(a, x, low, mid - 1);
} else {
binsearch(a, x, mid + 1, high);
}
}
Check it out:
#include<stdio.h>
#define N 4
int search_matrix(int a[N][N], int x);
int binsearch(int a[], int x, int low, int high);
int main(){
int a[N][N], i, j;
printf("Please Enter Matrix : \n");
for(i=0;i<N;i++){
for(j=0;j<N;j++){
scanf("%d",&a[i][j]);
}//forj
}//fori
printf("Please enter x : \n");
int x;
scanf("%d",&x);
printf("%d\n",search_matrix(a,x));
return 0;
}
int search_matrix(int a[N][N], int x){
if(x>a[0][N-1]||x<a[N-1][0])
return 0;
int savedIndex=0, i;
for(i=0;i<N;i++){
if(x>a[i][0]){
savedIndex=i;
break;
}
}//for
return(binsearch(a[savedIndex],x,0,N));
}//search_matrix
//------- THE PROBLEMATIC FUNCTION! ---------
int binsearch(int a[], int x, int low, int high) {
int mid;
if (low > high)
return 0;
mid = (low + high) / 2;
if (x == a[mid]) {
return 1;
} else if (x < a[mid]) {
binsearch(a, x, low, mid - 1);
} else {
binsearch(a, x, mid + 1, high);
}
}

returning boolean from a recursive binary search in C

I am trying to implement a recursive binary search in C. I am using the CS50 library to define bool as a type. My code will find the inputted value in a test array. However when i check the returned value r with an if statement it is usually returning false, even though the number is found.My code is as follows:
#include <stdio.h>
#include <cs50.h>
bool binarysearch(int value, int values [], int n, int lo, int hi);
int main(void)
{
// test array of 6 values sorted.
int values[] = {1 , 2, 3, 4 , 5, 6};
int n = 6;
int hi = values[n-1];
int lo = values[0];
// input from user
printf("What number\n");
int value = GetInt();
//search for value in test arary
bool r = binarysearch(value,values,n,lo,hi);
if (!r)
{
printf("not right\n");
return 1;
}
return 0;
}
bool binarysearch(int value, int values [], int n, int lo, int hi)
{
int mid;
mid = (lo + hi)/2;
// condition to avoid indexing error
if (((mid == 0) || (mid == n-1)) && (values[mid] != value) )
{
return false;
}
//check if value is at mid index in test array
if (values[mid] == value)
{
printf("Key Found\n");
return true;
}
// check right half of array
else if(value > values[mid])
{
binarysearch(value, values,n, mid+1, hi);
}
// check left half of array
else if(value <values[mid])
{
binarysearch(value, values,n,lo, mid-1);
}
return false;
}
This example will perform a binary search and return a boolean, similar to your code but the algorithm has to be correct.
#include <stdio.h>
#include <stdbool.h>
bool binarysearch(int value, int values[], int n, int lo, int hi) {
int mid = (hi + lo) / 2;
if (lo <= hi) {
if (values[mid] == value) {
printf("Key found at index %d \n", mid);
return true;
}
else if (values[mid] > value)
return binarysearch(value, values, n, lo, mid);
else
return binarysearch(value, values, n, mid + 1, hi);;
}
else return 0;
}
main() {
int i, n, value;
int values[] = {1, 2, 3, 4, 5, 6};
int hi = values[n - 1];
int lo = values[0];
printf("What number? \n");
scanf("%d", &value);
if (!binarysearch(value, values, n, 0, 5))
printf("Number not present in array\n");
}
You can try this algorithm online using random integer between 1 and 13 making it a 50 % chance of finding the number if you follow the link.

Quicksort implementation in C using first element as pivot

I am a complete beginner to stackoverflow and this is my first post. Please forgive if this is not the correct place to post these kinds of queries. I have written code for the Quicksort algorithm, based on the algorithm given in the Algorithms course in Coursera(It is not for any assignments though).
Basically, there are two functions Quicksort which is called recursively and partition() function that returns the index of the pivot. I select the pivot as the first element of the array every time. I checked the partition() function and it works fine but the array is not sorted even after I call the Quicksort() function.
Any help is appreciated. Thanks.
#include <stdio.h>
void swap(int *p, int i, int j)
{
int temp = *(p+i);
*(p+i) = *(p+j);
*(p+j) = temp;
}
int partition(int *q, int l, int r)
{
int i = l+1, j;
int p = l;
int len = r-l +1;
for (j = l+1; j < len; j++)
{
/*printf("%d \n", j);*/
if ( *(q+j) < *(q+p) )
{
swap(q, i, j);
i += 1;
}
}
swap(q, l, i-1);
/*printf("%d", i-1);*/
return (i-1);
}
void quicksort(int *ptr, int low, int high)
{
if (low < high)
{
int p = partition(ptr, low, high);
printf("%d\n", p);
quicksort(ptr, low, p);
quicksort(ptr, p+1, high);
}
}
int main(){
int i;
int a[] = {3, 8, 2, 5, 1, 4, 7, 6};
int len = sizeof(a)/sizeof(a[0]);
for ( i = 0; i < len; ++i)
{
printf("%d ", a[i]);
}
printf("\n");
int *ptr = a;
quicksort(ptr, 0, len-1);
for (i = 0; i < sizeof(a)/sizeof(a[0]); ++i)
{
printf("%d ", a[i]);
}
printf("\n");
return 0;
}
2 corrections.
Small one: Change 3rd line inside if block in QuickSort function
from
quicksort(ptr, low, p);
to
quicksort(ptr, low, p-1);
This will improve performance.
Main error:
Your partition function is wrong. Specifically the loop where j runs from l+1 to r-l+1, because, r-l+1 can be less than l+1
I'll write the partition function for you if you want (post a comment if you face any problem with that) though I'd advice you to do it yourself.
EDIT:
A possible partition function:
int partition(int *q, int l, int r){
int i,j;
int p = *(q + l);
for(i = l + 1, j = r; ;){
while(*(q + i) <= p)
i++;
while(*(q + j) >= p)
j--;
if(i >= j)
break;
swap(q, i, j);
}
return i;
}
Changes noted in comments.
int partition(int *q, int l, int r)
{
int i = l+1, j;
int p = l;
/* fix: int len = r-l+1; is not used */
for (j = l+1; j <= r; j++) /* fix: j <= r */
{
if ( *(q+j) <= *(q+p) ) /* fix: <= */
{
swap(q, i, j);
i += 1;
}
}
swap(q, l, i-1);
return (i-1);
}
void quicksort(int *ptr, int low, int high)
{
if (low < high)
{
int p = partition(ptr, low, high);
quicksort(ptr, low, p-1); /* optimization: p-1 */
quicksort(ptr, p+1, high);
}
}
If interested, Hoare partition scheme is faster. If you switch to this, don't forget to change the two quicksort calls to quicksort(lo, p) and quicksort(p+1, hi) ). You might want to change the Hoare pivot to pivot = A[(lo+hi)/2], which will avoid worst case issue with sorted or reverse sorted array.
http://en.wikipedia.org/wiki/Quicksort#Hoare_partition_scheme

Resources