-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMergeSort.cs
More file actions
150 lines (132 loc) · 4.58 KB
/
MergeSort.cs
File metadata and controls
150 lines (132 loc) · 4.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BarcodeRecoveryCS
{
public class MergeSort
{
#region Constants
private const Int32 mergesDefault = 6;
private const Int32 insertionLimitDefault = 12;
#endregion
#region Properties
protected Int32[] Positions { get; set; }
private Int32 merges;
public Int32 Merges
{
get { return merges; }
set
{
// A minimum of 2 merges are required
if (value > 1)
merges = value;
else
throw new ArgumentOutOfRangeException();
if (Positions == null || Positions.Length != merges)
Positions = new Int32[merges];
}
}
public Int32 InsertionLimit { get; set; }
#endregion
#region Constructors
public MergeSort(Int32 merges, Int32 insertionLimit)
{
Merges = merges;
InsertionLimit = insertionLimit;
}
public MergeSort()
: this(mergesDefault, insertionLimitDefault)
{
}
#endregion
#region Sort Methods
public List<FoundBars> Sort(List<FoundBars> entries)
{
// Allocate merge buffer
List<FoundBars> entries2 = new List<FoundBars>(entries.Count);
Sort(entries, entries2, 0, entries.Count - 1);
return entries2;
}
// Top-Down K-way Merge Sort
public void Sort(List<FoundBars> entries1, List<FoundBars> entries2, Int32 first, Int32 last)
{
var length = last + 1 - first;
if (length < 2)
return;
else if (length < InsertionLimit)
{
InsertionSort.Sort(entries1, first, last);
return;
}
var left = first;
var size = ceiling(length, Merges);
for (var remaining = length; remaining > 0; remaining -= size, left += size)
{
var right = left + Math.Min(remaining, size) - 1;
Sort(entries1, entries2, left, right);
}
Merge(entries1, entries2, first, last);
Array.Copy(entries2.ToArray(), first, entries1.ToArray(), first, length);
}
#endregion
#region Merge Methods
public void Merge(List<FoundBars> entries1, List<FoundBars> entries2, Int32 first, Int32 last)
{
Array.Clear(Positions, 0, Merges);
// This implementation has a quadratic time dependency on the number of merges
for (var index = first; index <= last; index++)
entries2[index] = remove(entries1, first, last);
}
private FoundBars remove(List<FoundBars> entries, Int32 first, Int32 last)
{
var entry = default(FoundBars);
var found = (Int32?)null;
var length = last + 1 - first;
var index = 0;
var left = first;
var size = ceiling(length, Merges);
for (var remaining = length; remaining > 0; remaining -= size, left += size, index++)
{
var position = Positions[index];
if (position < Math.Min(remaining, size))
{
var next = entries[left + position];
if (!found.HasValue || entry.x.CompareTo(next.x) > 0)
{
found = index;
entry = next;
}
}
}
// Remove entry
Positions[found.Value]++;
return entry;
}
#endregion
#region Math Methods
private static Int32 ceiling(Int32 numerator, Int32 denominator)
{
return (numerator + denominator - 1) / denominator;
}
#endregion
}
// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#region Insertion Sort
static class InsertionSort
{
public static void Sort(List<FoundBars> entries, Int32 first, Int32 last)
{
for (int i = first + 1; i <= last; i++)
{
var entry = entries[i];
var j = i;
while (j > first && entries[j - 1].x.CompareTo(entry.x) > 0)
entries[j] = entries[--j];
entries[j] = entry;
}
}
}
#endregion
}