๋๋์ฒด Stable์ด ๋ญ์ผ?
Stable sort๋ ๋ฐ๋ณต๋ ์์๊ฐ ์ ๋ ฌ๋๋๋ผ๋ ๊ฐ์ ์์๋๋ก ์ ๋ ฌ๋๋ ๊ฒ์ ๋ปํ๋ค.
๋ฌด์จ ์๋ฏธ๋๋ฉด ์ด๋ฐ ์๋ฏธ๋ค.
๊ทธ๋ ๋ค๋ฉด Stability๊ฐ ์ ์ค์ํ๊ฑธ๊น?
์ฌ๋ฌ๊ฐ์ง ์์ฑ์ ๊ฐ์ง ํํ์ ์๊ฐํด๋ณด์. ์ฒซ ๋ฒ์งธ ์์ฑ์ผ๋ก ๊ทธ ํํ์ด ์ด๋ฏธ ์ ๋ ฌ ๋์ด ์๊ณ , ์ด์ ์ฌ์ฉ์๋ ๋ ๋ฒ์งธ ์์ฑ์ผ๋ก ๊ทธ ํํ์ ์ ๋ ฌํ๊ณ ์ถ๋ค. ๊ทผ๋ฐ~ ์ ์๋ฆฌ ์ ๋ ฌ์ด ์๋๋ฉด ์ฒซ ๋ฒ์งธ ์์ฑ์ ์ ๋ ฌ์ด ๊นจ์ ธ๋ฒ๋ฆฌ๋ ๊ฒ์ด๋ค.
Stability๊ฐ ๋๋ ์ ๋ ฌ์ ์กฐ๊ฑด์ ๋ฌด์์ผ๊น?
Insertion sort, merge sort๋ Stableํ ์ ๋ ฌ์ด๋ค. ๋ค๋ฅธ ์ ๋ ฌ์ด๋ ๋ญ๊ฐ ๋ค๋ฅด๊ธธ๋!
less than
vs less than or equal to
Linked List๋ฅผ ์ ๋ ฌํ๋ ค๋ฉด Merge sort๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค. ๊ทธ ์ด์ ๋ Linked list๊ฐ random access ๋ถ๊ฐ๋ฅ
์ด๊ธฐ ๋๋ฌธ์ด๋ค.
Node* merge(Node *a, Node *b) {
Node *result = nullptr;
if(a==nullptr)
return b;
else if(b==nullptr)
return a;
if(a->data <= b->data) {
result = a;
result -> next = merge(a->next, b);
} else {
result = b;
result -> next = merge(a, b->next);
}
return result;
}
์ฌ๊ท์ ์ธ ๋ฐฉ๋ฒ์ผ๋ก ์ด๋ฏธ ์ ๋ ฌ๋ ๋ ์ฐ๊ฒฐ๋ฆฌ์คํธ๋ฅผ mergeํ ์ ์๋ค.
ํฐ ๋ ธ์ด๋ง์ ์ํด ๊ฐ๋ฐ๋์๋ค. ์ ์ฑ๋ฅ์ ๋ณด์ฅํ๋ค.
๋ถํ ์ ๋ณต์ ๊ธฐ๋ฐํ ์ ๋ ฌ๋ก ๋ค์์ ๋ฐ๋ณตํ๋ค.
๐ ๋ ์ ๋ ฌ๋ ๋ฐฐ์ด์ด ์์ ๋ ์ด๋ป๊ฒ ํฉ์น ์ ์์๊น? (ใ ใ )
E!A!S!Y!
void merge(vector<int>& a, vector<int>& aux, int lo, int mid, int hi) {
// why copy needed?
for (int k=lo; k<=hi; ++k) {
aux[k] = a[k];
}
int i = lo, j = mid+1;
for(int k=lo; k<=hi; ++k) {
if(i>mid) a[k] = aux[j++];
else if (j>hi) a[k] = aux[i++];
else if (aux[j]<aux[i]) a[k] = aux[j++];
else a[k] = aux[i++];
}
}
void mergeSort(vector<int>& a, vector<int>& aux, int lo, int hi) {
if (hi<=lo) return;
int mid = (lo+hi)/2;
mergeSort(a, aux, lo, mid);
mergeSort(a, aux, mid+1, hi);
merge(a, aux, lo, mid, hi);
}
๐ Merge sort๋ ์ ๋ ฌํ ๋ N ํฌ๊ธฐ์ ๋ฐฐ์ด์ ์ถ๊ฐ๋ก ์ฌ์ฉํ๋ค.
์์ ์ฝ๋์์ aux ๋ฐฐ์ด์ด merge sort๊ฐ ๋ฐ๋ก ๊ทธ ์ถ๊ฐ๋ก ์ฌ์ฉํ๋ ๋ฐฐ์ด์ด๋ค. ๋ฐ๋ผ์ merge sort๋ in-place sort๊ฐ ์๋๋ค. merge sort๋ in-place๋ก ๊ตฌํํ ์๋ ์์ง๋ง ๋๋ฌด ๋ณต์กํ์ฌ ์ฌ์ฉํ์ง ์๋๋ค.
subarray๊ฐ ์ถฉ๋ถํ ์๋ค๋ฉด, ์ฌ๊ท์ ์ค๋ฒํค๋๋ฅผ ์ค์ด๊ธฐ ์ํด ๋ค๋ฅธ ์ ๋ ฌ์ ํ์.
void mergeSort(vector<int>& a, vector<int>& aux, int lo, int hi) {
if (hi<=lo + CUTOFF - 1) {
insertionSort(a, lo, hi);
return;
}
int mid = (lo+hi)/2;
mergeSort(a, aux, lo, mid);
mergeSort(a, aux, mid+1, hi);
merge(a, aux, lo, mid, hi);
}
์ ๋ ฌ์ด ๋์๋ค๋ฉด ๋ฉ์ถ์.
void mergeSort(vector<int>& a, vector<int>& aux, int lo, int hi) {
if (hi<=lo) return;
int mid = (lo+hi)/2;
mergeSort(a, aux, lo, mid);
mergeSort(a, aux, mid+1, hi);
if(a[mid+1]>=a[lo])
return;
merge(a, aux, lo, mid, hi);
}
auxiliary array์ ๋ณต์ฌํ๋ ๊ณผ์ ์ ์ ๊ฑฐํ์. (์๊ฐ์ ์ ์ฝํ์ง๋ง ๊ณต๊ฐ์ ์ ์ฝํ๋ ๊ฒ์ ์๋์ ์ฃผ์)
void merge(vector<int>& a, vector<int>& aux, int lo, int mid, int hi) {
int i = lo, j = mid+1;
for(int k=lo; k<=hi; ++k) {
if(i>mid) a[k] = aux[j++];
else if (j>hi) a[k] = aux[i++];
else if (aux[j]<aux[i]) a[k] = aux[j++];
else a[k] = aux[i++];
}
}
void mergeSort(vector<int>& a, vector<int>& aux, int lo, int hi) {
if (hi<=lo) return;
int mid = (lo+hi)/2;
mergeSort(aux, a, lo, mid);
mergeSort(aux, a, mid+1, hi);
merge(a, aux, lo, mid, hi);
}
No recursion!!!
void merge(vector<int>& a, int lo, int mid, int hi) {
...
}
void mergeSort(vector<int>& a) {
int N = a.size();
vector<int> aux(N);
for(int sz=1; sz<N; sz+=sz) {
for(int lo=0; lo<N-sz; lo+=2*sz) {
merge(a, lo, lo+sz-1, min(lo+2*sz-1, N-1));
}
}
}
๋๋ถ๋ถ์ ์์คํ ์์ ์ฌ์ฉ๋๊ณ ์๋ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก 1980๋ ์ ๊ฐ๋ฐ๋์๋ค.
Partition!
์ ์๊ฐํด๋ณด๋ฉด partition์ธ a[j]๋ parition ๊ณผ์ ์์ ์๊ธฐ ์๋ฆฌ๋ฅผ ์ฐพ๊ฒ ๋๋ค.
i
์ j
๊ฐ ์๊ฐ๋ฆด ๋๊น์ง ๋ฐ๋ณตํ๋ค.
a[lo]
๋ณด๋ค ํฐ ์์๊ฐ ๋์ฌ ๋๊น์ง i++
a[lo]
๋ณด๋ค ์์ ์์๊ฐ ๋์ฌ ๋๊น์ง j++
i>=j
๊ฐ ์๋๋ผ๋ฉด swap(a[i], a[j])
int partition(vector<int> &a, int lo, int hi) {
int i = lo, j = hi+1;
while(true) {
while(a[++i] < a[lo])
if(i == hi) break;
while(a[lo] < a[--j])
if(j == lo) break;
if(i>=j) break;
swap(a[i], a[j]);
}
swap(a[lo], a[j]);
return j;
}
partition์ ๊ธฐ์ค์ผ๋ก left์ right๋ฅผ ์ ๋ ฌํ๋ค.
void sort(vector<int> &a, int lo, int hi) {
if(hi<=lo) return;
int j = partition(a, lo, hi);
sort(a, lo, j-1);
sort(a, j+1, hi);
// ์ด๋ฏธ a[j]๋ ์๊ธฐ ์๋ฆฌ๋ฅผ ์ฐพ์์ผ๋ฏ๋ก lo~j-1๊ณผ j+1~hi๋ฅผ ์ ๋ ฌํ๋ค.
}
๐ ํต์ํธ์ ์ต๋ ์ฅ์
: in-place ์ ๋ ฌ์ด๋ค. ์ฆ, ์ ๋ ฌ์ ์ํ ์ถ๊ฐ ๊ณต๊ฐ์ด ํ์ํ์ง ์๋ค.
Partitioning in-place
: ์ถ๊ฐ ๊ณต๊ฐ์ ์ฌ์ฉํด์ partitioning์ ์ฝ๊ณ ์ด๋ฅผ ํตํด, stableํ ์ ๋ ฌ์ ํ ์๋ ์์ง๋ง ํต์ํธ๋ฅผ ์ฌ์ฉํ๋ ์ด์ ๋ ์ ์๋ฆฌ์ ๋ ฌ์ด๋ผ๋ ์ ์ด ํฌ๊ธฐ ๋๋ฌธ์ ๊ตณ์ด
Terminatin the loop
: ์ธ์ loop๊ฐ ๋๋๋์ง ์ฃผ์ ๊น๊ฒ ๋ด์ผํจ (ํนํ ์ค๋ณต๋ ํค๊ฐ ์กด์ฌํ ๋)
Equal keys
: ์ค๋ณต ํค๊ฐ ์กด์ฌํ ๋ ์ฃผ์ํ ์ ๋ค์ด ์์ (์ถํ์ ์ค๋ช )
โ ํต์ํธ๊ฐ ๋จธ์ง์ํธ๋ณด๋ค ๋น ๋ฅด๊ธฐ ๋๋ฌธ์ ์ฃผ๋ก ์ฌ์ฉ๋๋ค. ๊ทธ๋ ๋ค๋ฉด ์ ๋น ๋ฅผ๊น?
์ฆ๋ช ๊ณผ์ ์ ์๋ตํ์ง๋ง ๋น๊ต ํ์๊ฐ ํต์ํธ๋ณด๋ค ๋จธ์ง์ํธ๊ฐ ๋ ๋ง๋ค. ๊ทธ๋ฐ๋ฐ ์ ๋น ๋ฅด์ง? ์ด๋ ๋จธ์ง ์ํธ๋ ๊ฐ์ ๋ณต์ฌ ๊ณผ์ ์ ๋น์ฉ๋๋ฌธ์ ํต ์ํธ๋ณด๋ค ๋๋ฆฌ๋ค.
subarray๊ฐ ์ถฉ๋ถํ ์๋ค๋ฉด insertion sort ํ๋ค.
Median of sample
median(a[lo], a[mid], a[hi])
void sort(vector<int> &a, int lo, int hi) {
if(hi<=lo) return;
int m = median(a[lo], a[(lo+hi)/2], a[hi]);
swap(a[lo], a[m]);
int j = partition(a, lo, hi);
sort(a, lo, j-1);
sort(a, j+1, hi);
}
N๊ฐ์ ํญ๋ชฉ์์ k๋ฒ์งธ๋ก ํฐ ์๋ฅผ ์ฐพ์๋ผ
์ด ๋ฌธ์ ๋ 60~70๋ ๋์ ํ๋ฐํ๊ฒ ๋ ผ์๋์๋ ์ฃผ์ ์ด๋ค.
Hoare๋ 1961๋ partitioning์ ๊ธฐ๋ฐํ ํด๊ฒฐ์ฑ ์ ์ ์ํ์๋ค.
partition์ ํน์ง์ ๊ธฐ๋ฐํ๋ค.
a[j]
๋ ์๊ธฐ ์๋ฆฌ์ ์๋ค. int select(vector<int> &a, int k) {
int lo = 0, hi = a.size() - 1;
while(lo<hi) {
int j = partition(a, lo, hi);
if(j<k) lo = j+1;
else if(j>k) hi = j-1;
else return k;
}
return a[k];
}
quicksort์์ ์ค๋ณตํค๊ฐ ๋ง์ผ๋ฉด ์ด๋กํ์ง?
mergesort๋ ๋ฐฐ์ด์ ์ ํํ ์ ๋ฐ์ผ๋ก ๋๋๊ธฐ๋๋ฌธ์ ์ด๋ฐ ํ์์ด ๋ฐ์ํ์ง ์๋๋ค. ํ์ง๋ง quicksort๋ ์ค๋ณต ํค๊ฐ ๋ง์ ๋ ์ค๋ณต ํค์ ๋ํด ํํฐ์
๋์ ์ค๋จํ์ง ์์ผ๋ฉด ์ฑ๋ฅ์ด ์ด ๋๋ค. 1990๋
C ์ฌ์ฉ์๊ฐ qsort()
์์ ์ด ๋ฌธ์ ์ ์ ๋ฐ๊ฒฌํ์๋ค. ์ ๊ทธ๋ด๊น?
์ฒซ ๋ฒ์งธ ๋ฌธ์ ์ ์
์ ํ๋ pivot์ ๊ธฐ์ค์ผ๋ก ์ค๋ณต๊ฐ์ ๊ฐ์ด๋ฐ, ์์๊ฐ์ ์ผ์ชฝ, ํฐ ๊ฐ์ ์ค๋ฅธ์ชฝ์ผ๋ก ๋๋ ๋ฐฉ๋ฒ.
์์ ๊ฐ์ด ํํฐ์ ๋ํ๋ค. ์ด๋ ๊ฒ ํ์ ๋ ์ข์ ์ ์ ๋ญ๊นโฆ
1990๋ ๋๊น์ง๋ ์ด ๋ฐฉ๋ฒ์ด ๊ทธ๋ ๊ฒ ํจ์จ์ ์ด๋ผ๊ณ ์๊ฐํ์ง ์์๋ค. ๊ทธ๋ฌ๋ ๋ค์ต์คํธ๋ผ๊ฐ Dutch national flag promblem์ ๊ณ ์ํ๋ฉด์ 3-way partitioning์ ์ ๋น์ฉ์ผ๋ก ํ ์ ์๊ฒ ๋์๋ค.
๐ pseudo code
1. a[lo]์ ๊ฐ v๋ฅผ pivot์ผ๋ก ์ผ๋๋ค.
2. ์ผ์ชฝ์์ ์ค๋ฅธ์ชฝ์ผ๋ก i๋ฅผ ์ค์บํ์.
- if (a[i] < v): swap(a[lt], a[i]) and lt++; i++;
- if (a[i] > v): swap(a[gt], a[i]) and gt--;
- if (a[i] == v): i++;
๐ code
void sort(vector<int> &a, int lo, int hi) {
if(hi<=lo)
return;
int lt = lo, gt = hi;
int v = a[lo];
int i = lo;
while(i<=gt) {
if(a[i] < v) {
swap(a[lt], a[i]);
lt++; i++;
} else if (a[i] > v) {
swap(a[gt], a[i]);
gt--;
}
}
sort(a, lo, lt-1);
sort(a, gt+1, hi);
}
โ JAVA์์ sort๋ quickSort or mergeSort?
Array.sort()๋ primitive type์ ๋ํด์๋ quicksort๋ฅผ ์ฌ์ฉํ๊ณ , object์ ๋ํด์๋ mergesort๋ฅผ ์ฌ์ฉํ๋ค. ์ ๋ค๋ฅธ ๋ฐฉ์์ ์ฌ์ฉํ ๊น? ๊ทธ ์ด์ ๋ 1. stability 2. ๋ณด์ฅ ์ด๋ค.
System sort๋ ๋๋ถ๋ถ quick sort
๋ฅผ ๊ธฐ๋ณธ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ์ฌ์ฉํ๋ค. ๊ทธ๋ฆฌ๊ณ ๋ค์๊ณผ ๊ฐ์ ์ต์ ํ๋ฅผ ์ถ๊ฐ๋ก ํด์ค๋ค.
partitioning item (pivot)
Median of the median of 3 samples, each of 3 entries
๋๋ค์ด ์๋ ๋ฐฐ์ด์ ๋ํด ํต์ํธ๋ ์ ์ฑ๋ฅ์ ๋ณด์ฅํ ์ ์๋ค. ๋ฐ๋ผ์ ์ ๋ ฌ ์ ์ ๋ณดํต random shuffling์ ์งํํ๋ค. (์ง์ง ๊ฐ?)
๊ฐ๊ฐ์ ์๋ฆฟ์๋ฅผ ๊ธฐ์ค์ผ๋ก ์ ๋ ฌํ๋ค.
stable sort