Click here to Skip to main content
15,887,596 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I want to inplement a binary search algorithm of an order array.
C++
int Array::Search(int target, int* start, int* tail){
	if(start>tail){
		cout<<"not find"<<endl;
		return -1;
	}
	int offsetMid= (tail-start)/2/sizeof(int);//by unit of int
	cout<<"offset: "<<offsetMid<<"  mid " <<*(start+offsetMid)<<endl;
	cout<<start<<" " <<tail<<endl;
	if(target == *(start+offsetMid) ){
		cout<<"mid"<<endl;
		return (offsetMid+1);
	}
	if(*(start+offsetMid) > target){
		cout<<"left"<<endl;
		tail = start+(offsetMid-1)*sizeof(int);
		return Search(target, start, tail);
	}
	if(*(start+offsetMid) < target){
		cout<<"right"<<endl;
		start = start+(offsetMid)*sizeof(int);
		return Search(target,start , tail);
	}
}

But it doesn't work, I know the parameter of the func should better be the index of the array rather than a pointor, I just want to try this way. The compiler I used is
gcc version 6.2.1 20160916 (Red Hat 6.2.1-2) (GCC) 
Another weird thing
int offsetMid= (tail-start)/2/sizeof(int);//by unit of int
Both tail and start are the type of int*, but the difference of them is counted by byte, so I must divide it by sizeof(int) to get the offset value.
if(*(start+offsetMid) > target)
But when I want to plus the offset value to the start address to get the value in a particular position, I shouldn't time it by sizeof(int).WHY??

What I have tried:

I have tried to print the addresses of both the start and end points, and the value of element in the middle position.
Posted
Updated 5-Feb-17 20:59pm

The problem I see is you're adjusting your pointers by sizeof(int). As they are already declared as int pointers, any additions or subtractions to the pointers are adjusted by sizeof(int) by the compiler.
i.e.
C++
int* pi = //a valid pointer;
void* pv = (void*)pi;

bool bAdj = (pi + 1) == (pv + sizeof(int)); // returns true
Both tail and start are the type of int*, but the difference of them is counted by byte, so I must divide it by sizeof(int) to get the offset value.
Wrong!! This is defined by the language (does not matter which compiler you use). The subtraction of these two pointers will return the number of ints that will fit in here.
 
Share this answer
 
Comments
alalba 2-Feb-17 22:15pm    
At first, I also thought this like u , until I encounter this problem. First, if I don't adjust the pointer by sizeof(int), the length of the array I got for the expression (tail-start) is 4 times than it actually is. Second if I use the value in my code "int offsetMid= (tail-start)/2/sizeof(int);//by unit of int" without adjusted by sizeof(int), the value of *(start + offsetMid) will get me a value that not exist in the array,cause offsetMid is 4 times larger than it should be
Stefan_Lang 6-Feb-17 3:01am    
+5 you are indeed correct.
I added more info to help the OP as a separate solution. I would have posted is as a comment here, but I preferred the benefit of code formatting.
When you don't understand what your code is doing or why it does what it does, the answer is debugger.
Use the debugger to see what your code is doing. It allow you to execute lines 1 by 1 and to inspect variables as it execute, it is an incredible learning tool.

Debugger - Wikipedia, the free encyclopedia[^]

The debugger is here to show you what your code is doing and your task is to compare with what it should do.
There is no magic in the debugger, it don't find bugs, it just help you to. When the code don't do what is expected, you are close to a bug.
 
Share this answer
 
Comments
alalba 3-Feb-17 10:44am    
thank you for your advise, I will try to learn how to use debugger.
tl;dr:
you might want to check your test code that calls the Search function - maybe the error is also there!

Long version:

This is not a stand-alone solution, but simply a verification for solution1. I'm only using the solution form for the sake of code formatting:

Using this test code, I could verify that solution 1 is correct:
C++
#include <iostream>
using std::cout;
using std::endl;

int Search(int target, int* start, int* tail){
   if(start>tail){
      cout<<"not find"<<endl;
      return -1;
   }
   int offsetMid= (tail-start)/2/*/sizeof(int)*/;//by unit of int
   cout<<"offset: "<<offsetMid<<"  mid " <<*(start+offsetMid)<<endl;
   cout<<start<<" " <<tail<<endl;
   if(target == *(start+offsetMid) ){
      cout<<"mid"<<endl;
      return (offsetMid+1);
   }
   if(*(start+offsetMid) > target){
      cout<<"left"<<endl;
      tail = start+(offsetMid-1)/**sizeof(int)*/;
      return Search(target, start, tail);
   }
   if(*(start+offsetMid) < target){
      cout<<"right"<<endl;
      start = start+(offsetMid)/**sizeof(int)*/;
      return Search(target,start , tail);
   }
}
void test_Search() {
   int arr[] = {2, 5, 6, 14, 44, 51, 94, 221, 356, 444};
   int* start = arr;
   size_t length = sizeof(arr)/sizeof(int);
   cout << length << endl;
   int *end = start + length;
   int s = Search(6, start, end);
   cout << s << endl;
}

This produces the output:
10
offset: 5  mid 51
0033FA60 0033FA88
left
offset: 2  mid 6
0033FA60 0033FA70
mid
3

Note how in the test function I calculated the end address of the array by explicitely dividing the size of the array by sizeof(int). This is necessary, because adding a number to an int pointer imlpicitely multiplies the address offset by sizeof(int): Suspect that may be the reason why you could not reproduce the expected results when following the advice from solution 1.

P.S.: The compiler complained with the following warning which I did not bother to fix - but you should:
Quote:
warning C4715: 'Search' : not all control paths return a value

It's easy enough to spot, but if you don't, here's a tip: what will happen if you search in the above array for, say, the value 11?
 
Share this answer
 
v2
Comments
Midi_Mick 6-Feb-17 3:10am    
Nice example.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900