Commit d2769fcc authored by Tom Almeida's avatar Tom Almeida

added mergesort, quicksort and heapsort

parent 445b1955
// Using std library to sort
#include <algorithm>
#include <iterator>
template<typename RandomAccessIterator>
void heap_sort(RandomAccessIterator begin, RandomAccessIterator end) {
std::make_heap(begin, end);
std::sort_heap(begin, end);
}
// Full code
#include <vector>
using namespace std;
void shift_down(vector<int>& heap,int i, int max) {
int i_big, c1, c2;
while(i < max) {
i_big = i;
c1 = (2*i) + 1;
c2 = c1 + 1;
if( c1<max && heap[c1]>heap[i_big] )
i_big = c1;
if( c2<max && heap[c2]>heap[i_big] )
i_big = c2;
if(i_big == i) return;
swap(heap[i],heap[i_big]);
i = i_big;
}
}
void to_heap(vector<int>& arr) {
int i = (arr.size()/2) - 1;
while(i >= 0) {
shift_down(arr, i, arr.size());
--i;
}
}
void heap_sort(vector<int>& arr) {
to_heap(arr);
int end = arr.size() - 1;
while (end > 0) {
swap(arr[0], arr[end]);
shift_down(arr, 0, end);
--end;
}
}
#include <iterator>
#include <algorithm> // for std::partition
template<typename RandomAccessIterator,
typename Order>
void quicksort(RandomAccessIterator first, RandomAccessIterator last, Order order)
{
if (last - first > 1)
{
RandomAccessIterator split = std::partition(first+1, last, std::bind2nd(order, *first));
std::iter_swap(first, split-1);
quicksort(first, split-1, order);
quicksort(split, last, order);
}
}
// Basic heapsort implimentation
// Returns the maximum of parent and their children in the array
int max (int *a, int n, int i, int j, int k) {
int m = i;
if (j < n && a[j] > a[m]) {
m = j;
}
if (k < n && a[k] > a[m]) {
m = k;
}
return m;
}
void downheap (int *a, int n, int i) {
while (1) {
int j = max(a, n, i, 2 * i + 1, 2 * i + 2);
if (j == i) {
break;
}
int t = a[i];
a[i] = a[j];
a[j] = t;
i = j;
}
}
void heapsort (int *a, int n) {
int i;
for (i = (n - 2) / 2; i >= 0; i--) {
downheap(a, n, i);
}
for (i = 0; i < n; i++) {
int t = a[n - i - 1];
a[n - i - 1] = a[0];
a[0] = t;
downheap(a, n - i - 1, 0);
}
}
// Quicksort algorithm
void quicksort(int *A, int len)
{
if (len < 2) return;
int pivot = A[len / 2];
int i, j;
for (i = 0, j = len - 1; ; i++, j--)
{
while (A[i] < pivot) i++;
while (A[j] > pivot) j--;
if (i >= j) break;
// swap
int temp = A[i];
A[i] = A[j];
A[j] = temp;
}
quicksort(A, i);
quicksort(A + i, len - i);
}
# Heapsort
## Complexity of O(`nlog(n)`)
The basic idea is to turn the array into a binary heap structure, which has the property that it allows efficient retrieval and removal of the maximal element.
We repeatedly "remove" the maximal element from the heap, thus building the sorted list from back to front.
Heapsort requires random access, so can only be used on an array-like data structure.
```
function heapSort(a, count) is
input: an unordered array a of length count
(first place a in max-heap order)
heapify(a, count)
end := count - 1
while end > 0 do
(swap the root(maximum value) of the heap with the
last element of the heap)
swap(a[end], a[0])
(decrement the size of the heap so that the previous
max value will stay in its proper place)
end := end - 1
(put the heap back in max-heap order)
siftDown(a, 0, end)
function heapify(a,count) is
(start is assigned the index in a of the last parent node)
start := (count - 2) / 2
while start ≥ 0 do
(sift down the node at index start to the proper place
such that all nodes below the start index are in heap
order)
siftDown(a, start, count-1)
start := start - 1
(after sifting down the root all nodes/elements are in heap order)
function siftDown(a, start, end) is
(end represents the limit of how far down the heap to sift)
root := start
while root * 2 + 1 ≤ end do (While the root has at least one child)
child := root * 2 + 1 (root*2+1 points to the left child)
(If the child has a sibling and the child's value is less than its sibling's...)
if child + 1 ≤ end and a[child] < a[child + 1] then
child := child + 1 (... then point to the right child instead)
if a[root] < a[child] then (out of max-heap order)
swap(a[root], a[child])
root := child (repeat to continue sifting down the child now)
else
return
```
### Languages
* [Rust](../../Rust/Sorting/Heapsort.rs)
* [C++](../../C++/Sorting/Heapsort.cpp)
* [C](../../C/Sorting/Heapsort.c)
# Mergesort
## Complexity of O(`nlog(n)`)
The basic idea is to split the collection into smaller groups by halving it until the groups only have one element or no elements (which are both entirely sorted groups).
Then merge the groups back together so that their elements are in order.
As such, the algorithm has two parts, the sorting function and the merging function.
```
function mergesort(m)
var list left, right, result
if length(m) ≤ 1
return m
else
var middle = length(m) / 2
for each x in m up to middle - 1
add x to left
for each x in m at and after middle
add x to right
left = mergesort(left)
right = mergesort(right)
if last(left) ≤ first(right)
append right to left
return left
result = merge(left, right)
return result
function merge(left,right)
var list result
while length(left) > 0 and length(right) > 0
if first(left) ≤ first(right)
append first(left) to result
left = rest(left)
else
append first(right) to result
right = rest(right)
if length(left) > 0
append rest(left) to result
if length(right) > 0
append rest(right) to result
return result
```
### Languages
* [Rust](../../Rust/Sorting/Mergesort.rs)
* [C++](../../C++/Sorting/Mergesort.cpp)
* [C](../../C/Sorting/Mergesort.c)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment