---
id: sorting
title: "Sorting"
author: Siyong (WIP)
order: 3
prerequisites:
-
- Silver - Containers
---
Description: Todo
- Sorting
- Comparators (C++)
- Coordinate Compression
**Sorting** is exactly what it sounds like: arranging items in some particular order.
## Sorting Algorithms
There are many sorting algorithms, here are some sources to learn about the popular ones:
- [Bubble Sort](https://www.freecodecamp.org/news/bubble-sort/)
- [Quicksort](https://medium.com/karuna-sehgal/a-quick-explanation-of-quick-sort-7d8e2563629b)
- [Mergesort](https://www.geeksforgeeks.org/merge-sort/)
(why are these important?)
## Library Sorting
- [C++ - std::sort](https://en.cppreference.com/w/cpp/algorithm/sort)
- Java: [Arrays.sort documentation](https://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html#sort(java.lang.Object[]))
- Python: [sorted documentation](https://docs.python.org/3/howto/sorting.html)
Problems:
- [Counting Haybales (Easy)](http://www.usaco.org/index.php?page=viewproblem2&cpid=666)
## Custom Comparators
(mention in context of http://www.usaco.org/index.php?page=viewproblem2&cpid=992)
*Custom comparators* define how the elements are ordered.
This section is very language-specific and will be separated by language.
### C++
Side note: In C++, a comparator must return false for two identical objects (not doing so results in undefined behavior and potentially RTE)
#### Comparators for Sorting
There are 2 main ways to have a custom comparator in c++
Type 1) Overloading operator
- Pro:
- This is the easiest to implement
- Easy to work with STL
- Con:
- Only works for objects (not primitives)
- Only supports two types of comparisons (less than (<) and greater than (>))
```cpp
struct Foo
{
int Bar;
Foo(int _Bar=-1):Bar(_Bar){}
bool operator < (const Foo& foo2) const {return Bar < foo2.Bar;}
};
const int N = 8;
int main()
{
Foo a[N];
for(int i=0;i
```cpp
struct Foo
{
int Bar;
Foo(int _Bar=-1):Bar(_Bar){}
};
const int N = 8;
Foo a[N];
bool cmp1(Foo foo1, Foo foo2) {return foo1.Bar < foo2.Bar;}
auto cmp2 = [](Foo foo1, Foo foo2) {return foo1.Bar < foo2.Bar;};//requires c++11 or above
int main()
{
printf("--- Method 1 ---\n");
for(int i=0;i Set(cmp);//pass the comparator as a parameter
priority_queue, decltype(cmp)> pq(cmp);
//Side Note: priority queue is sorted in REVERSE order (largest elements are first)
map Map(cmp);
```
#### Example of Comparators for Primitives
Since you cannot overload operators for primitives, you must use custom comparators
```cpp
const int N = 8;
int a[N], b[N] = {4,8,2,3,4,1,2,4};
int main()
{
printf("--- Comparator 1 ---\n");
iota(a, a+N, 0);
sort(a, a+N, greater());
//sort a in decreasing order
for(int i=0;iy);});
//sort a by increasing values of b[i], breaking ties by decreasing index
for(int i=0;i
```py
class Foo:
def __init__(self, _Bar): self.Bar = _Bar
def __str__(self): return "Foo({})".format(self.Bar)
def __lt__(self, o): # lt means less than
return self.Bar < o.Bar
a = []
for i in range(8):
a.append(Foo(random.randint(1, 10)))
print(*a)
print(*sorted(a))
```
Output:
```
Foo(0) Foo(1) Foo(2) Foo(1) Foo(9) Foo(5) Foo(5) Foo(8)
Foo(0) Foo(1) Foo(1) Foo(2) Foo(5) Foo(5) Foo(8) Foo(9)
```
Type 2) Function/Lambda
- This method defines how to compare two elements represented by an integer
- Positive: First term is greater than the second term
- Zero: First term and second term are equal
- Negative: First term is less than the second term
```py
from functools import cmp_to_key
class Foo:
def __init__(self, _Bar): self.Bar = _Bar
def __str__(self): return "Foo({})".format(self.Bar)
a = []
for i in range(8):
a.append(Foo(random.randint(0, 9)))
print(*a)
print(*sorted(a, key=cmp_to_key(lambda foo1, foo2: foo1.Bar - foo2.Bar)))
def cmp(foo1, foo2):
return foo1.Bar - foo2.Bar
print(*sorted(a, key=cmp_to_key(cmp)))
```
Output:
```
Foo(0) Foo(1) Foo(2) Foo(1) Foo(9) Foo(5) Foo(5) Foo(8)
Foo(0) Foo(1) Foo(1) Foo(2) Foo(5) Foo(5) Foo(8) Foo(9)
Foo(0) Foo(1) Foo(1) Foo(2) Foo(5) Foo(5) Foo(8) Foo(9)
```
Type 3) Remapping Key
- This method maps an object to another comparable datatype with which to be sorted. In this case, `Foo` is sorted by the sum of its members `x` and `y`.
```py
class Foo:
def __init__(self, _Bar, _Baz): self.Bar,self.Baz = _Bar,_Baz
def __str__(self): return "Foo({},{})".format(self.Bar, self.Baz)
a = []
for i in range(8):
a.append(Foo(random.randint(1, 9)*10, random.randint(1, 9)))
print(*a)
print(*sorted(a, key=lambda foo: foo.Bar+foo.Baz))
def key(foo):
return foo.Bar + foo.Baz
print(*sorted(a, key=key))
```
Output:
```
Foo(10,2) Foo(30,2) Foo(60,6) Foo(90,7) Foo(80,7) Foo(80,9) Foo(60,9) Foo(90,8)
Foo(10,2) Foo(30,2) Foo(60,6) Foo(60,9) Foo(80,7) Foo(80,9) Foo(90,7) Foo(90,8)
Foo(10,2) Foo(30,2) Foo(60,6) Foo(60,9) Foo(80,7) Foo(80,9) Foo(90,7) Foo(90,8)
```
## Coordinate Compression
- CPH 3
- coord compress