Upload
patience-best
View
146
Download
6
Embed Size (px)
DESCRIPTION
主題 : Sorting ( 排序 ). 解題技巧 什麼是 sorting ? 基本的 sorting 方法 如何使用 qsort 例題講解 : A.299 歷年題目. 什麼是 sorting ?. 將給定的資料按照 特定的順序 排列好 由小到大 由大到小 例: 1, 7, 9, 5, 3 由小到大: 1, 3, 5, 7, 9 由大到小: 9, 7, 5, 3, 1. 什麼是 sorting ?. 只有數字能比大小嗎? John Bob 小明 小華 只要能 定義大小關係 ,就可以 sort - PowerPoint PPT Presentation
Citation preview
1
主題 : Sorting ( 排序 ) 解題技巧
什麼是 sorting ? 基本的 sorting 方法 如何使用 qsort
例題講解 : A.299 歷年題目
2
什麼是 sorting ? 將給定的資料按照特定的順序排列好
由小到大 由大到小
例: 1, 7, 9, 5, 3 由小到大: 1, 3, 5, 7, 9 由大到小: 9, 7, 5, 3, 1
3
什麼是 sorting ? 只有數字能比大小嗎?
John Bob 小明 小華
只要能定義大小關係,就可以 sort J 在 B 之後 John > Bob “明”筆畫比“華”少 小明 < 小華
4
常見的 sorting 演算法 bubble sort merge sort quick sort heap sort integer sort
5
Bubble sort 原理
就像氣泡會往上浮一樣,小的數字必須要往前進,而大的數字就必須往後退 每次比較相鄰的兩個數字,然後將小的放在前面的位置,而大的放在後面的位置
6
Example
1 7 9 5 3
1 7 9 5 3
1 7 5 9 3
1 7 5 3 9
1 7 5 3 9
1 5 7 3 9
1 5 3 7 9
1 5 3 7 9
1 3 5 7 9
1 3 5 7 9
stage 1
stage 2
stage 3
stage 4
7
swap 方法 1:
寫一個 swap 的 function ,每次需要的時侯就可以 call 來用 注意不能直接傳值進去
8
swap example: 將兩個整數互換
void swap( int *a, int *b){
int tmp;
tmp = *a; *a = *b; *b = tmp;
}
int x, y;
swap( &x, &y);
9
swap 方法 2:
利用 #define 定義 swap 變數要記得宣告
10
swap example: 將兩個整數互換
#define swap( x, y) (( t) = ( x), ( x) = ( y), ( y) = ( t))
int t;
swap( x, y);
11
for ( i = 0 ; i <= n – 1 ; i++ ) for ( j = 0 ; j <= n – 2 ; j++)
if ( num[ j ] > num[ j + 1] )swap(&num[ j ] , &num[ j +
1]);
C code
代 n – i – 2 會更快
12
Stable sort 若是要 sort 的東西之中有大小相同的,如果 sort 完之後大小相同的排法是依照兩個東西 input 的順序排列的話,稱為
stable sort ,如果不保證一定按照 input 的順序排的話,稱為 non-stable sort input: 3 5 2 1 3 4 stable sort: 1 2 3 3 4 5
13
Parallel array 有時後在寫程式時為了方便起見會開幾個陣列來儲存而不是用 structure ,這時如果按其中一個
array 的值來 sort 的話,要記得所有的 array 都要跟著做一樣的動作 例 :
a[i] 代表身高, b[i] 代表體重,現在想按照身高來做 sort ,則 b[i] 也應該做相對應的變動才能夠讓 a[i] 和 b[i] 代表同一個人的身高體重
在 swap(a[i], a[j]) 時也應該做 swap(b[i], b[j]) 的動作
14
qsort C 內建的 sort function ,一般來說比用
bubble sort 來的快。 需要自己寫一個 compare function
15
Example: qsortint tbl[] = {5, 6, 12, 3, 20, 8};
int comp_func( const void *a, const void *b){ int c, d; c = *(int *)(a); d = *(int *)(b); if (c > d) return (1); else if (c == d) return (0); else return (-1);}
qsort(tbl, sizeof(tbl) / sizeof(tbl[0]), sizeof(tbl[0]), comp_func);
陣列指標 要 sort 的個數 每個要 sort 的 element 的大小compare function
16
Example: qsort
char tbl[][10] = {“Hello”, “OK”, “Test”, “BBS”, “Book”, “C”};
int comp_func( const void *a, const void *b){ char *c, *d; c = (char *)(a); d = (char *)(b); return (strcmp(c, d));}
qsort(tbl, sizeof(tbl) / sizeof(tbl[0]), sizeof(tbl[0]), comp_func);
17
Example: qsort#include <stdio.h>int num[5] = {1, 7, 9, 5, 3 };int comp_func(const void *a, const void *b){int c, d;
c = *(int *)(a); d = *(int *)(b); return ( c – d );}int main(void){
qsort(num, sizeof(num)/sizeof(num[0]), sizeof(num[0]), comp_func);
/* qsort(num, 5, sizeof(num[0]), comp_func); */
return 0;}
18
qsort and bubble sort bubble sort
執行速度較慢 程式好寫好記,不容易忘
qsort 執行速度較快 需要自己寫 compare function 不熟的話容易忘記格式
19
例題講解 : A.299(http://acm.uva.es/p/v2/299.html)
有一列火車總共有 L 節車廂,每節車廂都有個編號 ( 從 1 ~ L) 。現在車廂的順序亂掉了,而站長希望能把車廂的順序由 1 到 L 排好。唯一能做的方法是把相鄰的兩個車廂順序對調,請問,最少需要做幾次的車廂順序對調工作,而能讓車廂的順序由 1 到 L 排好。 L 最大到 50
20
Sample input/outputSample input:331 3 244 3 2 122 1
Sample output:Optimal train swapping takes 1 swaps.Optimal train swapping takes 6 swaps.Optimal train swapping takes 1 swaps.
總共會有幾組 test case
車廂的長度
車廂的編號
21
讀進 input 需要的資料結構 int case_num
總共有幾個 test case
int L 車廂的長度
int num[50] 每個車廂的編號 因為 L 最大只有 50 ,所以開一個長度 50 的整數陣列就夠了
22
分析 1 3 2
noswap ( 1, 3) 1 3 2 swap ( 2, 3) 1 2 3 noswap ( 1, 2) 1 2 3
4 3 2 1 swap ( 4, 3) 3 4 2 1 swap ( 4, 2) 3 2 4 1 swap ( 4, 1) 3 2 1 4 swap ( 3, 2) 2 3 1 4 swap ( 3, 1) 2 1 3 4 swap ( 2, 1) 1 2 3 4
23
解法 換火車車廂的順序跟 bubble sort 的順序是一樣的 照著 bubble sort 的方法去做,每當 sw
ap 發生的時候就在總次數的地方加一,最後得到的數字就是最少需要換的次數
24
Program structureread_case_num();for ( i = 0; i < case_num; i++){
read_train_length();read_train_number();bubble_sort();// 每次 swap 時把 counter 往上加output_optimal_solution();
}
25
Program#include <stdio.h>#define swap( x, y) (( t) = ( x) , ( x) = ( y), ( y) = ( t))int main(void){
int i, j, k, t, L, case_num, counter, num[50];freopen(“data.in”, “r”, stdin); // 若是要送到 acm online judge ,則這行要拿掉scanf(“%d”, &case_num);for ( i = 0; i < case_num; i++){counter = 0;scanf(“%d”, &L);for( j = 0; j < L; j++)scanf(“%d”, &num[j]);for( j = 0; j < L – 1; j++)for( k = 0; k < L – j – 1; k++)if ( num[k] > num[k + 1]) {counter++;swap( num[k], num[k + 1]);}printf(“Optimal train swapping takes %d swaps. \n”, counter);}return 0;
}
26
例題講解 : H.88.4http://www.cc.nccu.edu.tw/info_race88/Q.pdf
了解題意 input 格式、範圍, output 格式、要求 分析解法,需要什麼資料結構 架構程式,上機實作
27
漏洞與陷阱 漏洞
題目寫著“金、銀、銅牌的分配約為 1: 2: 3” ,那要是人數不是 6 的倍數怎麼辦? 要是有同分的人落在金、銀牌之間的分界處,該怎麼解決? Output 格式,欄位有多寬?不然該怎麼對齊? 輸出 3 中,如果有得獎牌數一樣的國家,該 output 一個或是全部 output ?有順序分別嗎?
陷阱 人名有可能中間有空白字元分開,讀 input 時要特別小心
28
解法 依照得分高低排序
只要能正確的讀入 input ,排序,再 output 就好 計算各種獎牌數量
加個 counter 計算一下獎牌數量 找出得獎牌最多的國家
用陣列計算每個國家得獎的數量 計算平均數、最高分、最低分和全距
簡單的數學式
29
解題重點 如何正確的讀入 input
C 有許多內建的 string function 可以利用,請期待明天的教學
30
歷年題目 練習題
A.10008 What’s Cryptanalysis http://acm.uva.es/p/v100/10008.html
A.10057 A Mid-summer Night’s Dream http://acm.uva.es/p/v100/10057.html
A.612 DNA Sorting http://acm.uva.es/p/v6/612.html
挑戰題 A.10125 Sumsets
http://acm.uva.es/p/v101/10125.html
其他歷年題目 H.88.4
http://www.cc.nccu.edu.tw/info_race88/Q.pdf H.89.1 對對碰
http://www.cc.nccu.edu.tw/info_race89/doc/final_program.doc