|
using System; |
|
|
|
namespace MedianBenchmark |
|
{ |
|
public static class MedianImpls |
|
{ |
|
public static int ArraySort(int[] data) |
|
{ |
|
var w = (int[])data.Clone(); |
|
Array.Sort(w); |
|
return w.Length % 2 == 0 |
|
? (w[w.Length / 2] + w[w.Length / 2 - 1]) / 2 |
|
: w[w.Length / 2]; |
|
} |
|
|
|
public static int InsertSort(int[] data) |
|
{ |
|
var capacity = data.Length / 2 + 1; |
|
var w = new int[capacity]; |
|
w[0] = data[0]; |
|
var wCount = 1; |
|
|
|
for (var i = 1; i < data.Length; i++) |
|
{ |
|
var v = data[i]; |
|
var j = wCount - 1; |
|
if (w[j] <= v) |
|
{ |
|
if (wCount < capacity) |
|
w[wCount++] = v; |
|
continue; |
|
} |
|
|
|
if (wCount < capacity) |
|
{ |
|
wCount++; |
|
j++; |
|
} |
|
|
|
for (; j > 0 && w[j - 1] > v; j--) |
|
w[j] = w[j - 1]; |
|
|
|
w[j] = v; |
|
} |
|
|
|
return data.Length % 2 == 0 |
|
? (w[capacity - 1] + w[capacity - 2]) / 2 |
|
: w[capacity - 1]; |
|
} |
|
|
|
public static int HeapSort(int[] data) |
|
{ |
|
var capacity = data.Length / 2 + 1; |
|
var heap = new RestrictedBinaryHeap<int>(capacity); |
|
|
|
var i = 0; |
|
for (; i < capacity; i++) |
|
heap.Push(data[i]); |
|
|
|
for (; i < data.Length; i++) |
|
{ |
|
if (data[i] < heap.GetHead()) |
|
heap.ReplaceHead(data[i]); |
|
} |
|
|
|
return data.Length % 2 == 0 |
|
? (heap.GetHead() + heap.GetSecond()) / 2 |
|
: heap.GetHead(); |
|
} |
|
|
|
private struct RestrictedBinaryHeap<T> where T : IComparable<T> |
|
{ |
|
private readonly T[] _array; |
|
private int _count; |
|
|
|
public RestrictedBinaryHeap(int capacity) |
|
{ |
|
_array = new T[capacity]; |
|
_count = 0; |
|
} |
|
|
|
public void Push(T value) |
|
{ |
|
var nodeIndex = _count++; |
|
|
|
while (nodeIndex > 0) |
|
{ |
|
var parentIndex = (nodeIndex - 1) / 2; |
|
|
|
if (value.CompareTo(_array[parentIndex]) <= 0) break; |
|
|
|
_array[nodeIndex] = _array[parentIndex]; |
|
nodeIndex = parentIndex; |
|
} |
|
|
|
_array[nodeIndex] = value; |
|
} |
|
|
|
public void ReplaceHead(T value) |
|
{ |
|
var nodeIndex = 0; |
|
|
|
while (true) |
|
{ |
|
var childIndex = 2 * nodeIndex + 1; |
|
|
|
if (childIndex >= _count) break; |
|
|
|
if (childIndex + 1 < _count && _array[childIndex + 1].CompareTo(_array[childIndex]) > 0) |
|
childIndex++; |
|
|
|
if (value.CompareTo(_array[childIndex]) >= 0) break; |
|
|
|
_array[nodeIndex] = _array[childIndex]; |
|
nodeIndex = childIndex; |
|
} |
|
|
|
_array[nodeIndex] = value; |
|
} |
|
|
|
public T GetHead() => _array[0]; |
|
|
|
public T GetSecond() => _count < 3 || _array[1].CompareTo(_array[2]) >= 0 ? _array[1] : _array[2]; |
|
} |
|
} |
|
} |