473,417 Members | 1,626 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,417 software developers and data experts.

Binary search class: small problem retrieving the last element in the ordered array

Hello,

I have an array of strings and need to find the matching one with the
fastest possible code. I decided to order the array and then write a binary
search algo.
What I came up with is the following. I noticed that if I set:

int upper = strings.GetUpperBound(0);

I never match the last element in the array (i.e. "iii")

while if I set:

int upper = strings.GetUpperBound(0) + 1;

I'm able to match also the last element in the array.
The problem is that I think upper should indeed be equal to
strings.GetUpperBound(0).
Is there something I'm missing??? Is the algo wrong or missing something???
using System;

namespace TestApplication
{
class BinarySearchClass
{
static void Main(string[] args)
{
string[] strings = new string[]{"aaa", "bbb", "ccc", "ddd", "eee", "fff",
"ggg", "hhh", "iii"};

BinarySearchClass search = new BinarySearchClass();

int res = search.FindString(strings, "iii");

Console.Read();
}

public int FindString(string[] strings, string str)
{
int lower = strings.GetLowerBound(0);
int upper = strings.GetUpperBound(0);

return this.BinarySearch(strings, str, lower, upper);
}

public int BinarySearch(string[] strings, string str, int lowerbound, int
upperbound)
{
int pos = ((upperbound - lowerbound) / 2) + lowerbound;

int res = string.Compare(strings[pos], str);

if(res 0)
{
pos = this.BinarySearch(strings, str, lowerbound, pos);
}
else if(res < 0)
{
pos = this.BinarySearch(strings, str, pos, upperbound);
}
return pos;
}
}
}

Regards,
Bob Rock


Dec 28 '06 #1
11 2394
You do need set upper = strings.GetUpperBound(0) + 1. This is because when
you
divide by 2, you truncate and thus can never attain the end of the array,
unless you add
1.

I don't see why your algorithm does not loop forever if there is no match in
the array. You
should check to see that the new pos is not equal to either the upper or
lower bound. If it is, the binary search is done, even if the element is
not found. Continuing to
call BinarySearch will just calculate the same pos forever.

You should *seriously* consider using the .Net library's BinarySearch
instead
of writing your own, IMHO.

"Bob Rock" <ye********************@hotmail.com.nospamwrote in message
news:O7**************@TK2MSFTNGP06.phx.gbl...
Hello,

I have an array of strings and need to find the matching one with the
fastest possible code. I decided to order the array and then write a
binary search algo.
What I came up with is the following. I noticed that if I set:

int upper = strings.GetUpperBound(0);

I never match the last element in the array (i.e. "iii")

while if I set:

int upper = strings.GetUpperBound(0) + 1;

I'm able to match also the last element in the array.
The problem is that I think upper should indeed be equal to
strings.GetUpperBound(0).
Is there something I'm missing??? Is the algo wrong or missing
something???
using System;

namespace TestApplication
{
class BinarySearchClass
{
static void Main(string[] args)
{
string[] strings = new string[]{"aaa", "bbb", "ccc", "ddd", "eee",
"fff", "ggg", "hhh", "iii"};

BinarySearchClass search = new BinarySearchClass();

int res = search.FindString(strings, "iii");

Console.Read();
}

public int FindString(string[] strings, string str)
{
int lower = strings.GetLowerBound(0);
int upper = strings.GetUpperBound(0);

return this.BinarySearch(strings, str, lower, upper);
}

public int BinarySearch(string[] strings, string str, int lowerbound, int
upperbound)
{
int pos = ((upperbound - lowerbound) / 2) + lowerbound;

int res = string.Compare(strings[pos], str);

if(res 0)
{
pos = this.BinarySearch(strings, str, lowerbound, pos);
}
else if(res < 0)
{
pos = this.BinarySearch(strings, str, pos, upperbound);
}
return pos;
}
}
}

Regards,
Bob Rock


Dec 29 '06 #2
Bob Rock wrote:
Hello,

I have an array of strings and need to find the matching one with the
fastest possible code. I decided to order the array and then write a binary
search algo.
What I came up with is the following. I noticed that if I set:

int upper = strings.GetUpperBound(0);

I never match the last element in the array (i.e. "iii")

while if I set:

int upper = strings.GetUpperBound(0) + 1;

I'm able to match also the last element in the array.
The problem is that I think upper should indeed be equal to
strings.GetUpperBound(0).
Is there something I'm missing??? Is the algo wrong or missing something???
using System;

namespace TestApplication
{
class BinarySearchClass
{
static void Main(string[] args)
{
string[] strings = new string[]{"aaa", "bbb", "ccc", "ddd", "eee", "fff",
"ggg", "hhh", "iii"};

BinarySearchClass search = new BinarySearchClass();

int res = search.FindString(strings, "iii");

Console.Read();
}

public int FindString(string[] strings, string str)
{
int lower = strings.GetLowerBound(0);
int upper = strings.GetUpperBound(0);

return this.BinarySearch(strings, str, lower, upper);
}

public int BinarySearch(string[] strings, string str, int lowerbound, int
upperbound)
{
int pos = ((upperbound - lowerbound) / 2) + lowerbound;

int res = string.Compare(strings[pos], str);

if(res 0)
{
pos = this.BinarySearch(strings, str, lowerbound, pos);
}
else if(res < 0)
{
pos = this.BinarySearch(strings, str, pos, upperbound);
}
return pos;
}
}
}

Regards,
Bob Rock

Bob, how about this..

int pos= Array.BinarySearch<string>(strings, "iii");

J.W.
Dec 29 '06 #3
Yes, the code as I provided it does loop forever if there is no match.
I coded my own algo because I don't want BinarySearch to order by array
every single time, as it indeed does. The array is already ordered.
As for the stop condition when the searched string is not in the array,
upper == lower does not guarantee the search from stopping.
For example, if the searched string is lexicographically bigger than any
other string in the array, lower never gets to be equal to upper and the
algo goes on in a loop until a until a stack overflow exception is rised.

I wonder how I should write the stop condition to handle any situation.
Bob Rock
"Fred Mellender" <no****************@frontiernet.netwrote in message
news:aR*****************@news02.roc.ny...
You do need set upper = strings.GetUpperBound(0) + 1. This is because
when you
divide by 2, you truncate and thus can never attain the end of the array,
unless you add
1.

I don't see why your algorithm does not loop forever if there is no match
in the array. You
should check to see that the new pos is not equal to either the upper or
lower bound. If it is, the binary search is done, even if the element is
not found. Continuing to
call BinarySearch will just calculate the same pos forever.

You should *seriously* consider using the .Net library's BinarySearch
instead
of writing your own, IMHO.

Dec 29 '06 #4
Yes, the problem is that BinarySearch orders the array everytime while the
array in *already* ordered. I was trying to be more efficient by writing my
own code.

Bob Rock

Bob, how about this..

int pos= Array.BinarySearch<string>(strings, "iii");

J.W.

Dec 29 '06 #5
Bob Rock wrote:
Yes, the problem is that BinarySearch orders the array everytime
while the array in *already* ordered. I was trying to be more
efficient by writing my own code.
Not so. Array.BinarySearch requires that the array is already sorted - it
does not itself sort the array. You're re-inventing a wheel that's already
built for you in the framework.

-cd
Dec 29 '06 #6
Bob Rock wrote:
Yes, the code as I provided it does loop forever if there is no match.
I coded my own algo because I don't want BinarySearch to order by array
every single time, as it indeed does. The array is already ordered.
As for the stop condition when the searched string is not in the array,
upper == lower does not guarantee the search from stopping.
For example, if the searched string is lexicographically bigger than any
other string in the array, lower never gets to be equal to upper and the
algo goes on in a loop until a until a stack overflow exception is rised.

I wonder how I should write the stop condition to handle any situation.

when (upperbound - lowerbound)==1, you should just check two elements to
see if there is a match..

Your condition :

int pos = ((upperbound - lowerbound) / 2) + lowerbound;

if the upperbound =2, and lowerbound=1, then you get pos=1, and when you
go to the next loop, you are getting the same condition.

Have you did some experiment that you can save time by doing your own
binary search.

Bob Rock
"Fred Mellender" <no****************@frontiernet.netwrote in message
news:aR*****************@news02.roc.ny...
>You do need set upper = strings.GetUpperBound(0) + 1. This is because
when you
divide by 2, you truncate and thus can never attain the end of the array,
unless you add
1.

I don't see why your algorithm does not loop forever if there is no match
in the array. You
should check to see that the new pos is not equal to either the upper or
lower bound. If it is, the binary search is done, even if the element is
not found. Continuing to
call BinarySearch will just calculate the same pos forever.

You should *seriously* consider using the .Net library's BinarySearch
instead
of writing your own, IMHO.

Dec 29 '06 #7
public int BinarySearch(string[] strings, string str, int lowerbound, int
upperbound)
{
int pos = ((upperbound - lowerbound) / 2) + lowerbound;

int res = string.Compare(strings[pos], str);

if(res 0)
{
pos = this.BinarySearch(strings, str, lowerbound, pos);
}
else if(res < 0)
{
pos = this.BinarySearch(strings, str, pos, upperbound);
Use pos + 1 here, since pos is already checked.
}
return pos;
}
}
}

Dec 29 '06 #8

"Ben Voigt" <rb*@nospam.nospamwrote in message
news:%2****************@TK2MSFTNGP02.phx.gbl...
> public int BinarySearch(string[] strings, string str, int lowerbound,
int upperbound)
{
int pos = ((upperbound - lowerbound) / 2) + lowerbound;

int res = string.Compare(strings[pos], str);

if(res 0)
{
pos = this.BinarySearch(strings, str, lowerbound, pos);
}
else if(res < 0)
{
pos = this.BinarySearch(strings, str, pos, upperbound);

Use pos + 1 here, since pos is already checked.
> }
return pos;
}
}
}
.... and if you really want to gain performance, re-write this as a
non-recursive version. The C# compiler won't un-do the tail recursion for
you. The JIT might, but I wouldn't count on it - better to just write a
non-recursive version to start with. Even better, just use
Array.BinarySearch (assuming you're using the 2.0 framework, or later).

-cd
Dec 29 '06 #9

"Carl Daniel [VC++ MVP]" <cp*****************************@mvps.org.nospam >
wrote in message news:ua**************@TK2MSFTNGP02.phx.gbl...
>
"Ben Voigt" <rb*@nospam.nospamwrote in message
news:%2****************@TK2MSFTNGP02.phx.gbl...
>> public int BinarySearch(string[] strings, string str, int lowerbound,
int upperbound)
{
int pos = ((upperbound - lowerbound) / 2) + lowerbound;

int res = string.Compare(strings[pos], str);

if(res 0)
{
pos = this.BinarySearch(strings, str, lowerbound, pos);
}
else if(res < 0)
{
pos = this.BinarySearch(strings, str, pos, upperbound);

Use pos + 1 here, since pos is already checked.
>> }
return pos;
}
}
}

... and if you really want to gain performance, re-write this as a
non-recursive version. The C# compiler won't un-do the tail recursion for
you. The JIT might, but I wouldn't count on it - better to just write a
non-recursive version to start with. Even better, just use
Array.BinarySearch (assuming you're using the 2.0 framework, or later).
That wasn't actually meant as a performance tip, but for correctness.
>
-cd


Dec 29 '06 #10
"Ben Voigt" <rb*@nospam.nospamwrote in message
news:%2****************@TK2MSFTNGP04.phx.gbl...
"Carl Daniel [VC++ MVP]" <cp*****************************@mvps.org.nospam >
wrote in message news:ua**************@TK2MSFTNGP02.phx.gbl...
>... and if you really want to gain performance, re-write this as a
non-recursive version. The C# compiler won't un-do the tail recursion
for you. The JIT might, but I wouldn't count on it - better to just
write a non-recursive version to start with. Even better, just use
Array.BinarySearch (assuming you're using the 2.0 framework, or later).

That wasn't actually meant as a performance tip, but for correctness.
I know - just pointing it out for the OPs benefit. I know you know better
:)

-cd
Dec 29 '06 #11
Hello Carl,

I read somewhere that BinarySearch was sorting the array everytime it is
called ... tried finding the source but no luck.
Anyhow in the end I got the code working .... although I do not know if it
is faster or not:

public int BinarySearch(string[] strings, string str)
{
int upper = strings.GetUpperBound(0);
int lower = strings.GetLowerBound(0);

while(upper >= lower)
{
int pos = (upper + lower) / 2;

int res = string.Compare(strings[pos], str);
if(res 0)
{
upper = pos - 1;
}
else if(res < 0)
{
lower = pos + 1;
}
else
{
return pos;
}
}

throw new ApplicationException("String not found.");
}

Bob Rock
"Carl Daniel [VC++ MVP]" <cp*****************************@mvps.org.nospam >
wrote in message news:ee**************@TK2MSFTNGP02.phx.gbl...
Bob Rock wrote:
>Yes, the problem is that BinarySearch orders the array everytime
while the array in *already* ordered. I was trying to be more
efficient by writing my own code.

Not so. Array.BinarySearch requires that the array is already sorted - it
does not itself sort the array. You're re-inventing a wheel that's
already built for you in the framework.

-cd


Dec 29 '06 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: Nobody | last post by:
This is sort of my first attempt at writing a template container class, just wanted some feedback if everything looks kosher or if there can be any improvements. This is a template class for a...
3
by: tsunami | last post by:
hi all; I have an array and want to insert all the elements from this array to a binary search tree.That array is an object of the class of a stringtype which includes overloaded "< > = =="...
3
by: Jeffrey D. Gordon | last post by:
I'm wanting to replace Field Values in an existing PDF, I've done this with PHP by doing a replace in the file. I've been able to read the file in a byte array in c# but all my attempts to...
10
by: free2cric | last post by:
Hi, I have a single link list which is sorted. structure of which is like typedef struct mylist { int num; struct mylist *next;
6
by: zfareed | last post by:
<code> #include <iostream> #include <fstream> const int MAX_LENGTH = 10; using namespace std;
2
by: Timmy | last post by:
The bigger problem is with the Binary Search. The program crashes when it's excuted. and Visual Studio 2005 indicates stack over flow and shows a break at that function. Sequential search is...
9
ADezii
by: ADezii | last post by:
One question which pops up frequently here at TheScripts is: 'How do I retrieve data from a Recordset once I've created it?' One very efficient, and not that often used approach, is the GetRows()...
3
ADezii
by: ADezii | last post by:
Last Tip, we demonstrated the technique for retrieving data from a DAO Recordset, and placing it into a 2-dimensional Array using the GetRows() Method. This week, we will cover the same exact Method...
0
by: Atos | last post by:
Binary search is used to locate a value in a sorted list of values. It selects the middle element in the array of sorted values, and compares it with the target value; that is the key we are...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.