简明排序代码
天天准备面试题,有复杂的算法有简单的数据结构。但是总是有些常考的经典排序算法:插入排序/堆排序/快排/归并排序。日常工作中谁也不会2B到自己写这些排序,这些纯应付面试用,你懂的!
// insert sort
template<typename T>
void insert_sort(T *begin, T *end)
{
if (begin == NULL || end == NULL)
{
return;
}
if (begin == end || begin + 1 == end)
{
return;
}
for (T *p = begin + 1; p != end; ++p)
{
T *pp = p - 1; T key = *p;
while (pp >= begin && key < *pp)
{
*(pp + 1) = *pp;
--pp;
}
*(pp + 1) = key;
}
}
// heap sort
template<typename T>
void unguarded_heapify(T *data, size_t size, size_t top)
{
while (true)
{
size_t max = top;
if (top * 2 < size && data[max] < data[top * 2])
{
max = top * 2;
}
if (top * 2 + 1 < size && data[max] < data[top * 2 + 1])
{
max = top * 2 + 1;
}
if (max == top)
{
return;
}
swap(data[max], data[top]);
top = max;
}
}
template<typename T>
void make_heap(T *begin, T *end)
{
if (begin == NULL || end == NULL)
{
return;
}
if (begin == end || begin + 1 == end)
{
return;
}
size_t len = end - begin;
for (size_t top = len / 2; top >= 1; --top)
{
unguarded_heapify(begin - 1, len + 1, top);
}
}
template<typename T>
void pop_heap(T *begin, T *end)
{
if (begin == NULL || end == NULL)
{
return;
}
if (begin == end || begin + 1 == end)
{
return;
}
iter_swap(begin, end - 1);
unguarded_heapify(begin - 1, end - begin, 1);
}
template<typename T>
void heap_sort(T *begin, T *end)
{
if (begin == NULL || end == NULL)
{
return;
}
make_heap(begin, end);
while (end - begin > 1)
{
pop_heap(begin, end--);
}
}
// quick sort
template<typename T>
T *unguarded_partition(T *begin, T *end, T key)
{
while (true)
{
while (*begin < key) ++begin;
--end;
while (key < *end) --end;
if (!(begin < end)) return begin;
iter_swap(begin, end);
++begin;
}
}
template<typename T>
void quick_sort(T *begin, T *end)
{
if (begin == NULL || end == NULL)
{
return;
}
if (begin == end || begin + 1 == end)
{
return;
}
while (begin < end)
{
T *cut = unguarded_partition(begin, end, *begin);
quick_sort(cut + 1, end);
end = cut;
}
}
// merge sort
template<typename T>
void merge(T *begin, T *end, T *scratch)
{
if (begin >= end || begin + 1 == end)
{
return;
}
T *mid = begin + (end - begin) / 2;
merge(begin, mid, scratch);
merge(mid, end, scratch);
T *left = begin;
T *right = mid;
T *target = scratch;
while (left != mid || right != end)
{
if (left < mid && (right == end || *left < *right))
{
*target++ = *left++;
}
else
{
*target++ = *right++;
}
}
memcpy(begin, scratch, (end - begin) * sizeof(T));
}
template<typename T>
void merge_sort(T *begin, T *end)
{
if (begin == NULL || end == NULL)
{
return;
}
T *scratch = new T[end - begin];
merge(begin, end, scratch);
delete[] scratch;
}