auto update

This commit is contained in:
Jet Hughes 2022-04-07 17:50:51 +12:00
parent 909046b6d6
commit 2a2242f1a2
6 changed files with 236 additions and 185 deletions

View File

@ -1,8 +1,14 @@
---
title: "04-requirements"
sr-due: 2022-04-06
sr-interval: 15
sr-ease: 232
tags:
- info201
- lecture
sr-due: 2022-04-10
sr-interval: 3
sr-ease: 250
---
[requirements](notes/requirements.md)

View File

@ -1,17 +1,24 @@
---
title: "07-mergesort-1"
sr-due: 2022-04-26
sr-interval: 23
sr-ease: 250
tags:
- cosc201
- lecture
---
# Divide and conquer
[mergeosrt](notes/mergeosrt.md)
#unfinished
# 1 Divide and conquer
1. pre ⇒ break apartinto two or more smaller problems whose size add up to at most n
2. Rec ⇒ solve those problems recursively
3. post ⇒ combine solutions into a solution of the original problem
## 1 quicksort
## 1.1 quicksort
pre ⇒ select pivot and split the array
@ -27,78 +34,3 @@ works best of primitive types as they can be stored in the fastest memory locati
- those advantages are limited when sorting objects of reference type
- i that case each element of the array is just a reference to where the object really is
- so there are no local access advantages
# Mergesort
a variant of a divide and conquer sorting array
pre ⇒ split array into two pieces of nearly equal size,
rec ⇒ sort the pieces,
post ⇒ merge the pieces
## 2 Merge
take the two lowest values
place the lowest of the two in the next place in the sorted array
## 3 Implementation
- given: a and b are sorted arrays. m in an array whose sixe is the sum fo their sizes
- desired outcome: the elements of a and b have been copoed into m in sorted order
- maiain indices, ai, bi, and mi of the active location in a b and m
- if both ai and bi represent actual indices of a and b, find the one which points to the lesser value (break ties in favour of a) copy that vale into m at mi and increment mi and whichever of ai or bi was used for the copy.
- once one of ai and bi is out of range, copy the rest of the other array into the remainder of m
```java
public static int[] merge (int[] a int[] b){
int[] m = new int[a.length + b.length]
int ai = 0, bi = 0, mi = 0;
while(ai < a.length && bi < b.length) {
if(a[ai] <= b[bi]) m[mi++] = a[ai++];
else m[mi++] = b[bi++]
}
while (ai < a.length) m[mi++] = a[ai++];
while (bi < b.length) m[mi++] = a[bi++];
return m;
}
```
```java
public static void mergeSort(int[] a){
mergeSort(a, 0, a.length);
}
public static void mergeSort(int[] a, int lo, int hi){
if(hi - lo <= 1) return;
int mid = (hi + lo)/2;
mergeSort(a, lo, mid);
mergeSort(a, mid, hi);
merge(a, lo, mid, hi);
}
public static void merge(int[] a, int lo, int mid, int hi){
int[] t = new int [hi-lo];
//adjust code from 'merge' here so that the part of a from lo to mid, and the part of a from mid to hi are merged into t
System.arraycopy(t, 0, a, lo, hi-lo) //copy back into a
}
```
## 4 Complexity
- n is the length of a plus the length of b
- no obvious counter controlled loop
- key ⇒ in each of the three loops mi in incremented by one.
- ∴ the total number of loop bodies executed is always n
- since each loop has a constant amount of work
- ∴ so total cost is **ϴ(n)**

View File

@ -1,110 +1,11 @@
---
title: "08-mergesort-2"
sr-due: 2022-04-06
sr-interval: 8
sr-ease: 270
tags:
- cosc201
- lecture
---
recall definition of merge sort
- pre ⇒ split
- rec ⇒ sort pieces
- post ⇒ merge
## 1 Complexity
no counters
pre and post pahses are constant and ϴ(n)
so M(n) = ϴ(n) + 2 * M(n/2)
does this even help. what if n is odd
pretend ϴ(n) is $C \times n$
$$
\begin{align*}
M(n) &= C \times n+2 \times M(n/2) \\
&= C \times n+2 \times (C \times (n/2) + 2 \times M(n/4))\\
&= C \times (2n) + 4 \times M(n/4) \\
&= C \times (2n) + 4 \times (C \times (n/4)) + 2 \times M(n/8))\\
&= C \times (3n) + 8 \times M(n/8)\\ \\
&= C \times (kn) + 2^k \times M(n/2^k)
\end{align*}
$$
ends when we find base case
when we get to $n/2^k = 1$
we could split earlier.
the work done base case is (bounded by) some constatn D
so if $k$ is large enough that $n/2^k$ is a base case, we get
$$
M(n) = C \times (kn) + 2^k \times D
$$
how big is $k$
$k <=lg(n)$
so:
$$
M(n) ≤ C \times (n lg(n)) + D(n) = ϴ(n lg(n))
$$
which is true
> In a divide and consiwer algo wher pre and pst processign work are Ο(n) and the division is into parts of size at least n for some contatn c > 0 tge total time complexity is Ο(n lg n) and generally ϴ(n log n)
## 2 Variations of mergesort
unite and conquer
5 | 8 | 2 | 3 | 4 | 1 | 7 | 6
5 8 | 2 3 | 1 4 | 6 7
2 3 5 8 | 1 4 6 7
1 2 3 4 5 6 7 8
```java
public static void mergeSort(int[] a) {
int blockSize = 1;
while(blockSize < a.length) {
int lo = 0;
while (lo + blockSize < a.length) {
int hi = lo + 2*blockSize;
if (hi > a.length) hi = a.length;
merge(a, lo, lo + blockSize, hi);
lo = hi;
}
blockSize *=2;
}
}
```
outer loop is executed lg n times, where n is the length of a
inner loop proceeds until we find a block that "runs out of elements"
inner loop is having 2 x blocksize added each time, to runs most n/2 x blocksize
inside inner is call to merge which is ϴ(blocksize)
### 2.1 complexity from bottom up
- $n$ is the numbe of elemetns in a
- outer loop is executed
![[Pasted image 20220329114859.png#invert]]
### 2.2 improvments
some arrays have sections that are already sorted
you canm
### 2.3 timsort
used by python java rust etc
[mergeosrt](notes/mergeosrt.md)

View File

@ -6,7 +6,7 @@ tags:
---
links: [[notes/cosc-201]]
- [[notes/07-mergesort-1]]
- [[notes/08-mergesort-2]]
- [[notes/09-stacks-and-queues]]
- [[notes/10-heaps-and-heapsort]]
- [07-mergesort-1](notes/07-mergesort-1.md)
- [08-mergesort-2](notes/08-mergesort-2.md)
- [09-stacks-and-queues](notes/09-stacks-and-queues.md)
- [10-heaps-and-heapsort](notes/10-heaps-and-heapsort.md)

156
content/notes/mergeosrt.md Normal file
View File

@ -0,0 +1,156 @@
---
title: "mergesort"
tags:
- cosc201
- algorithm
---
Mergesort is a [divide-and-conquer](notes/divide-and-conquer.md) algorithm. It works by recursively splitting the array in half then merging the two (sorted) halfs together . It has three main steps. These are:
- pre-processing: split the array into two pieces
- recurive step: sort each of the pieces
- post-processing: merge the two pieces
e.g.,
7 5 3 9 1 8 2 5 4 0
7 5 3 9 1 | 8 2 5 4 0
7 5 | 3 9 1 | 8 2 5 | 4 0
5 7 | 1 9 3 | 2 8 5 | 0 4
1 3 5 7 9 | 0 2 4 5 8
0 1 2 3 4 4 6 7 8 9
# 1 Implementation
## 1.1 Merge
Given: a and b are sorted arrays. m is an array whose size is the sum of their sizes
Get: a sorted array containing the elements of a and b
Keep track of indices, ai, bi, and mi of the active location of a, b, and m.
Find which of ai or bi is lesser (break ties is favour of a), and copy that value into m at mi, and increment mi and whichever of ai or bi was used.
Once ai or bi is out of range, copy the rest of the other array into the remainder of m
```java
public static int[] merge (int[] a int[] b){
int[] m = new int[a.length + b.length]
int ai = 0, bi = 0, mi = 0;
while(ai < a.length && bi < b.length) {
if(a[ai] <= b[bi]) m[mi++] = a[ai++];
else m[mi++] = b[bi++]
}
while (ai < a.length) m[mi++] = a[ai++];
while (bi < b.length) m[mi++] = a[bi++];
return m;
}
```
### 1.1.1 Complexity of merge
$\theta(n)$
$n$ is the sum of the lengths of $a$ and $b$
Each time we loop the parameter $mi$ must increase by one, and this parameter runs from $0$ to $n-1$
Since the total number of loop bodies executed is $n$ and each loop does a constant amount of work, the total time complexity is $\theta(n)$
## 1.2 Sort
```java
public static void mergeSort(int[] a) {
int blockSize = 1;
while (blockSize < a.length) {
int lo = 0;
while (lo + blockSize < a.length) {
int hi = lo + 2*blockSize;
if (hi > a.length) hi = a.length;
merge(a, lo, lo + blockSize, hi);
lo = hi;
}
blockSize *= 2;
}
}
```
### 1.2.1 Complexity of Sort
$\theta(n\ lg\ n)$
> In a divide and conquer algorithm where pre and pst processing work are Ο(n) and the division is into parts of size at least n for some contatn c > 0 the total time complexity is Ο(n lg n) and generally ϴ(n log n)
#### 1.2.1.1 Top down
We can split into the three steps to analyse this.
- Pre has constant time i.e., $\theta(1)$
- Post has linear time i.e., $\theta(n)$
Therefore: $M(n) = \theta(n) + 2 \times M(n/2))$
Substitue $\theta(n)$ with $C \times n$ then
$$
\begin{align*}
M(n) &= C \times n+2 \times M(n/2) \\
&= C \times n+2 \times (C \times (n/2) + 2 \times M(n/4))\\
&= C \times (2n) + 4 \times M(n/4) \\
&= C \times (2n) + 4 \times (C \times (n/4)) + 2 \times M(n/8))\\
&= C \times (3n) + 8 \times M(n/8)\\ \\
&= C \times (kn) + 2^k \times M(n/2^k)
\end{align*}
$$
This stops (at least) when we reach the base case of $n/2^k=1$ . We could stop earlier and
If we do a constant amount of work $D$ when we reach the base case we get:
$$
M(n) = C \times (kn) + 2^k \times D
$$
where $k\leq lg(n)$ so:
$$
M(n) ≤ C \times (n lg(n)) + D(n) = ϴ(n\ lg(n))
$$
#### 1.2.1.2 Bottom Up
- Let n be the number of elements in the array, $a$.
- The outer while loop (controlled by blockSize, or $b$) is executed $lg(n)$ times since its upper bound is n and b is doubled each time.
- In the inner loop, the update on lo is to add $2b$ so it is executed $n/(2b)$ times.
- The inner loop merges two arrays of size b, so each instance does $\theta(b)$ work.
- That gives an upper bound on the work done in one instance of the outer loop of the form:
$$
(n/(2b)) \times (A \times b) = (A/2) \times n
$$
and a matching lower bound.
- Thus, the work done in one instance of the outer loop is $\theta(n)$
- And so, the total complexity is $\theta(n\ lg\ n)$.
The bottom-up version does exactly the same thing as the top-down version, just in an apparently different order, so this analysis applies to the top-down version as well.
# 2 Variations of Mergesort
[[unite and conquer]] #unfinished

View File

@ -0,0 +1,56 @@
---
title: "unite-and-conquer"
tags:
- cosc201
---
unite and conquer
5 | 8 | 2 | 3 | 4 | 1 | 7 | 6
5 8 | 2 3 | 1 4 | 6 7
2 3 5 8 | 1 4 6 7
1 2 3 4 5 6 7 8
```java
public static void mergeSort(int[] a) {
int blockSize = 1;
while(blockSize < a.length) {
int lo = 0;
while (lo + blockSize < a.length) {
int hi = lo + 2*blockSize;
if (hi > a.length) hi = a.length;
merge(a, lo, lo + blockSize, hi);
lo = hi;
}
blockSize *=2;
}
}
```
outer loop is executed lg n times, where n is the length of a
inner loop proceeds until we find a block that "runs out of elements"
inner loop is having 2 x blocksize added each time, to runs most n/2 x blocksize
inside inner is call to merge which is ϴ(blocksize)
### 0.1.1 complexity from bottom up
- $n$ is the numbe of elemetns in a
- outer loop is executed
![[Pasted image 20220329114859.png#invert]]
### 0.1.2 improvments
some arrays have sections that are already sorted
you canm
### 0.1.3 timsort
used by python java rust etc