user: Explain bubble sort

assistant: Bubble sort is a sorting algorithm to sort arrays of numbers or other comparable things. It works by swapping two elements that are next to each other so that the bigger one is on the right afterwards. This process is repeated for each position from left to right. After this the biggest number in the array is at the last position. Next, the algorithm starts at the very left again and swaps neighbours going to the right, but this time it can stop before the last position, as the biggest number is already there. It is called bubble sort as the biggest number always "bubbles" up.
Here is an example:
```
4 8 3 6 1
# don't swap 4, 8 as 8 > 4
4 8 3 6 1
# swap 8, 3
4 3 8 6 1
# swap 8, 6
4 3 6 8 1
# swap 8, 1; 8 is now correct
4 3 6 1 8
# swap 4, 3
3 4 6 1 8
# don't swap 4, 6 as 6 > 4
3 4 6 1 8
# swap 1, 6; 6 is now correct
3 4 1 6 8
# don't swap 3, 4 as 4 > 3
3 4 1 6 8
# swap 4, 1; 4 is now correct
3 1 4 6 8
# swap 3, 1; 3 is now correct
1 3 4 6 8
# array is sorted
```

user: Explain heap sort and heapify.

assistant: **Heap Sort**
Heap sort is a more efficient sorting algorithm than bubble sort that also sorts numbers or other similarly comparable things. It uses a heap, (can be max or min) which is a binary tree where a node is always greater or lesser than both of its children. It takes `n*log_2(n)` time to create the heap, because each item must be inserted, and can travel up at most `log_2(n)` levels of the tree.
Then, the root node is already max, so it can be taken out and placed in a sorted list instantly. Then, a leaf node is placed where the root node is, and the tree is re-sorted, which takes at most `log_2(n)` time. Then the root node is taken out and placed in the sorted list again. This process is repeated until the tree is empty, which will take a total of `n*log_2(n)` time.
Here's an example sorting 3 numbers:
```


user: 

assistant: 

user: 

assistant: 

user: 

assistant: 

user: 

assistant: ##
# First, build the heap. #


user: 

assistant: 

user: 

assistant: 

user: 

assistant: 

user: 

assistant: ##
7 2 9
# Add 7 to root: 
# (7)
2 9
# add two to next leaf node:
# 7
# └── 2
# is it a max heap? Are all child nodes less than their parent nodes? Yes.
9
# add nine to the next leaf node:
# 7
# ├── 2
# └── 9
# Are all child nodes less than their parent nodes? No.
# move nine up:
# 9
# ├── 2
# └── 7
# Are all child nodes less than their parent nodes? Yes.

# No more elements are left. Heap is created. 



user: 

assistant: 

user: 

assistant: 

user: 

assistant: 

user: 

assistant: 

user: 
# Now sort from the heap. #


assistant: 

user: 

assistant: 

user: 

assistant: 

user: 

assistant: 

user: 

assistant: 
# take the root node and place it into the list:
# -
# ├── 2
# └── 7
9
# replace the root node with the last leaf node:
# 7
# └── 2
# Are all child nodes less than their parent nodes? Yes.
# take the root node and place it into the list on the left:
# -
# └── 2
7 9
# replace the root node with the last leaf node:
# (2)
# Are all child nodes less than their parent nodes? Yes.
# take the root node and place it into the list on the left: 
# (_)
2 7 9
# the tree is empty, which means we're done sorting!
```

---

**Heapify**

Instead of adjusting upwards in heap creation like before, heapify looks at each node, starting with the rightmost leaf node, and goes left until it reaches something that isn't a heap. Once it reaches a node where the children aren't all smaller than the parent, it will switch out the value of the root with the largest child. This is repeated with the swapped child node until it reached the bottom of the tree. Then, this whole process is repeated until the root of the entire tree is reached. This process still takes `n*log_m(n)` time at most, if all items need to move to the bottom of the tree each time, but it's useful for generally transforming trees into heaps.
Here's an example with a binary tree with four elements:
```
# start with a non max heap binary tree:
2
├── 9
│   └── 11
└── 7
# 11 is a heap because it has no children, continue to 7
# 7 is a heap because it has no children, continue to 9
# 9 is not a heap, because 11 is greater. Swap.
2
├── 11
│   └── 9
└── 7
# 9 is now a heap. Continue to 2.
# 2 is not a heap. Both 11 and 7 are greater. Swap with 11 since it's highest:
11
├── 2
│   └── 9
└── 7
# 2 is still not a heap. Swap with 9:
11
├── 9
│   └── 2
└── 7
# 2 is a heap, and 11 is the root. We're done!
```