Skip to content

Commit c37e746

Browse files
authored
Merge pull request aalhour#119 from kdimolikas/search-algo
BinarySearcher Algorithm
2 parents 3e10141 + 1d5d728 commit c37e746

File tree

2 files changed

+190
-0
lines changed

2 files changed

+190
-0
lines changed

Algorithms/Search/BinarySearcher.cs

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using Algorithms.Sorting;
5+
6+
namespace Algorithms.Search
7+
{
8+
public class BinarySearcher<T> : IEnumerator<T>
9+
{
10+
private readonly IList<T> _collection;
11+
private readonly Comparer<T> _comparer;
12+
private T _item;
13+
private int _currentItemIndex;
14+
private int _leftIndex;
15+
private int _rightIndex;
16+
17+
/// <summary>
18+
/// The value of the current item
19+
/// </summary>
20+
public T Current
21+
{
22+
get
23+
{
24+
return _collection[_currentItemIndex];
25+
}
26+
}
27+
28+
object IEnumerator.Current => Current;
29+
30+
/// <summary>
31+
/// Class constructor
32+
/// </summary>
33+
/// <param name="collection">A list</param>
34+
/// <param name="comparer">A comparer</param>
35+
public BinarySearcher(IList<T> collection, Comparer<T> comparer)
36+
{
37+
if (collection == null)
38+
{
39+
throw new NullReferenceException("List is null");
40+
}
41+
_collection = collection;
42+
_comparer = comparer;
43+
HeapSorter.HeapSort(_collection);
44+
}
45+
46+
/// <summary>
47+
/// Apply Binary Search in a list.
48+
/// </summary>
49+
/// <param name="item">The item we search</param>
50+
/// <returns>If item found, its' index, -1 otherwise</returns>
51+
public int BinarySearch(T item)
52+
{
53+
bool notFound = true;
54+
55+
if (item == null)
56+
{
57+
throw new NullReferenceException("Item to search for is not set");
58+
}
59+
Reset();
60+
_item = item;
61+
62+
while ((_leftIndex <= _rightIndex) && notFound)
63+
{
64+
notFound = MoveNext();
65+
}
66+
67+
if (notFound)
68+
{
69+
Reset();
70+
}
71+
return _currentItemIndex;
72+
}
73+
74+
/// <summary>
75+
/// An implementation of IEnumerator's MoveNext method.
76+
/// </summary>
77+
/// <returns>true if iteration can proceed to the next item, false otherwise</returns>
78+
public bool MoveNext()
79+
{
80+
_currentItemIndex = this._leftIndex + (this._rightIndex - this._leftIndex) / 2;
81+
82+
if (_comparer.Compare(_item, Current) < 0)
83+
{
84+
_rightIndex = _currentItemIndex - 1;
85+
}
86+
else if (_comparer.Compare(_item, Current) > 0)
87+
{
88+
_leftIndex = _currentItemIndex + 1;
89+
}
90+
else
91+
{
92+
return false;
93+
}
94+
return true;
95+
}
96+
97+
public void Reset()
98+
{
99+
this._currentItemIndex = -1;
100+
_leftIndex = 0;
101+
_rightIndex = _collection.Count - 1;
102+
}
103+
104+
public void Dispose()
105+
{
106+
//not implementing this, since there are no managed resources to release
107+
}
108+
}
109+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
using System.Collections.Generic;
2+
using Xunit;
3+
using Algorithms.Search;
4+
5+
namespace UnitTest.AlgorithmsTests
6+
{
7+
public static class BinarySearcherTest
8+
{
9+
[Fact]
10+
public static void IntBinarySearchTest()
11+
{
12+
//list of ints
13+
IList<int> list = new List<int> { 9, 3, 7, 1, 6, 10 };
14+
IList<int> sortedList = new List<int> { 1, 3, 6, 7, 9, 10 };
15+
int numToSearch = 6;
16+
BinarySearcher<int> intSearcher = new BinarySearcher<int>(list, Comparer<int>.Default);
17+
int actualIndex = intSearcher.BinarySearch(numToSearch);
18+
int expectedIndex = sortedList.IndexOf(numToSearch);
19+
20+
Assert.Equal(expectedIndex, actualIndex);
21+
Assert.Equal(numToSearch, intSearcher.Current);
22+
23+
numToSearch = 20;
24+
int itemNotExists = intSearcher.BinarySearch(numToSearch);
25+
Assert.Equal(-1, itemNotExists);
26+
}
27+
28+
[Fact]
29+
public static void StringBinarySearchTest()
30+
{
31+
//list of strings
32+
IList<string> animals = new List<string> { "lion", "cat", "tiger", "bee", "sparrow" };
33+
IList<string> sortedAnimals = new List<string> { "bee", "cat", "lion", "sparrow", "tiger" };
34+
string itemToSearch = "bee";
35+
BinarySearcher<string> strSearcher = new BinarySearcher<string>(animals, Comparer<string>.Default);
36+
int actualIndex = strSearcher.BinarySearch(itemToSearch);
37+
int expectedAnimalIndex = sortedAnimals.IndexOf(itemToSearch);
38+
39+
Assert.Equal(expectedAnimalIndex, actualIndex);
40+
Assert.Equal(itemToSearch, strSearcher.Current);
41+
42+
itemToSearch = "shark";
43+
int itemNotExist = strSearcher.BinarySearch(itemToSearch);
44+
Assert.Equal(-1, itemNotExist);
45+
}
46+
47+
[Fact]
48+
public static void MoveNextTest()
49+
{
50+
IList<int> items = new List<int> {3, 5, 2, 6, 1, 4};
51+
BinarySearcher<int> searcher = new BinarySearcher<int>(items, Comparer<int>.Default);
52+
searcher.BinarySearch(1);
53+
//reset indices to test MoveNext()
54+
searcher.Reset();
55+
IList<int> leftEnumeratedValues = new List<int> {3, 2, 1};
56+
int i = 0;
57+
while (searcher.MoveNext())
58+
{
59+
Assert.Equal(leftEnumeratedValues[i++], searcher.Current);
60+
}
61+
62+
searcher.BinarySearch(6);
63+
//reset indices to test MoveNext()
64+
searcher.Reset();
65+
IList<int> rightEnumeratedValues = new List<int> {3, 5, 6};
66+
i = 0;
67+
while (searcher.MoveNext())
68+
{
69+
Assert.Equal(rightEnumeratedValues[i++], searcher.Current);
70+
}
71+
72+
}
73+
74+
[Fact]
75+
public static void NullCollectionExceptionTest()
76+
{
77+
IList<int> list = null;
78+
Assert.Throws<System.NullReferenceException>(() => new BinarySearcher<int>(list, Comparer<int>.Default));
79+
}
80+
}
81+
}

0 commit comments

Comments
 (0)