home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 18 REXX
/
18-REXX.zip
/
bsrch.rex
< prev
next >
Wrap
OS/2 REXX Batch file
|
1996-01-17
|
5KB
|
124 lines
/* rexx */
/* Bsearch -
A binary search is useful when there is a large amount of data
to search through very quickly. It is comparable to the way a human
would look up a word in a dictionary or phone book. You could start
at the beginning and read sequentially until the word or number is found,
and that's fine if the name or word is near the beginning, but most often
you would start in the middle of the phone book. Here is a table:
Search: A_Test B_Test C_Test D_Test E_Test
1 A_Test <- 3
2 B_Test <- 2 <-2
3 C_Test <- 1 <-1 <-1 <-1 <-1 <- Start in the middle
4 D_Test <-2 <-2
5 E_Test <-3
Passes: 3 2 1 2 3
An array of 5 elements can be searched in 3 passes max. The stem is cut in
half for every pass. This is almost always much faster then sequentially
reading through each stem. The main drawback to this approach is that all
data in the stem MUST be sorted. (Just like a dictionary or Phone book)
This implementation of Bsearch returns a space delimited string of information
"Found Where Passes"
The search is case sensitive. But it would be easy to modify.
This routine was written for regina running on a Linux system, but I see no
reason why it wouldn't run under OS/2 as well.
It is based on Ethan Winer's book: QuickBasic Techniques and Utilities
Binary Search routine. But is modified for rexx.
It is important to note that the stem to search must be exposed to the
routine, and that since rexx has no "bound checking" a common convention
is to use stem.0 for the number of elements. Bsearch uses this as the
default, but a range may be specified in args 3,4.
Result = Bsearch("Animal.","Cat",2,10) /* look for a Cat */
Will look at the stem "Animal." for the word "Cat". The range it will
look at is animal.2 to animal.10
if the range is not specified, and animal.0 contains a NON numeric string,
bsearch will bomb. Of course, Animal. must have been sorted.
*/
/* the following is test code */
Gl.0 = 26
/* produce a SORTED test stem of 26 */
DO I = 1 to Gl.0
Gl.I = D2C(I+64)||"_Test"
END
TestFind = "A_Test Zebra B_Test M_Test N_Test Y_Test Z_Test Apple"
DO I = 1 to WORDS(TestFind)
Find = WORD(TestFind,I)
Say "Looking for : '"Find"'"
Result = Bsearch("Gl.",Find) /* look for find */
Found = Word(Result,1) /* Did we find it? 0/1 */
Where = Word(Result,2) /* where was it? */
Passes = Word(Result,3) /* how long did it take? */
IF Found THEN
Say "'"Find"' Was found element: "Where" it took "Passes" Passes."
ELSE
Say "'"Find"' Was not found, closest: "Where" it took "Passes" Passes."
Say "Value of Gl."Where" : '"Gl.Where"'"
END
Call Charout ,"Do you wish to look for every element [N] "
Pull Q
Say
if Q = "Y" Then DO
Say "Finding every element"
Do I = 1 to 26
Find = Gl.I
Result = Bsearch("Gl.",Find)
IF WORD(Result,1) THEN
Say "Found: '"Find"' element "WORD(Result,2)" Passes: "Word(Result,3)
ELSE
Say "'"Find"' was not found, bsearch is broken, do not use"
END
END
Exit
/* this is the actual routine, cut & paste to your program. */
/***************************************************************************
* Binary search a stem. Stem MUST be sorted
* Stem = Arg(1) - Stem to look at
* Find = Arg(2) - What to look for
* From = Arg(3) - Where to start (default 1)
* To = Arg(4) - Where to stop (default Stem.0)
*
* Returns a string:
* Found Where Passes
* Found - 0/1 Did we find it?
* Where - Where in the stem did we find it?
* Passes - How many passes (Remove this for speed, just for demonstration)
*
* This routine was ported from a QuickBasic Function by Ethan Winer
* in his book "Basic Techniques an Utilities" ISBN 1-56276-008-4
***************************************************************************/
Bsearch: procedure expose Gl.
stem = ARG(1)
Find = ARG(2)
IF DATATYPE(ARG(3),"N") THEN ; Min = Arg(3) ; Else ; Min = 1
IF DATATYPE(ARG(4),"N") THEN ; Max = Arg(4) ; Else ; Max = VALUE(Stem"0")
Pass = 0 /* remove if you want */
DO FOREVER
Pass = Pass + 1 /* remove if you want */
Try = (Max + Min) % 2 /* start in middle */
Now = VALUE(Stem||Try)
IF Now = Find THEN
return "1 "Try" "Pass /* remove the "pass" if you want */
IF Now > Find THEN /* this cuts the range in 1/2 */
Max = (Try - 1)
Else
Min = (Try + 1)
IF Max < Min THEN
return "0 "Try" "Pass /* remove "pass" if you want */
END