mirror of
https://github.com/jackyzha0/quartz.git
synced 2025-12-23 21:04:07 -06:00
auto update
This commit is contained in:
parent
909046b6d6
commit
2a2242f1a2
@ -1,8 +1,14 @@
|
|||||||
---
|
---
|
||||||
title: "04-requirements"
|
title: "04-requirements"
|
||||||
|
sr-due: 2022-04-06
|
||||||
|
sr-interval: 15
|
||||||
|
sr-ease: 232
|
||||||
tags:
|
tags:
|
||||||
- info201
|
- info201
|
||||||
- lecture
|
- lecture
|
||||||
|
sr-due: 2022-04-10
|
||||||
|
sr-interval: 3
|
||||||
|
sr-ease: 250
|
||||||
---
|
---
|
||||||
|
|
||||||
[requirements](notes/requirements.md)
|
[requirements](notes/requirements.md)
|
||||||
|
|||||||
@ -1,17 +1,24 @@
|
|||||||
---
|
---
|
||||||
title: "07-mergesort-1"
|
title: "07-mergesort-1"
|
||||||
|
sr-due: 2022-04-26
|
||||||
|
sr-interval: 23
|
||||||
|
sr-ease: 250
|
||||||
tags:
|
tags:
|
||||||
- cosc201
|
- cosc201
|
||||||
- lecture
|
- 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
|
1. pre ⇒ break apartinto two or more smaller problems whose size add up to at most n
|
||||||
2. Rec ⇒ solve those problems recursively
|
2. Rec ⇒ solve those problems recursively
|
||||||
3. post ⇒ combine solutions into a solution of the original problem
|
3. post ⇒ combine solutions into a solution of the original problem
|
||||||
|
|
||||||
## 1 quicksort
|
## 1.1 quicksort
|
||||||
|
|
||||||
pre ⇒ select pivot and split the array
|
pre ⇒ select pivot and split the array
|
||||||
|
|
||||||
@ -26,79 +33,4 @@ works best of primitive types as they can be stored in the fastest memory locati
|
|||||||
- memory access can be localised and the comparisions are direct
|
- memory access can be localised and the comparisions are direct
|
||||||
- those advantages are limited when sorting objects of reference type
|
- 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
|
- 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
|
- 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)**
|
|
||||||
@ -1,110 +1,11 @@
|
|||||||
---
|
---
|
||||||
title: "08-mergesort-2"
|
title: "08-mergesort-2"
|
||||||
|
sr-due: 2022-04-06
|
||||||
|
sr-interval: 8
|
||||||
|
sr-ease: 270
|
||||||
tags:
|
tags:
|
||||||
- cosc201
|
- cosc201
|
||||||
- lecture
|
- lecture
|
||||||
---
|
---
|
||||||
|
|
||||||
recall definition of merge sort
|
[mergeosrt](notes/mergeosrt.md)
|
||||||
- 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
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ tags:
|
|||||||
---
|
---
|
||||||
links: [[notes/cosc-201]]
|
links: [[notes/cosc-201]]
|
||||||
|
|
||||||
- [[notes/07-mergesort-1]]
|
- [07-mergesort-1](notes/07-mergesort-1.md)
|
||||||
- [[notes/08-mergesort-2]]
|
- [08-mergesort-2](notes/08-mergesort-2.md)
|
||||||
- [[notes/09-stacks-and-queues]]
|
- [09-stacks-and-queues](notes/09-stacks-and-queues.md)
|
||||||
- [[notes/10-heaps-and-heapsort]]
|
- [10-heaps-and-heapsort](notes/10-heaps-and-heapsort.md)
|
||||||
156
content/notes/mergeosrt.md
Normal file
156
content/notes/mergeosrt.md
Normal 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
|
||||||
56
content/notes/unite-and-conquer.md
Normal file
56
content/notes/unite-and-conquer.md
Normal 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
|
||||||
Loading…
Reference in New Issue
Block a user