Sorting and Binary Search
基礎排序與二分搜
Laurice
時間複雜度
- 回想一下找最大值的時候我們怎麼做
int max = 0, i;
for(i=0;i<size_arr;i++){
if(max< arr[i])
max = arr[i];
}
// max is the answer最多跑幾次?
常數 * size_arr
時間複雜度
Big O notation
的意思是,當n夠大時,我們可以找到一個常數c,
使得
例如:
如果把n當成輸入的個數,Big O代表的其實就是跑的時間的上界
時間複雜度
- 我們學過的東西的時間複雜度?
- 找n個數裡的最大值?
- 掃過所有數字選出最大的 ->
- 判斷一個數字n是不是質數(這裡的n是數字大小)
- 掃過 2~n ->
- 掃過 2~ ->
- 給定平面上n個點,找最近點對
- 枚舉所有點對並找出最小值 ->
- 找n個數裡的最大值?
- 為什麼需要知道時間複雜度?
- 因為我們在意當問題規模變大時,演算法花的時間會增加多少
- 常數會隨著語言、機器而變,所以Big O中省略常數
時間複雜度
- 今天要講的排序是最基本的方法:時間複雜度
- Selection Sort 選擇排序法
- Insertion Sort 插入排序法
- Bubble Sort 泡沫排序法
Sorting
基礎排序
選擇排序法 Selection Sort
核心觀念:
假設現在要由小排到大
- 把資料分成排好序跟未排序兩邊
- 每次都從未排序的那邊拿最小值放到排序好的那邊
- 全部都變已排序就排完了
已排序
未排序
最小的元素
選擇排序法 Selection Sort
未排序
20 15 -23 60 -80 由小排到大
已排序部分
未排序部分
20 15 -23 60 -80
20 15 -23 60
-80
20 15 60
-80 -23
20 60
-80 -23 15
60
-80 -23 15 20
-80 -23 15 20 60
選擇排序法 Selection Sort
未排序
- 時間複雜度
- 有n個元素
- n次之後才會把所有的元素排好
- 每次裡面都要看n個元素(找最小值)
- Code怎麼寫?
- 一個大的for loop一個一個丟東西到已排序那邊
- 一個小的for loop找最小值
選擇排序法 Selection Sort
就直接照著剛剛的方法,開一個新陣列放排序好的吧~
#include<iostream>
int main(){
int unsorted[10] = {7, 4, 8, 2, 6, 3, 100, 9, 22, -20};
int sorted[10];
int i, j, min_index = 0;
for(i=0;i<10;i++){
for(j=0;j<10;j++){
if(unsorted[j]<unsorted[min_index])
min_index = j;
}
sorted[i] = unsorted[min_index];
unsorted[min_index] = 1000;
}
for(i=0;i<10;i++)
std::cout << sorted[i] << " ";
return 0;
}
選擇排序法 Selection Sort
記憶體雖然不用錢,但是能省則省啊
#include<iostream>
int main(){
int unsorted[10] = {7, 4, 8, 2, 6, 3, 100, 9, 22, -20};
int i, j, min_index;
for(i=0;i<10;i++){
min_index = i;
for(j=i;j<10;j++){
if(unsorted[j]<unsorted[min_index])
min_index = j;
}
//swap
int tmp = unsorted[i];
unsorted[i] = unsorted[min_index];
unsorted[min_index] = tmp;
}
for(i=0;i<10;i++)
std::cout << unsorted[i] << " ";
return 0;
}
插入排序法 Insertion Sort

- 一樣分成排好跟未排好
- 一直向左邊比,如果順序不對就交換
- 直到相對順序是對的
左邊的圖接下來怎麼跑?
插入排序法 Insertion Sort
#include<iostream>
int main(){
int array[10] = {293, 422, 12, 31, 41, 21, 33, 55, 2, 10};
int n, i, j, length = 10;
for (i = 1; i < length; ++i)
{
n = array[i];
for (j = i - 1; j >= 0 && array[j] > n; --j)
array[j + 1] = array[j];
array[j + 1] = n;
}
for(i=0;i<length;i++)
std::cout << array[i] << " ";
return 0;
}
泡沫排序法 Bubble Sort
顧名思義,
他就是個像泡沫一樣的排序法?
像泡泡一樣,密度小的一直往上跑
數值大的一直往後跑

泡沫排序法 Bubble Sort
- 比較相鄰的元素,如果前者比後者大,就交換他們兩個。
- 再換下一對相鄰的元素做一樣的事
- 針對所有的元素重複以上的步驟,除了最後一個。
- 持續每次對越來越少的元素重複上面的步驟,直到沒有任何一對數字的順序是錯的。
由小排到大
泡沫排序法 Bubble Sort
- Code 怎麼寫呢?
- 雙層for loop
#include <iostream>
void bubble_sort(int arr[], int len) {
int i, j, temp;
for (i = 0; i < len - 1; i++){
for (j = 0; j < len - 1 - i; j++){ //最後i個是已經浮(?)好的
if (arr[j] > arr[j + 1]) {
temp = arr[j]; //swap
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
int main() {
int arr[] = { 22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70 };
int len = 14;
bubble_sort(arr, len);
int i;
for (i = 0; i < len; i++)
std::cout << arr[i] << " ";
return 0;
}注意:j的index上界是len - 1 - i,Why??
練習:#369 書瑾與他的泡泡們
Binary Search
二分搜尋法
如何搜尋
假設現在給你一個已經由小到大排好的陣列
- 找出最大值
- 找出最小值
- 找出第二大的值
- 找出第K大的值
- 找出裡面有沒有36
難道我真的要整個陣列走一次嗎.....
要整個陣列走一次嗎.....
走一次嗎.....
嗎.....
如何搜尋
假設現在給你一個已經由小到大排好的陣列
| 1 | 4 | 100 | 232 | 2111 | 20321 |
|---|
Max
Min
但要找特定數字,像是36? 30000?
二分搜 Binary Search
顧名思義,就是一次切兩份搜
ex. 找20321
| 1 | 4 | 100 | 232 | 2111 | 20321 |
|---|
round1
round2
二分搜 Binary Search
| -122 | 4 | 24 | 34 | 47 | 48 | 55 | 65 | 80 | 80 |
|---|
return the index of 48
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
|---|
二分搜 Binary Search
Code 怎麼寫?
1. 每一輪都有左index: left 跟右index: right
2. [ left, right ) -> 含左不含右
3. mid = (left + right)/2
4. arr[mid] > num :在mid左邊,right = mid
arr[mid] < num :在mid右邊,left = mid + 1
arr[mid] == num :找到了!!
給定一個由小排到大的陣列
二分搜 Binary Search
#include<iostream>
int binary_search(int arr[], int size, int goal){
int left = 0, right = size, mid; //含左不含右
while(left < right){ //如果左界與右界相等,是發生什麼事了呢?
mid = (left + right)/2;
if(arr[mid] == goal)
return mid;
else if(arr[mid] > goal)
right = mid;
else if(arr[mid] < goal)
left = mid + 1;
}
return -1; //while loop跑完還沒找到,回傳-1表示要找的東西不在裡面
}
二分搜 Binary Search
如果給你的資料是由大排到小呢?
判斷新的left, right的方法不一樣
二分搜真的有比較快嗎?
- 一個個看:O(n)
- 二分搜 :O(log n)

y = x
y = log x
以上講的都是對數字做比較跟搜尋,
還有什麼可以排序跟搜尋呢?
字串!!
strcmp(str1, str2) 回傳值的意義:
等於0: 兩個字串一樣
大於0: 前面的字串字典序比較大 (ex. apple > abuse)
大於0: 前面的字串字典序比較小 (ex. apple < banana)
Any Questions?
再說一次,我叫LauriceXD
Sorting and Binary Search
By austinlaurice
Sorting and Binary Search
for CSIE sprout
- 1,388