ch01資料結構導論

Download Report

Transcript ch01資料結構導論

親愛的老師您好
感謝您選用本書作為授課教材,博碩文化準備本書精選簡報檔,
特別摘錄重點提供給您授課專用。
說明:
1、本教具為非賣品,不得作為商業之用。
2、本教具僅授權使用原著作為授課教材之教師作為教學或研究等學術用途。
3、本教具未授權提供學生任何拷貝、影印、引用、翻印等行為。
4、教師若需申請網站或內容授權,可透過您的博碩業務協助處理,謝謝。
博碩文化:
總公司:台北縣汐止市新台五路一段94號6樓A棟
電話:(02) 2696-2869 分機 313 傳真:(02) 2696-2867
網址:www.drmaster.com.tw
客服信箱:[email protected]
出書提案信箱 [email protected]
資料結構
請老師填入姓名主講
課本:圖解資料結構
博碩文化出版發行
第一章 資料結構導論
課前指引
資料結構科學可稱得上是近十幾年來蓬勃興起的一門新興科
學,他的研究重點是在電腦程式設計領域中,如何將電腦中相
關資料的組合,以某種方式組織而成,然後在這樣的定義下,
就可以談討各種有意義的操作與關係,藉以提升程式設計上的
執行績效。
章節大綱
1-1 資料結構簡介
1-5 遞迴演算法
1-2 資料抽象化
1-6 程式效能分析
1-3 演算法與程式設計
1-4 程式設計的風格
備註:可依進度點選小節
1-1
資料結構簡介
資料結構的應用
樹狀結構
一種相當重要的非線性資料結構,廣泛運用在如人類社
會的族譜或是機關組織、計算機上的MS-DOS和Unix作業
系統、平面繪圖應用、遊戲設計等
最短路徑
功用是在眾多不同的路徑中,找尋行經距離最短、或者
所花費成本最少的路徑,如都市運輸系統、鐵道運輸系
統、通信網路系統等。
搜尋理論
是一種自動從網際網路的眾多網站中蒐集資訊,經過一
定整理後,提供給使用者進行查詢的系統,例如Yahoo
、Google、蕃薯藤等。
5
1-1
資料結構簡介
演算法(1/2)
輸入(Input)
在演算法的處理過程中,通常所輸入資料可有可無,零
或一個以上都可以。
有效性(Effectiveness)
每個步驟都可正確執行,即使交給不同的人用手動來計
算,也能達成相同效果。
明確性(Definiteness)
每一個步驟或指令必須要敘述的十分明確清楚,不可以
模糊不清來造成混淆。
6
1-1
資料結構簡介
演算法(2/2)
有限性(Finiteness)
演算法一定在有限步驟後會結束,不會產生無窮迴路,
這是相當重要的基本原則。
輸出(Output)
至少會有一個輸出結果,不可以沒有輸出結果。
7
1-1
資料結構簡介
演算法描述工具(1/5)
流程圖
流程圖的繪製方向應由上至下,由左至右。
8
1-1
資料結構簡介
演算法描述工具(2/5)
虛擬語言
是一種接近高階程式語言寫法的語言,不過不能直接放
進電腦中執行。
以下是利用輾轉相除法求整數m與n的SPARKS遞迴演算法
Procedure GCD(m,n)
if n=0 then return (m) else
return (GCD(n,m mod n))
endif
end
9
1-1
資料結構簡介
演算法描述工具(3/5)
圖形
如陣列、樹狀圖、矩陣圖等,以下是是井字遊戲的某個
決策區域,利用決策樹圖形來表示其演算法:
10
1-1
資料結構簡介
演算法描述工具(4/5)
敘述表示法
演算法如下:
1.I=1,2,…5循序輸入Student-Name(I)、Chinese(I)、Math(I)、
English(I)。
2.計算Average(I)=(Chinese(I)+Math(I)+English(I))/3
3.印出Average(I)及Student-Name(I)
4.如果Average(I)>60,則加印“這位同學的平均分數是及格”
。
5.結束
11
1-1
資料結構簡介
演算法描述工具(5/5)
程式語言
以下演算法是以C/C++語言來計算所輸入兩數x、y的xy
值函數Pow():
float Pow( float x, int y )
{
float p = 1;
int i;
for( i = 1; i <= y; i++ )
p *= x;
return p;
}
12
1-2 資料抽象化
基本資料型態
如果基本資料型態更高一層,是指一個資料型態
包含其他的資料型態,稱為延伸型資料型態
(Derived Data Type),或組合資料型態。
例如C中的結構(structure)型態,或C++中的字串
(string)或類別(class)型態。
13
1-2 資料抽象化
抽象資料型態
如果是一種自訂資料型態,可簡化一個資料型態的
表現方式及操作運算,並提供使用者以預定的方式
來使用這個資料型態。
堆疊(Stack)或佇列(Queue),就是很典型的ADT
堆疊的運作圖示
14
1-3 演算法與程式設計
認識程式設計(1/2)
需求與目的
了解程式所要解決的問題,並搜集相關的輸入資訊與期
望得到的輸出結果。
設計與規劃
根據撰寫此程式的目的、程式的使用者、滿足需求的軟
硬體環境等,來著手設計這個程式演算法的描述。
分析與討論
思考其他可能適合的演算法及資料結構,最後再選出最
適當的標的,還必須考慮到可讀性、穩定性及可維護性
等因素。
15
1-3 演算法與程式設計
認識程式設計(2/2)
撰寫與編輯
事先必須選擇所需的程式語言,再依據演算法來繪製流
程圖,最後進行程式碼的撰寫。
測試與偵錯
最後必需確認程式的輸出是否符合需求,並進行包括所
謂「語意錯誤」 (Semantic Error)、「語法錯誤」
(Syntax Error)與「邏輯錯誤」(Logical Error)等相
關測試與除錯工作。
16
1-4 程式設計的風格
由上而下與模組化設計
例如C是相當符合模組化設計精神的語言。
C程式本身就是由各種函數所組成,所謂函數,就
是具有特定功能的指令集合,各位就可把它視為一
種模組。
C的主程式其實就包含了最大的函數就是main(),
還可區分為系統本身提供的標準函數及使用者自行
定義的自訂函數。
17
1-4 程式設計的風格
可讀性設計
適時使用「註解」就是提高程式可讀性的第一步。
程式可讀性和可偵錯性的因素,最好將程式碼中的
識別字名稱定義為較具體且有意義。
一個程式的程式碼就像一篇文章一樣,是由一個或
數個程式區塊(Block)所構成,而程式區塊就像文
章中的段落。
程式區塊,就是由{}左右兩個大括弧所組成,包含
了多行或單行的指令。
18
1-4 程式設計的風格
控制結構設計(1/3)
循序結構
是一個程式敘述由上而下接著一個程式敘述的執行指令
,如下圖所示:
19
1-4 程式設計的風格
控制結構設計(2/3)
選擇結構
是一種條件控制敘述,包含有一個條件判斷式,如果條
件為真,則執行某些程式,一旦條件為假,則執行另一
些程式。如下圖所示:
20
1-4 程式設計的風格
控制結構設計(3/3)
重覆結構
主要是迴圈控制的功能。迴圈(Loop)會重複執行一個程
式區塊的程式碼,直到符合特定的結束條件為止。依照
結束條件的位置不同分為兩種:
前測試型迴圈
後測試型迴圈
21
1-5 遞迴演算法
遞迴的定義(1/3)
C的遞迴函數演算法
int factorial(int i)
{
int sum;
if(i == 0) //跳出執行過程的出口
return(1);
else
sum = i * factorial(i-1); //反覆執行的遞迴過程
return sum;
}
22
/*用遞迴函數求 n階乘的值*/
#include <stdio.h>
#include <stdlib.h>
int factorial(int); /*函數原型*/
int main()
{
int i,n; 請以C語言,設計一個計算n!的遞迴程式。
printf("請輸入階乘數:");
scanf("%d",&n);
for (i=0;i<=n;i++)
printf("%d !值為 %3d\n", i,factorial(i));
system("pause");
return 0;
}
int factorial(int i)
{
int sum;
if(i == 0)/* 遞迴終止的條件 */
return(1);
else
sum = i * factorial(i-1); /* sum=n*(n-1)!所以直接呼叫本身 */
return sum;
}
1-5 遞迴演算法
範例 1.5.1
23
1-5 遞迴演算法
遞迴的定義(2/3)
直接遞迴(Direct Recursion)
指遞迴函數中,允許直接呼叫該函數本身,稱為直接遞
迴(Direct Recursion)。如下例:
int Fun(...)
{
.
.
if(...)
Fun(...)
.
.
}
24
1-5 遞迴演算法
遞迴的定義(3/3)
間接遞迴(Direct Recursion)
指遞迴函數中,如果呼叫其他遞迴函數,再從其他遞迴
函數呼叫回原來的遞迴函數,我們就稱做間接遞迴
(Indirect Recursion) :
int Fun1(...)
{
.
.
if(...)
Fun2(...)
.
.
}
int Fun2(...)
{
.
.
if(...)
Fun1(...)
.
.
}
25
1-5 遞迴演算法
費伯那序列
是一序列的第零項是0、第一項是1,其它每一個序
列中項目的值是由其本身前面兩項的值相加所得。
從費伯那序列的定義,也可以嘗試把它轉成遞迴的
形式:
int fib(int n)
{
if(n==0)return 0;
if(n==1)
return 1;
else
return fib(n-1)+fib(n-2);//遞迴引用本身2次
}
26
#include <stdio.h>
#include <stdlib.h>
int fib(int);
/* fib()函數的原型宣告 */
int main()
{
int i,n;
printf("請輸入所要計算第幾個費式數列:");
請以C來設計一個計算第n項費伯那序列的遞迴程式
scanf("%d",&n);
for(i=0;i<=n;i++)
/* 計算前1n個費氏數列 */
printf("fib(%d)=%d\n",i,fib(i));
system("pause");
return 0;
}
int fib(int n)
/* 定義函數fib()*/
{
if (n==0)
return 0; /* 如果n=0 則傳回 0*/
else if(n==1 || n==2)
/* 如果n=1或n=2,則傳回1 */
return 1;
else
/* 否則傳回 fib(n-1)+fib(n-2) */
return (fib(n-1)+fib(n-2));
}
1-5 遞迴演算法
範例1.5.2
27
1-5 遞迴演算法
河內塔問題(1/9)
河內塔問題可以這樣形容:假設有A、B、C三個木
樁和n個大小均不相同的套環(Disc),由小到大編
號為1,2,3…n,編號越大直徑越大。
開始的時候,n個套環境套在A木樁上,現在希望
能找到將A木樁上的套環藉著B木樁當中間橋樑,
全部移到C木樁上最少次數的方法。不過在搬動時
還必須遵守下列規則:
1.直徑較小的套環永遠置於直徑較大的套環上。
2.套環可任意地由任何一個木樁移到其他的木樁上。
3.每一次僅能移動一個套環,而且只能從最上面的套
環開始移動。
28
1-5 遞迴演算法
河內塔問題(2/9)
現在我們考慮n=1~3的狀況,以圖示方式示範處理
河內塔問題的步驟:
n=1個套環
(當然是直接把盤子從1號木樁移動到3號木樁。)
n=2個套環
1.將套環從1號木樁移動到2號木樁
29
1-5 遞迴演算法
河內塔問題(3/9)
n=2個套環
2.將套環從1號木樁移動到3號木樁
3.將套環從2號木樁移動到3號木樁,就完成了
30
1-5 遞迴演算法
河內塔問題(4/9)
n=2個套環
完成
結論:移動了22-1=3次,盤子移動的次序為1,2,1(此處為
盤子次序)
步驟為:1→2,1→3,2→3(此處為木樁次序)
31
1-5 遞迴演算法
河內塔問題(5/9)
n=3個套環
1.將套環從1號木樁移動到3號木樁
2.將套環從1號木樁移動到2號木樁
32
1-5 遞迴演算法
河內塔問題(6/9)
n=3個套環
3.將套環從3號木樁移動到2號木樁
4.將套環從1號木樁移動到3號木樁
33
1-5 遞迴演算法
河內塔問題(7/9)
n=3個套環
5.將套環從2號木樁移動到1號木樁
6.將套環從2號木樁移動到3號木樁
34
1-5 遞迴演算法
河內塔問題(8/9)
n=3個套環
7.將套環從1號木樁移動到3號木樁,就完成了
完成
結論:移動了23-1=7次,盤子移動的次序為
1,2,1,3,1,2,1(盤子次序)
步驟為1→3,1→2,3→2,1→3,2→1,2→3,1→3(木樁次
序)
35
1-5 遞迴演算法
河內塔問題(9/9)
以下以遞迴式來表示河內塔遞迴函數演算法:
void hanoi(int n, int p1, int p2, int p3)
{
if (n==1) //遞迴出口
printf("套環從 %d 移到 %d\n", p1, p3);
else
{
hanoi(n-1, p1, p3, p2);
printf("套環從 %d 移到 %d\n", p1, p3);
hanoi(n-1, p2, p1, p3);
}
}
36
#include <stdio.h>
#include <stdlib.h>
void hanoi(int, int, int, int); /* 函數原型 */
int main()
{
int j;
printf("請輸入所移動套環數量:");
請設計一支C語言程式,以遞迴式來實作河內塔演
scanf("%d", &j);
hanoi(j,1,
2, 3);
算法的求解。
system("pause");
return 0;
}
void hanoi(int n, int p1, int p2, int p3)
{
if (n==1) /* 遞迴出口 */
printf("套環從 %d 移到 %d\n", p1, p3);
else
{
hanoi(n-1, p1, p3, p2);
printf("套環從 %d 移到 %d\n", p1, p3);
hanoi(n-1, p2, p1, p3);
}
}
1-5 遞迴演算法
範例 1.5.3
37
1-5 遞迴演算法
範例 1.5.4
請問河內塔問題中,移動n個盤子所需的最小移動
次數?試說明之。
解答
課文中曾經提過當有n 個盤子時,可將河內塔問題歸納
成三個步驟,其中an為移動n個盤子所需要的最少移動次
數,an-1為移動n-1個盤子所需要的最少移動次數,a1=1
為只剩一個盤子時的次數,因此可得如下式子:
an= an-1+1+ an-1
=2an-1+1
=2(an-2+1)
=4an-2+2+1
=4(2an-3+1)+2+1
38
1-5 遞迴演算法
=8an-3+4+2+1
=8(2an-4+1)+4+2+1
=16an-4+8+4+2+1
=...
=...
=2n-1a1+
因此,an=2n-1*1+
=2n-1+2n-1-1=2n-1,得知要移動n個盤子所需的最小移動次數
為2n-1次
39
1-6 程式效能分析
程式效能分析(1/3)
範例 1.6.1
考慮下列x←x+1的執行次數。
(1)
:
x←x+1
:
(2)
for i←1 to n do
:
x←x+1
:
end
解答
(1)1次(2)n次(3)n*m次
(3)
for i←1 to n do
:
for j←1 to m do
:
x←x+1
:
end
:
end
40
1-6 程式效能分析
程式效能分析(2/3)
範例 1.6.2
考慮下列x←x+1的執行次數。
for i←1 to n do
j←i
for k←j+1 to n do
x←x+1
end
end
解答
因為j←i,且k←j+1所以可用以下數學式表示,所以其執行次數為
41
1-6 程式效能分析
程式效能分析(3/3)
範例 1.6.3
請決定以下片斷程式的執行時間。
k=100000
while k<>5 do
k=k DIV 10
end
解答
因為k=k DIV 10,所以一直到k=0時,都不會出現k=5的
情況,整個迴路為無窮迴路,執行時間為無限長。
42
1-6 程式效能分析
Big-oh(1/3)
範例 1.6.4
請證明
 i =O(n2)
1i  n
解答
43
1-6 程式效能分析
Big-oh(2/3)
常見的Big-oh有下列幾種:
44
1-6 程式效能分析
45
1-6 程式效能分析
Big-oh(3/3)
對於n≥16時,時間複雜度的優劣比較關係如下:
O(1)<O(log2n)<O(n)<O(nlog2n)<O(n2)<O(n3)<O(2n)
範例 1.6.5
請問河內塔遞迴氏的時間複雜度為何?
解答:由範例1.5.1中,可以得到以下結論:
an== an-1+1+ an-1
=2n-1 → O(2n)
46
1-6 程式效能分析
Ω(omega)
以下是Ω的定義:
對f(n)= Ω(g(n))(讀作”big-omega of g(n)”),意思是存在常數c
和n0,對所有的n值而言,n>= n0時,f(n)≧cg(n)均成立。例如
f(n)=5n+6,存在c=5 n0=1,對所有n≧1時,5n+6≧5n,因此
f(n)= Ω(n)而言,n就是成長的最大函數。
範例1.6.6
f(n)=6n2+3n+2,請利用Ω來表示f(n)的時間複雜
度。
f(n)= 6n2+3n+2,存在c=6 ,n0≧1,對所有的n≧n0,使得
6n2+3n+2>=6n2,所以f(n)= Ω(n2)
47
1-6 程式效能分析
θ(theta)
是一種比Big-O與Ω更精確時間複雜度的漸近表示
法。定義如下:
f(n)= θ(g(n))(讀作”big-theta of g(n)”),意是存在常數c1、c2
、n0,對所有的n≧n0時,c1g(n)≦f(n)≦c2g(n)均成立。換句話
說,當f(n)=θ(g(n))時,就表示g(n)可代表f(n)的上限與下限。
例如以f(n)=n2+2n為例,當n≧0時,n2+2n≦3n2,
可得f(n)=O(n2)。同理,n≧0時, n2+2n≧n2,可
得f(n)=Ω(n2)。所以f(n)=n2+2n=θ(n2)
48
本章結束
Q&A討論時間
49