ARRAY 和朋友們
Michael Tsai
2010/10/01 作業 1 開始寫了 沒 ?
作業 1 題目有少數更動 . 請上 課程網站下載 .
點
今日菜單
•
複習上次教過 ( 以及沒教完 ) 的部分•
陣列•
陣列的朋友們• 多項式
• 字串
• 矩陣
•
都是中文•
Slides 底色是白的 ( 比較好印 )•
希望大家可以醒著久一點Asymptotic notation 有什麼用 ?
•
知道當 input” 大小”改變的時候 , 執行速度有什麼改變?
•
“ 粗略”的比較•
a, bn, c 都”比較不重要”•
bn, c 都”成長得”比較慢•
不同的 a 差別不是很大•
讓我們看看不同的” order” 長的速度差別有多大…•
n n
1 秒 10 億指令的機器的執行速度
兜基 ??
Θ ( �) Θ ( �)
Θ ( �
2)
Θ ( �
2)
�
2ms
�
2ms
10 10
66� �� � ��
哪一個好…
•
n 很大的時候右邊比左邊好•
但是 n 會很大嗎 ?•
有時候不會•
如果 n 永遠小於 ??•
結論 : 要看 n 大小 ( 實際上寫程式的時候適用 )•
Θ ( �) Θ ( �)
Θ ( �
2)
Θ ( �
2)
�
2ms
�
2ms
10 10
66� �� � ��
Asymptotic notation – Big OH
•
Definition [Big “oh”]:if and only if there exist positive constants and such th at for all .
•
“f of n is big oh of g of n”•
“=“ is “is” not “equal”•
•
Asymptotic notation – Omega
•
Definition [Omega]:if and only if there exist positive constants and such th at for all .
•
“f of n is omega of g of n”•
Asymptotic notation – Theta
•
Definition [Theta]:if and only if th ere exist positive con stants , and such th at for all .
•
“f of n is theta of g of n”•
Theta Platform
GMC Terrain
用圖表示
•
Big Oh•
紅色•
Omega•
藍色•
Theta•
紅色藍色都要•
•
•
•
for all for all
Example
•
(1)•
for all for all
•
for all for all
有用的 Theorem ( 別睡著 )
•
Theorem: If , then .•
Proof:, for all . So,
•
�
�− �≤ 1
分析演算法
•
複習 :•
程式花的時間 :• Compile time
• Run (execution) time
•
程式花的空間 :• Fixed space requirement
• Variable space requirement
•
實用上 , 大多使用 Big Oh•
表示最糟的狀況也不會比 Big Oh 裡面的 order 糟� ( � ) =� +�
�( � )
� ( � ) = �+ �
�( � )
那麼 , 怎麼知道程式的時間複雜度
?
•
看每個 statement 執行幾次 , 畫表來計算•
今天會看到不少例子•
有時候複雜度跟 input 大小不一定有關係•
這時候就會取 average case, worst case, best case•
實際測量程式執行時間 ( 作業有 ) 最實際再看一次簡單的例子
Statement Asymptotic complexity void add(int a[][MAX_SIZE]…) { 0
int i,j; 0
for(i=0;i<rows;i++) for(j-0;j<cols;j++)
c[i][j]=a[i][j]+b[i][j];
} 0
Total
Statement Asymptotic complexity void add(int a[][MAX_SIZE]…) { 0
int i,j; 0
for(i=0;i<rows;i++) for(j-0;j<cols;j++)
c[i][j]=a[i][j]+b[i][j];
} 0
Total
接下來 , 讓我們看點有趣的 ~~~
2010/03/26 在 Carnegie Mellon University 的 Lab 中努力焊板子
Array 是什麼東東
•
帶狀的記憶體 , 連續的 , 一格一格的•
每一格存不同的資料•
每一格有個編號•
我們可以把它看成是一個 index 和 value 的關聯或者對應•
很像是電腦記憶體的結構 , 所以常常被拿來當作基本元素ㄅ ㄐ ㄖ ㄊ ㄟ ㄌ
0 1 2 …
Array 支援那些動作 ?
•
創造一個 array•
讀取某格子的值•
寫入某格子的值•
毀掉一個 array?< 複習時間 > C 語言
•
int list[3];•
降子的話 , list[i] 是去記憶體哪邊拿值 ?•
這邊 : list + i* sizeof (int)•
那這樣呢 ? *(list+i)•
會拿到同樣一個值•
C 會看 list 是哪種 type 的 pointer•
然後自動把 i 乘以 sizeof(type)1 4 5
0 1 2 0-
3
4- 7
8- 11 index
addres: s:
lis t
< 複習時間 > C 語言
void change_array(int a[], int b) {
a[0]=10;
b=10;
}
int main() {
int foo[2];
int bar=0;
int i;
foo[0]=0;
change_array(foo, bar);
printf("foo[0]=%d bar=%d\n", foo[0], bar);
return 0;
• }
答案 : foo[0]=10 bar=0 bar:“call-by-value”
foo:“call-by-value”, 但是 foo 是 address
最好多一個參數表示 array 的大 小
< 複習時間 > C 語言
•
如果事先不知道資料大小怎麼辦 ?•
開太大浪費 , 開太小不能用•
知道了再開•
請愛用 malloc.•
Example:•
我要開一個大小 n 的陣列 list( 注意 n 是變數喔 )•
int * list;•
list=(int*)malloc(sizeof(int)*n);< 複習時間 > C 語言
•
calloc : 跟 malloc 差不多 不過會把內容先都清成 0•
realloc: 之前用 malloc 拿的空間 , 可以用 realloc 變大 變小•
free: 不用了 , 把之前拿來的空間還給系統•
怎麼用 ? 請自己看 man page or help那麼二維的陣列呢 ?
•
C 是這樣玩 - 如果我要宣告 int x[3][5]:•
比如說 , 怎麼拿到 x[1][3] 的值 ?x[
x[0]
1]x[
2]
指標們
[0 ]
[1 ]
[2 ]
[3
] [4 ]
放資料的地方
那麼三維的陣列呢 ?
•
請一位同學來畫 , 並解釋運作的方式有沒有別的方法 ?
•
指標一直指來指去好麻煩 •
用一個一維陣列表示多維陣列好不好 ?•
例子 : 假設我要宣告 int list[3][5]•
請一位同學來畫圖 :D•
怎麼宣告 ? ( 要幾個元素 ?)•
怎麼拿值 ? ( 我要 index=(i,j) 的值 )•
二維 : “Row major” v.s. “column major”< 複習時間 > C 語言 趴兔
• 什麼是 Structure?
• 例子 :
struct { char name[10];
int age;
float salary;
} person;
struct person pa;
pa.age=25;
Part II
< 複習時間 > C 語言 趴兔
•
怎麼比較兩個 structure variable 一不一樣 ?•
struct person a, b;•
if (!strcmp(a.name, b.name) &&•
a.name==b.name && ….)•
ANSI C 可以讓你直接比 •
if (a==b)•
也可以直接 assign•
a=b;< 複習時間 > C 語言 趴兔
• 什麼是 enum?
• 什麼是 union?
• typedef 幹嘛用的 ?
• 例子 :
typedef struct sexType {
enum tagField {female, male} sex;
union { int children;
int beard;
}u;
}
sexType si;
si.sex=male;
si.u.beard=0;
Part II
朋友一 : 多項式
• 問題 : 我想要把多項式存起來,方便做加法 ( 可能還有別的 動作 )
• 多項式 :
• 提示 : array 是它的朋友
• 這樣存方不方便作加法 ?
• 有沒有什麼壞處 ?
•
�
0�
1�
2�
3 …�
�0 1 2 3 n
index 代表指數 value 存係數
很鬆的多項式
•
如果是 要怎麼存 ?•
浪費了 999 個格子 T_T•
有沒有什麼更好的方法 ?•
1
0
0
0
…2
0 1 2 3 1000
index 代表指數 value 存係數
很鬆的多項式
2 1 1 10 3 1
1000 0 4 3 2 0
存指數 存係數
startA finishA startB finishB
•
用兩個變數 (start, finish) 存多項式的開始與結束的 index•
照指數大排到小那麼 , 加法怎麼運作呢 ?
•
題目 : 多項式 A 和多項式 B 乘起來的結果要放到 C( 新的 )•
先想一想2 1 1 10 3 1 ?? ??
1000 0 4 3 2 0 ?? ??
startA finishA startB finishB
…
startC, finishC 存指數
存係數
舉個例子好了
2 1
1000 0
1 10 3 1
4 3 2 0
多項式 A 多項式 B
多項式 C 2 1000
2 1 10
1000 4 3
2 1 10 3
1000 4 3 2
2 1
1000 4
2 1 10 3 1
1000 4 3 2 0
Time complexity = O(??)
接下來看一下程式
•
Program 2.6 on page 70•
Time complexity=????•
有沒有什麼缺點 ??朋友二 : 字串
•
C 語言的字串是怎麼表示的 ? (Representation)•
char foo[]=“data “;•
看起來像這樣子•
字串可以做什麼動作 ?•
超多的 !• 把 B 字串附在 A 字串後面 strcat
• 比較兩個字串是不是完全一樣 strcmp
• 還有什麼 ?…
• (< 複習時間 >: 回去自己看一下 string.h 裡面有哪些 function)
d a t a \0
< 動腦時間 >
•
題目 : 把 t 字串插入 s 字串位置為 i 的地方 , 結果放到 s•
t 字串 : amobile•
s 字串 : uto•
i=1•
那麼結果應為 automobile先看一個爛方法
•
方法 :• 開一個新的 temp 字串
• 把 i 之前的 a 字串 copy 過去 temp
• 然後把 b 字串 copy 過去 temp
• 然後把 i 之後的 a 字串 copy 過去 temp
• 然後把整個 temp 字串 copy 到 b
•
為什麼不好 ?• Space
• Time
•
請同學們想出一個好一點的方法< 動腦時間 > 趴兔
•
題目 : 在 s 字串裡面找 p 字串第一次出現的位置 , 如果 有的話 output 出 p 字串在 s 字串裡面開始的位置 . 如果 沒有的話 output -1.•
例子 :• s 字串 : abcbabcabca
• p 字串 : abca.
• output: 4
Part II
先看一個爛方法
•
方法 :• 比對 s 字串裡面從第一個字元開始是不是跟 p 字串一樣
• 比對 s 字串裡面從第二個字源開始是不是跟 p 字串一樣
• 一直比到 s 字串的最後一個字元或者找到為止
•
為什麼不好 ?•
Time complexity = O(??)大師們的好方法
•
KMP: Knuth, Morris, and Pratt•
可以達到 O(n+m).•
意思就是說 , 每個在 p 和 s 的字元都只需要處理一次• order 來講不可能更好了
•
這個神奇的方法 , 大意是什麼呢 ?• 如果 p 裡面有重複出現的 pattern 的話 , 要記得
• 如果比對到一個不對的字元 , 就退到前一次出現同樣 pattern 的下 一個字源繼續開始比較就好了
例子
•
p=“abcabcacab”•
s=“abcabcabcacab”a b c a b c a b c a c a b a b c a b c a c a b
Failure function
•
定義 :•
例子 :•
a b c a b c a c a b
f
Failure function
•
另外一個定義 (recursive)•
a b c a b c a c a b
f -1 -1 -1 0 1 2 3 -1 0 1
Failure function
•
那麼 , 算 failure function 的 time complexity=O(??)•
答案 : O(strlen(pat))有了 failure function 以後要怎麼用呢 ?
•
舉個例子a b c a b c a b c a c a b id
x 0 1 2 3 4 5 6 7 8 9
a b c a b c a c a b
f -1 -1 -1 0 1 2 3 -1 0 1
Knuth–Morris–Pratt algorithm
•
看一下程式 , 看能不能理解•
O(n+m)• 每個字元處理過一遍 , order 無法更好的演算法
•
利用 failure function 記得 , 現在這邊最近幾個字元的 p attern 是不是前面一開始也出現過•
如果比對錯了 , 就回到前一個字元的 failure function 的位置的下一個字元開始比對朋友三 : 矩陣
•
怎麼存起來 ?•
用二維陣列 , a[ 行 ][ 列 ] 來存•
加法乘法都很容易•
很鬆的矩陣
•
浪費很多空間在存 0•
有沒有什麼節省空間的方法可以存 ?•
很鬆的矩陣
•
存法 :•
ind ex
0 1 2 3 4 5 6 7 8
Row 6 0 0 0 1 1 2 4 5
Col 6 0 3 5 1 2 3 0 2
valu e
8 15 22 -15 11 3 -6 91 28
空間省了 , 但是…
•
如果要做 transpose…•
直接把 row & col 的值交換 ?•
這樣就沒有照順序了 ( 以 row 為主 )ind
ex 0 1 2 3 4 5 6 7 8
Row 6 0 3 5 1 2 3 0 2
Col 6 0 0 0 1 1 2 4 5
valu
e 8 15 22 -15 11 3 -6 91 28
1 5
¿
¿¿
11 3
¿ 2 2 ¿ − 15
¿ − 6 ¿
91 ¿ 28
¿ ¿ ¿
¿ ¿
¿
15 ¿ ¿
11 ¿3 91
[
¿ ¿¿ ¿¿− 152228 ¿− 6¿ ❑]
< 動腦時間 >
•
怎麼用 O(columns+elements) 的時間做完 transpose?•
當不鬆的時候 , 就變成 O(columns+elements)=O(columns+columns*rows)=O(columns*rows)
•
怎麼做 ? 當做回家習題 請看 program 2.9 (p.78)那麼 , 矩陣乘法呢 ?
•
不順 ( 希望同樣 column 的會放在一起 )•
所以可以先 Transpose1 5
¿
¿¿
11 3
¿ 2 2 ¿ − 15
¿ − 6 ¿
91 ¿ 28
¿ ¿ ¿
¿ ¿
¿
1 5¿
¿¿
11 3
¿ 2 2 ¿ − 15
¿ − 6 ¿
91 ¿ 28
¿ ¿ ¿
¿ ¿
¿
實際乘乘看
•
類似之前的”鬆多項式”加法•
比較兩邊的 row & col 數•
a<b a 移到下一項•
a==b 可以相乘 , 乘起來以後的值存起來•
a>bb 移到下一項1 5
¿
¿¿
11 3
¿ 2 2 ¿ − 15
¿ − 6 ¿
91 ¿ 28
¿ ¿ ¿
¿ ¿
¿
1 5¿
¿¿
11 3
¿ 2 2 ¿ − 15
¿ − 6 ¿
91 ¿ 28
¿ ¿ ¿
¿ ¿
¿
看看程式
•
program 2.10 和 2.11 (p.81)•
這個程式比較複雜 , 如果看不懂回家請再多花時間 •
Time complexity = O(??)•
複雜度也很複雜 , 請也多花時間休息時間
周末愉快 ~
•
希望今天有上完•
沒有上完的話 , 下周繼續•
請踴躍發表今天上課的感想Michael
Pittsburgh 2009 年大雪 ( 有史以來第 三大 )