Skip to content

Commit 912794e

Browse files
committed
- Added (and fixed) Bucket Sort, using recursive calls to Bucket Sort and Insertion Sort
1 parent eaac0e0 commit 912794e

File tree

7 files changed

+234
-5
lines changed

7 files changed

+234
-5
lines changed

Sorting Algorithms/BucketSort.cs

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace Sorting_Algorithms
8+
{
9+
class BucketSort : Sort
10+
{
11+
List<double>[] buckets;
12+
readonly int NUM_OF_BUCKETS = 10;
13+
int currentBucketIndex = -1;
14+
15+
const int MAKE_BUCKETS = 0;
16+
const int SORT_BUCKETS = 1;
17+
const int CONCAT_BUCKETS = 2;
18+
19+
// uses insertion sort if bucket contains fewer than this number of items
20+
// otherwise uses recursive call to bucket sort
21+
const int INSERT_BUCKET_THRESHOLD = 6;
22+
23+
readonly double minArrValue = 3.0;
24+
readonly double maxArrValue = 100.0;
25+
readonly double rangeOfBucket = 0;
26+
27+
Sort currentSort;
28+
29+
public BucketSort(double[] array, double minArrValue, double maxArrValue) : base(array)
30+
{
31+
// no need to sort fewer than two elements
32+
if (array.Length < 2)
33+
{
34+
isFinished = true;
35+
return;
36+
}
37+
38+
// must be able to split the array into singletons
39+
NUM_OF_BUCKETS = Math.Min(array.Length, NUM_OF_BUCKETS);
40+
41+
// initialise list of buckets
42+
this.buckets = new List<double>[NUM_OF_BUCKETS];
43+
44+
// initialise each bucket
45+
for (int i = 0; i < buckets.Length; i++)
46+
{
47+
buckets[i] = new List<double>();
48+
}
49+
50+
this.minArrValue = minArrValue;
51+
this.maxArrValue = maxArrValue;
52+
this.MODE = MAKE_BUCKETS;
53+
this.rangeOfBucket = (this.maxArrValue - this.minArrValue) / NUM_OF_BUCKETS;
54+
this.fillGapWithColour = true;
55+
}
56+
57+
private int getBucketIndex(double arrVal)
58+
{
59+
return (int)Math.Max(Math.Min(Math.Floor((arrVal - minArrValue) / rangeOfBucket), buckets.Length - 1),0);
60+
}
61+
62+
public override int getI()
63+
{
64+
if (currentSort is BucketSort)
65+
return SortK + currentSort.getI();
66+
return SortK;
67+
}
68+
69+
public override int getJ()
70+
{
71+
if (MODE == MAKE_BUCKETS)
72+
return Math.Max(0, SortJ - 1);
73+
else if (currentSort is BucketSort)
74+
return SortK + currentSort.getJ();
75+
else if (currentSort is InsertionSort)
76+
return SortK + currentSort.getMax();
77+
else if (currentBucketIndex > -1 && currentBucketIndex < buckets.Length)
78+
return SortK + buckets[currentBucketIndex].Count;
79+
80+
return SortK;
81+
}
82+
83+
public override int getK()
84+
{
85+
if (currentSort is InsertionSort)
86+
return SortK + currentSort.getI() - 1;
87+
else if (currentSort is BucketSort)
88+
return SortK + currentSort.getK();
89+
return SortK;
90+
}
91+
92+
public override double[] Run()
93+
{
94+
if (MODE == MAKE_BUCKETS)
95+
{
96+
addNextValueToBucket();
97+
if (SortJ > max)
98+
MODE = SORT_BUCKETS;
99+
}
100+
else if (MODE == SORT_BUCKETS)
101+
{
102+
if (currentSort != null && !currentSort.hasFinished())
103+
sortCurrentBucket();
104+
else
105+
initNextBucketSort();
106+
}
107+
else
108+
{
109+
isFinished = true;
110+
array = concatBuckets();
111+
return array;
112+
}
113+
114+
return concatBuckets();
115+
}
116+
117+
public override double[] QuickRun()
118+
{
119+
if (MODE == MAKE_BUCKETS) {
120+
int iterations = Math.Min(array.Length / NUM_OF_BUCKETS, max - SortJ);
121+
122+
for (; iterations > -1; iterations--) {
123+
addNextValueToBucket();
124+
}
125+
126+
if (SortJ > max)
127+
MODE = SORT_BUCKETS;
128+
}
129+
else if (MODE == SORT_BUCKETS)
130+
{
131+
while (currentSort != null && !currentSort.hasFinished())
132+
sortCurrentBucket();
133+
134+
initNextBucketSort();
135+
}
136+
else {
137+
isFinished = true;
138+
array = concatBuckets();
139+
return array;
140+
}
141+
142+
return concatBuckets();
143+
}
144+
145+
private void addNextValueToBucket()
146+
{
147+
double value = array[SortJ];
148+
int index = getBucketIndex(value);
149+
// add the value to its bucket
150+
buckets[index].Add(value);
151+
swapCount++;
152+
SortJ++;
153+
}
154+
155+
private void initNextBucketSort()
156+
{
157+
if (currentBucketIndex > -1)
158+
SortK += buckets[currentBucketIndex].Count;
159+
160+
currentBucketIndex++;
161+
162+
if (currentBucketIndex < buckets.Length)
163+
currentSort = beginNewSort(currentBucketIndex, buckets[currentBucketIndex].ToArray());
164+
else
165+
MODE = CONCAT_BUCKETS;
166+
}
167+
168+
private void sortCurrentBucket()
169+
{
170+
int prevSwaps = currentSort.getSwaps();
171+
int prevComparisons = currentSort.getComparisons();
172+
// run next step of child sort and store results in the current bucket
173+
buckets[currentBucketIndex] = currentSort.Run().ToList();
174+
swapCount += currentSort.getSwaps() - prevSwaps;
175+
comparisonCount += currentSort.getComparisons() - prevComparisons;
176+
}
177+
178+
protected virtual Sort beginNewSort(int bucketIndex, double[] bucket)
179+
{
180+
double minBucketValue = minArrValue + bucketIndex * rangeOfBucket;
181+
double maxBucketValue = minBucketValue + rangeOfBucket;
182+
183+
if (bucket.Length < 2)
184+
return null;
185+
186+
if (bucket.Length <= INSERT_BUCKET_THRESHOLD)
187+
return new InsertionSort(bucket);
188+
189+
return new BucketSort(bucket, minBucketValue, maxBucketValue);
190+
}
191+
192+
private double[] concatBuckets()
193+
{
194+
double[] concat = new double[array.Length];
195+
int index = 0;
196+
197+
foreach (List<double> bucket in buckets)
198+
{
199+
for (int i = 0; i < bucket.Count; i++)
200+
{
201+
concat[index] = bucket[i];
202+
index++;
203+
}
204+
}
205+
206+
return concat;
207+
}
208+
}
209+
}

Sorting Algorithms/HeapSort.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ its parent at index floor((i − 1) ∕ 2)
1414
int root = 0;
1515
int swap;
1616
int largest;
17-
int MODE = 0;
1817
const int CREATE_HEAP = 0;
1918
const int SIFT_HEAP = 1;
2019
const int BETWEEN_SIFTS = 2;

Sorting Algorithms/IntroSort.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ public int getInterval()
2828
protected const int QUICK_MODE = 0;
2929
protected const int INSERTION_MODE = 1;
3030
protected const int HEAP_MODE = 2;
31-
protected int MODE;
3231
readonly int insertionSortThreshold = 16; // if partition is smaller, use insertion sort
3332

3433
Queue<IntroQNode> queue = new Queue<IntroQNode>();

Sorting Algorithms/MainWindow.xaml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,17 @@
6868
</StackPanel>
6969
</GroupBox>
7070

71+
<GroupBox Name="CountingSortsGroup" Header="Counting Sorts" Margin="10" FontStyle="Italic" BorderBrush="Gray" BorderThickness="2">
72+
<StackPanel Margin="2">
73+
<Button Name="BucketSort" Content="Bucket Sort" Margin="2" Height="25" Click="SortButton_Click" ToolTip="Bucket Sort with recursive sub-calls to Bucket/Insertion Sort"></Button>
74+
</StackPanel>
75+
</GroupBox>
76+
7177
<GroupBox Name="OtherSortsGroup" Header="Other Sorts" Margin="10" FontStyle="Italic" BorderBrush="Gray" BorderThickness="2">
7278
<StackPanel Margin="2">
73-
<Button Name="MergeBtn" Content="Merge Sort" Margin="2" Canvas.Top="210" Height="25" Click="SortButton_Click" ToolTip="Merge Sort"></Button>
74-
<Button Name="CycleBtn" Content="Cycle Sort" Margin="2" Canvas.Top="210" Height="25" Click="SortButton_Click" ToolTip="Cycle Sort"></Button>
75-
<Button Name="PatienceSort" Content="Patience Sort" Margin="2" Canvas.Top="210" Height="25" Click="SortButton_Click" ToolTip="Patience Sort without Priority Queue"></Button>
79+
<Button Name="MergeBtn" Content="Merge Sort" Margin="2" Height="25" Click="SortButton_Click" ToolTip="Merge Sort"></Button>
80+
<Button Name="CycleBtn" Content="Cycle Sort" Margin="2" Height="25" Click="SortButton_Click" ToolTip="Cycle Sort"></Button>
81+
<Button Name="PatienceSort" Content="Patience Sort" Margin="2" Height="25" Click="SortButton_Click" ToolTip="Patience Sort without Priority Queue"></Button>
7682
</StackPanel>
7783
</GroupBox>
7884
</StackPanel>

Sorting Algorithms/MainWindow.xaml.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ private void EnableSortButtons(bool state)
172172
QuickSortGroup.IsEnabled = state;
173173
HeapSortsGroup.IsEnabled = state;
174174
HybridSortsGroup.IsEnabled = state;
175+
CountingSortsGroup.IsEnabled = state;
175176
OtherSortsGroup.IsEnabled = state;
176177

177178
FastChkBox.IsEnabled = state;
@@ -239,6 +240,9 @@ private void SortButton_Click(object Sender, RoutedEventArgs e)
239240
case "Binary Intro Sort":
240241
currentSort = new BinaryIntroSort(array);
241242
break;
243+
case "Bucket Sort":
244+
currentSort = new BucketSort(array, minBarVal, maxBarVal);
245+
break;
242246
default:
243247
return;
244248
}

Sorting Algorithms/Sort.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ abstract class Sort
1515
protected bool isFinished = false;
1616
protected int min = 0;
1717
protected int max = 0;
18+
protected int MODE = 0;
1819

1920
public Sort(double[] array)
2021
{
@@ -29,6 +30,16 @@ protected void updateArray(double[] array)
2930
this.array = array;
3031
}
3132

33+
public int getMin()
34+
{
35+
return min;
36+
}
37+
38+
public int getMax()
39+
{
40+
return max;
41+
}
42+
3243
public bool isArraySorted()
3344
{
3445
// linear pass to determine if array is sorted (so heavy algorithms do not need to be started)

Sorting Algorithms/Sorting Algorithms.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
</Compile>
7878
<Compile Include="BinaryInsertion.cs" />
7979
<Compile Include="BubbleSort.cs" />
80+
<Compile Include="BucketSort.cs" />
8081
<Compile Include="CocktailShakerSort.cs" />
8182
<Compile Include="CombSort.cs" />
8283
<Compile Include="CycleSort.cs" />

0 commit comments

Comments
 (0)