Skip to content

Commit 87e0d56

Browse files
r-avenousczgdp1807
andauthored
Added search algorithms for OneDimensionalArray (#454)
* Added helping note in README.md Co-authored-by: Gagandeep Singh <gdp.1807@gmail.com>
1 parent bea497c commit 87e0d56

File tree

6 files changed

+270
-6
lines changed

6 files changed

+270
-6
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ For development purposes, you can use the option `e` as shown below,
2525
python -m pip install -e .
2626
```
2727

28+
In the above commands, `.` in the end means the current directory. So, make sure you change your working directory
29+
to `pydatastructs` before executing any of the above commands.
30+
2831
Make sure that your python version is above `3.5`.
2932

3033
Testing

docs/source/pydatastructs/linear_data_structures/algorithms.rst

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,10 @@ Algorithms
3333

3434
.. autofunction:: pydatastructs.next_permutation
3535

36-
.. autofunction:: pydatastructs.prev_permutation
36+
.. autofunction:: pydatastructs.prev_permutation
37+
38+
.. autofunction:: pydatastructs.linear_search
39+
40+
.. autofunction:: pydatastructs.binary_search
41+
42+
.. autofunction:: pydatastructs.jump_search

pydatastructs/linear_data_structures/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
longest_increasing_subsequence,
4040
next_permutation,
4141
prev_permutation,
42-
bubble_sort
42+
bubble_sort,
43+
linear_search,
44+
binary_search,
45+
jump_search
4346
)
4447
__all__.extend(algorithms.__all__)

pydatastructs/linear_data_structures/algorithms.py

Lines changed: 218 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
_check_type, _comp, Backend,
55
raise_if_backend_is_not_python)
66
from concurrent.futures import ThreadPoolExecutor
7-
from math import log, floor
7+
from math import log, floor, sqrt
88

99
__all__ = [
1010
'merge_sort_parallel',
@@ -23,7 +23,10 @@
2323
'longest_increasing_subsequence',
2424
'next_permutation',
2525
'prev_permutation',
26-
'bubble_sort'
26+
'bubble_sort',
27+
'linear_search',
28+
'binary_search',
29+
'jump_search'
2730
]
2831

2932
def _merge(array, sl, el, sr, er, end, comp):
@@ -1369,3 +1372,216 @@ def bubble_sort(array, **kwargs):
13691372
array._modify(force=True)
13701373

13711374
return array
1375+
1376+
def linear_search(array, value, **kwargs):
1377+
"""
1378+
Implements linear search algorithm.
1379+
1380+
Parameters
1381+
==========
1382+
1383+
array: OneDimensionalArray
1384+
The array which is to be searched.
1385+
value:
1386+
The value which is to be searched
1387+
inside the array.
1388+
start: int
1389+
The starting index of the portion
1390+
which is to be searched.
1391+
Optional, by default 0
1392+
end: int
1393+
The ending index of the portion which
1394+
is to be searched.
1395+
Optional, by default the index
1396+
of the last position filled.
1397+
backend: pydatastructs.Backend
1398+
The backend to be used.
1399+
Optional, by default, the best available
1400+
backend is used.
1401+
1402+
Returns
1403+
=======
1404+
1405+
output: int
1406+
The index of value if found.
1407+
If not found, returns None.
1408+
1409+
Examples
1410+
========
1411+
1412+
>>> from pydatastructs import OneDimensionalArray, linear_search
1413+
>>> arr = OneDimensionalArray(int,[3, 2, 1])
1414+
>>> linear_search(arr, 2)
1415+
1
1416+
1417+
References
1418+
==========
1419+
1420+
.. [1] https://en.wikipedia.org/wiki/Linear_search
1421+
"""
1422+
raise_if_backend_is_not_python(
1423+
linear_search, kwargs.get('backend', Backend.PYTHON))
1424+
start = kwargs.get('start', 0)
1425+
end = kwargs.get('end', len(array) - 1)
1426+
1427+
for i in range(start, end + 1):
1428+
if array[i] == value:
1429+
return i
1430+
1431+
return None
1432+
1433+
def binary_search(array, value, **kwargs):
1434+
"""
1435+
Implements binary search algorithm.
1436+
1437+
Parameters
1438+
==========
1439+
1440+
array: OneDimensionalArray
1441+
The array which is to be searched.
1442+
value:
1443+
The value which is to be searched
1444+
inside the array.
1445+
start: int
1446+
The starting index of the portion
1447+
which is to be searched.
1448+
Optional, by default 0
1449+
end: int
1450+
The ending index of the portion which
1451+
is to be searched.
1452+
Optional, by default the index
1453+
of the last position filled.
1454+
comp: lambda/function
1455+
The comparator which is to be used
1456+
for performing comparisons.
1457+
Optional, by default, less than or
1458+
equal to is used for comparing two
1459+
values.
1460+
backend: pydatastructs.Backend
1461+
The backend to be used.
1462+
Optional, by default, the best available
1463+
backend is used.
1464+
1465+
Returns
1466+
=======
1467+
1468+
output: int
1469+
The index of elem if found.
1470+
If not found, returns None.
1471+
1472+
Examples
1473+
========
1474+
1475+
>>> from pydatastructs import OneDimensionalArray, binary_search
1476+
>>> arr = OneDimensionalArray(int,[1, 2, 3, 5, 10, 12])
1477+
>>> binary_search(arr, 5)
1478+
3
1479+
1480+
References
1481+
==========
1482+
1483+
.. [1] https://en.wikipedia.org/wiki/Binary_search_algorithm
1484+
1485+
Note
1486+
====
1487+
1488+
This algorithm assumes that the portion of the array
1489+
to be searched is already sorted.
1490+
"""
1491+
raise_if_backend_is_not_python(
1492+
binary_search, kwargs.get('backend', Backend.PYTHON))
1493+
start = kwargs.get('start', 0)
1494+
end = kwargs.get('end', len(array) - 1)
1495+
comp = kwargs.get("comp", lambda u, v: u <= v)
1496+
1497+
left = start
1498+
right = end
1499+
while left <= right:
1500+
middle = left//2 + right//2 + left % 2 * right % 2
1501+
if array[middle] == value:
1502+
return middle
1503+
if comp(array[middle], value):
1504+
left = middle + 1
1505+
else:
1506+
right = middle - 1
1507+
1508+
return None
1509+
1510+
def jump_search(array, value, **kwargs):
1511+
"""
1512+
Implements jump search algorithm.
1513+
1514+
Parameters
1515+
==========
1516+
1517+
array: OneDimensionalArray
1518+
The array which is to be searched.
1519+
value:
1520+
The value which is to be searched
1521+
inside the array.
1522+
start: int
1523+
The starting index of the portion
1524+
which is to be searched.
1525+
Optional, by default 0
1526+
end: int
1527+
The ending index of the portion which
1528+
is to be searched.
1529+
Optional, by default the index
1530+
of the last position filled.
1531+
comp: lambda/function
1532+
The comparator which is to be used
1533+
for performing comparisons.
1534+
Optional, by default, less than or
1535+
equal to is used for comparing two
1536+
values.
1537+
backend: pydatastructs.Backend
1538+
The backend to be used.
1539+
Optional, by default, the best available
1540+
backend is used.
1541+
1542+
Returns
1543+
=======
1544+
1545+
output: int
1546+
The index of elem if found.
1547+
If not found, returns None.
1548+
1549+
Examples
1550+
========
1551+
1552+
>>> from pydatastructs import OneDimensionalArray, jump_search
1553+
>>> arr = OneDimensionalArray(int,[1, 2, 3, 5, 10, 12])
1554+
>>> linear_search(arr, 5)
1555+
3
1556+
1557+
References
1558+
==========
1559+
1560+
.. [1] https://en.wikipedia.org/wiki/Jump_search
1561+
1562+
Note
1563+
====
1564+
1565+
This algorithm assumes that the portion of the array
1566+
to be searched is already sorted.
1567+
"""
1568+
raise_if_backend_is_not_python(
1569+
jump_search, kwargs.get('backend', Backend.PYTHON))
1570+
start = kwargs.get('start', 0)
1571+
end = kwargs.get('end', len(array) - 1)
1572+
comp = kwargs.get("comp", lambda u, v: u < v)
1573+
1574+
step = int(sqrt(end - start + 1))
1575+
current_position = step
1576+
prev = start
1577+
while comp(array[min(current_position, end)], value):
1578+
prev = current_position
1579+
current_position += step
1580+
if prev > end:
1581+
return None
1582+
while prev <= min(current_position, end):
1583+
if array[prev] == value:
1584+
return prev
1585+
prev += 1
1586+
1587+
return None

pydatastructs/linear_data_structures/tests/test_algorithms.py

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
heapsort, matrix_multiply_parallel, counting_sort, bucket_sort,
55
cocktail_shaker_sort, quick_sort, longest_common_subsequence, is_ordered,
66
upper_bound, lower_bound, longest_increasing_subsequence, next_permutation,
7-
prev_permutation, bubble_sort)
7+
prev_permutation, bubble_sort, linear_search, binary_search, jump_search)
88

99
from pydatastructs.utils.raises_util import raises
1010
import random
@@ -322,3 +322,39 @@ def test_next_prev_permutation():
322322
_, prev_array = prev_permutation(array)
323323
_, orig_array = next_permutation(prev_array)
324324
assert str(orig_array) == str(array)
325+
326+
def _test_common_search(search_func, sort_array=True):
327+
ODA = OneDimensionalArray
328+
329+
array = ODA(int, [1, 2, 5, 7, 10, 29, 40])
330+
for i in range(len(array)):
331+
assert i == search_func(array, array[i])
332+
333+
checker_array = [None, None, 2, 3, 4, 5, None]
334+
for i in range(len(array)):
335+
assert checker_array[i] == search_func(array, array[i], start=2, end=5)
336+
337+
random.seed(1000)
338+
339+
for i in range(25):
340+
data = list(set(random.sample(range(1, 10000), 100)))
341+
342+
if sort_array:
343+
data.sort()
344+
345+
array = ODA(int, list(data))
346+
347+
for i in range(len(array)):
348+
assert search_func(array, array[i]) == i
349+
350+
for _ in range(50):
351+
assert search_func(array, random.randint(10001, 50000)) is None
352+
353+
def test_linear_search():
354+
_test_common_search(linear_search, sort_array=False)
355+
356+
def test_binary_search():
357+
_test_common_search(binary_search)
358+
359+
def test_jump_search():
360+
_test_common_search(jump_search)

pydatastructs/utils/tests/test_code_quality.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ def _apis():
103103
pyds.AdjacencyMatrixGraphNode, pyds.GraphEdge, pyds.Set, pyds.BinaryIndexedTree,
104104
pyds.CartesianTree, pyds.CartesianTreeNode, pyds.Treap, pyds.RedBlackTreeNode, pyds.RedBlackTree,
105105
pyds.Trie, pyds.TrieNode, pyds.SkipList, pyds.RangeQueryStatic, pyds.SparseTable,
106-
pyds.bubble_sort]
106+
pyds.bubble_sort, pyds.linear_search, pyds.binary_search, pyds.jump_search]
107107

108108
def test_public_api():
109109
pyds = pydatastructs

0 commit comments

Comments
 (0)