23 แผนการสอนประจําบทเรียน รายชือ่ อาจารยผจู ดั ทํา สุณี รักษาเกียรติศักดิ์ และ สมชาย ประสิทธิจ์ ตู ระกูล หัวขอของเนื้อหา ตอนที่ 2.1 การสรางและการใชขอ มูลแบบคัดยอ (2 คาบ) เรือ่ งที่ 2.1.1
การสรางชนิดขอมูลแบบคัดยอ
เรือ่ งที่ 2.1.2
การใชชนิดขอมูลแบบคัดยอ
ตอนที่ 2.2 มาตรวัดประสิทธิภาพของอัลกอริทึม (1 คาบ) เรือ่ งที่ 2.2.1
แนวคิด
เรือ่ งที่ 2.2.2
การนับจํานวนครั้งของการใชงานคําสั่ง
เรือ่ งที่ 2.2.3
คําสัง่ มาตรเวลา
เรือ่ งที่ 2.2.4
การวิเคราะหเชิงเสนกํากับ
เรือ่ งที่ 2.2.5
สัญกรณโอใหญ
เรือ่ งที่ 2.2.6
ตัวอยางการวิเคราะหโปรแกรมเชิงเสนกํากับ
แนวคิด 1. ในตอนที่ 1.3 ของบทเรียนที่ 1 เราไดเห็นหลักการของการสรางชนิดขอมูลตามความตองการ ของเรา โดยใชหลักการของชนิดของขอมูลแบบคัดยอ ซึง่ มีวธิ กี ารดําเนินการ 2 ขั้นตอนใหญๆ ขั้นตอนแรกคือ การกําหนดคุณลักษณะเฉพาะของชนิดของขอมูลทีเ่ ราตองการสรางใหชดั เจน และขั้นตอนที่ 2 คือการสรางชนิดขอมูลตามคุณลักษณะเฉพาะทีก่ าํ หนด โดยในตอนที่ 1.3 ของบทเรียนที่ 1 ไดใหตัวอยางคุณลักษณะเฉพาะของชนิดขอมูลที่ตองการสราง 2 ชนิด คือ ชนิดขอมูล “Color” และชนิดขอมูล “LetterString” 2. ในตอนที่ 2.1 ของบทเรียนที่ 2 นี้ จะไดนาํ เสนอวิธใี นการสรางชนิดขอมูล “Color” และ “LetterString” ตามคุณลักษณะเฉพาะทีก่ าํ หนดในตอนที่ 1.3 ของบทเรียนที่ 1 โดยใช UNIT ของ Turbo Pascal เปนเครือ่ งมือ พรอมทั้งเขียนโปรแกรมเพื่อทดสอบวาชนิดขอมูลที่เราสราง ขึน้ สามารถทํางานไดถกู ตอง 3. ประสิทธิภาพของการดําเนินงานทีส่ ราง ขึ้นอยูกับการแทนที่ขอมูลที่เลือกใชและอัลกอริทึมใน สราง ซึ่งมาตรวัดอันหนึ่งที่นิยมใชในการวัดประสิทธิภาพของอัลกอริทึม คือ สัญกรณโอใหญ (function big O)
24 วัตถุประสงค หลังจากศึกษาบทเรียนที่ 2 แลว นักศึกษาสามารถ 1. เห็นตัวอยางและเขาใจวิธีการสรางและการทดสอบการใช ชนิดขอมูลแบบคัดยอ และสามารถ ประยุกตใชได 2. เขาใจการทํางานของมาตรวัดประสิทธิภาพของอัลกอริทึมได กิจกรรมการเรียนการสอน กิจกรรมทีน่ กั ศึกษาตองทําสําหรับการเรียนการสอน ไดแก 1. ศึกษาเอกสารชุดวิชา/โฮมเพจชุดวิชา ตอนที่ 2.1 และตอนที่ 2.2 2. ทํากิจกรรมของบทเรียนที่ 2 3. ทําแบบประเมินผลของบทเรียนที่ 2 เอกสารประกอบการสอน 1. เอกสารชุดวิชา สื่อการสอน 1. โฮมเพจชุดวิชา 2. สไลดประกอบการบรรยาย (Powerpoint) 3. โปรแกรมคอมพิวเตอร ประเมินผล 1. ประเมินผลจากกิจกรรมที่ทํา 2. ประเมินผลจากคําถามทายบทเรียน
25 ตอนที่ 2.1 การสรางและการใชขอมูลแบบคัดยอ หัวเรื่อง เรือ่ งที่ 2.1.1
การสรางชนิดขอมูลแบบคัดยอเชิงเดีย่ ว Color
เรือ่ งที่ 2.1.2
การใชชนิดขอมูลแบบคัดยอเชิงเดี่ยว Color
เรือ่ งที่ 2.1.3
การสรางชนิดขอมูลแบบคัดยอเชิงโครงสราง LetterString
เรือ่ งที่ 2.1.4
การใชชนิดขอมูลแบบคัดยอเชิงโครงสราง LetterString
แนวคิด 1. หลักการสรางชนิดขอมูลตามความตองการของเรา โดยใชหลักการของชนิดของขอมูลแบบคัด ยอ มีวธิ กี ารดําเนินการ 2 ขั้นตอนใหญ ๆ ขั้นตอนแรกคือ การกําหนดคุณลักษณะเฉพาะของ ชนิดของขอมูลที่เราตองการสรางใหชัดเจน และขั้นตอนที่ 2 คือการสรางชนิดขอมูลตามคุณ ลักษณะเฉพาะทีก่ าํ หนด 2. UNIT ของ Turbo Pascal สามารถใชเปนเครื่องมือในการสรางชนิดขอมูลแบบคัดยอตามคุณ ลักษณะเฉพาะทีก่ าํ หนดไวแลว เมื่อสรางแลวเราตองเขียนโปรแกรมเพื่อทดสอบวาชนิดขอมูลที่ เราสรางขึน้ สามารถทํางานไดถกู ตอง วัตถุประสงค หลังจากที่ศึกษาตอนที่ 2.1 แลว นักศึกษาสามารถ 1. เห็นตัวอยางและเขาใจวิธีการสรางและการทดสอบการใชชนิดขอมูลแบบคัดยอ ชนิด “Color” และชนิด “LetterString” 2. สามารถประยุกตวธิ กี ารไปใชได ในการสรางและทดสอบชนิดขอมูลแบบอืน่ ๆ เรื่องที่ 2.1.1 การสรางชนิดขอมูลแบบคัดยอ การสรางชนิดขอมูลแบบคัดยอเชิงเดี่ยว Color ตามคุณลักษณะเฉพาะที่กําหนดของชนิดขอมูลแบบคัดยอ “Color” ในเรื่องที่ 1.3.1 ของบทเรียนที่ 1 นัน้ หากเราตองการจะสรางชนิดขอมูล “Color” โดยใช Turbo Pascal เปนเครือ่ งมือ เราจะตองนึกถึงการ ดําเนินการ 2 สวน สวนที่ 1 คือ การเลือกการแทนทีข่ อ มูลของ domain ของ Color ซึ่งเราอาจจะใชขอมูล ชนิด enumerated ในภาษาปาสคาลได เมือ่ เลือกการแทนทีข่ อ มูลแลว เราก็สามารถจะสรางการดําเนินงาน ตาง ๆ ตามทีร่ ะบุในคุณลักษณะเฉพาะของ “Color” ได ดังตัวอยางของโปรแกรม 2.1
26 คําอธิบายโปรแกรม 2.1 UNIT ในปาสคาลจะแบงเปนสองสวน สวนแรกเราเรียกวาสวนของ INTERFACE ซึง่ ก็คอื สวนทีจ่ ะ ติดตอกับผูใช (สวนซึ่งผูใชมองเห็น) ซึ่งประกอบดวยการแทนที่ขอมูลซึ่งในที่นี้ คือ Color ในบรรทัดที่ 5 และ การดําเนินงานทีส่ ามารถทําไดกบั Color ไดแก Mix, Primary, Form ในบรรทัดที่ 6, 7, 8 ตามลําดับ สวนที่ สองเราเรียกวาสวนของ IMPLEMENTATION จะเปนสวนรายละเอียดของการสรางการดําเนินงานซึง่ สวนนีจ้ ะ เปนสวนที่ผูใชจะมองไมเห็น (information hiding) ในหลักการของขอมูลแบบคัดยอนั้นจริง ๆ แลวการแทนที่ขอมูลควรจะเปนสวนที่ซอนจากผูใชดวย แต UNIT ของ TURBO PASCAL ยังไมสามารถซอนจากผูใชไดเพราะกําหนดอยูในสวนของ INTERFACE ทํา ใหยังไมาสามารถสนับสนุนคุณสมบัติของ integrity ไดอยางสมบูรณ ภาษาโปรแกรมในยุคที่ 3 ทีส่ นับสนุน การทํางานของหลักการของขอมูลแบบคัดยอคือภาษา Ada การสรางชนิดขอมูลแบบคัดยอเชิงโครงสราง Letterstring เราสามารถสรางชนิดขอมูลแบบคัดยอ Letterstring ไดดว ยวิธกี ารทํานองเดียวกันกับการสรางชนิด ขอมูลแบบคัดยอ Color นัน่ คือ การเลือกการแทนทีข่ อ มูลของ Letterstring ซึ่งอาจจะใชแถวลําดับหรืออะ เรยกไ็ ด หลังจากนัน้ ก็สรางการดําเนินงานตาง ๆ ของ Letterstring กิจกรรม 2.1 ฝกการสรางชนิดขอมูลแบบคัดยอ 1. จงคอมไพล UNIT ColorU ตามตัวอยาง และตั้งชื่อไฟลชื่อ ColorU.pas เมือ่ คอมไพลแลวและ ไมเกิด error ระบบจะสราง object code ไฟลชื่อ ColorU.TPU ใหในไดเร็กทอรีเดียวกับ ColorU.pas 2. จงสราง UNIT StingU ตามคุณลักษณะเฉพาะ 2.2 และตั้งชื่อไฟลชื่อ StringU.pas
27 UNIT ColorU; 1 {**************************} 2 INTERFACE 3 {**************************} 4 TYPE Color=(Red,Blue,Yellow,Green,Violet,Orange); 5 FUNCTION Mix(C1,C2:Color):Color; 6 FUNCTION Primary(C:Color):boolean; 7 PROCEDURE Form(C:Color;VAR C1,C2:Color); 8 {**************************} 9 IMPLEMENTATION 10 {**************************} 11 FUNCTION Mix(C1,C2:Color):Color; 12 BEGIN 13 IF ((C1=Red)and(C2=Yellow))or((C1=Yellow)and(C2=Red)) THEN 14 Mix:=Orange 15 ELSE IF ((C1=Red)and(C2=Blue))or((C1=Blue)and(C2=Red)) THEN 16 Mix:=Violet 17 ELSE IF ((C1=Yellow)and(C2=Blue))or((C1=Blue)and(C2=Yellow))18 THEN Mix:=Green 19 END; 20 21 FUNCTION Primary(C:Color):boolean; 22 BEGIN 23 IF (C=Red)or(C=Yellow)or(C=Blue) THEN Primary:=True 24 ELSE Primary:=False; 25 26 END; 27 28 PROCEDURE Form(C:Color;VAR C1,C2:Color); 29 BEGIN 30 IF C=Orange THEN 31 BEGIN 32 C1:=Red; C2:=Yellow; 33 END 34 ELSE IF C=Green THEN 35 BEGIN 36 C1:=Yellow; C2:=Blue; 37 END 38 ELSE IF C=Violet THEN 39 BEGIN 40 C1:=Red; C2:=Blue; 41 END; 42 END; 43 44 END. 45
โปรแกรม 2.1 การสรางขอมูลแบบคัดยอชนิด “Color”
28 เรื่องที่ 2.1.2
การใชชนิดขอมูลแบบคัดยอเชิงเดี่ยว Color
UNIT เปรียบเสมือนชนิดขอมูลทีเ่ ราสรางขึน้ มาเปน library และผูอ น่ื สามารถนําไปใชได ดังนัน้ เพือ่ ใหแนใจวา UNIT ทีเ่ ราสรางขึน้ มาถูกตอง เราตองมีการทดสอบ (ซึง่ เปรียบเสมือนเปนผูใ ช) ดังนั้นผูใชเพียง แตทราบวาชนิดขอมูลคัดยอที่สรางมานี้มีชนิดเปน Color ซึง่ เปน enumerated type ประกอบดวยขอมูล 6 ตัว คือ Red, Blue,Yellow,Green,Violet,Orange และมีการดําเนินงานใหใชได 3 การดําเนินงานคือ Mix, Primary, และ Form ซึ่งมีรูปแบบการใชดังปรากฎในบรรทัดที่ 6, 7, 8 เงือ่ นไขและผลลัพธในการดําเนินงาน ดังทีก่ าํ หนดไวในคุณลักษณะเฉพาะ ผูใชสามารถเรียกการดําเนินงานทั้งสามนี้ไปใชได โดยไมตองสนใจใน รายละเอียดวาการดําเนินงานเหลานีส้ รางมาไดอยางไร (mplementation independence) ตัวอยางโปรแกรมการทดสอบการดําเนินงานดังแสดงในโปรแกรม 2.2 PROGRAM ColorT; USES ColorU,wincrt; VAR C,C1,C2:Color; CS,CS1,CS2:string; Choice:char; PROCEDURE GetChoice(VAR Ch:char); BEGIN write('Input choice of operation: '); readln(Ch); END; PROCEDURE ConvertColor(S:string;VAR C:Color); BEGIN IF S='red' THEN C:=Red ELSE IF S='yellow' THEN C:=Yellow ELSE IF S='blue' THEN C:=Blue ELSE IF S='green' THEN C:=Green ELSE IF S='orange' THEN C:=Orange ELSE IF S='violet' THEN C:=Violet ELSE writeln('Invalid Color, please primary color again'); END; FUNCTION WriteColor(C:Color):string; BEGIN IF C=Red THEN WriteColor:='red' ELSE IF C=Yellow THEN WriteColor:='yellow' ELSE IF C=Blue THEN WriteColor:='blue' ELSE IF C=Green THEN WriteColor:='green' ELSE IF C=Orange THEN WriteColor:='orange' ELSE IF C=Violet THEN WriteColor:='violet'; END; BEGIN
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
29 Clrscr; writeln('****************************'); writeln('Test operations of ADT Color'); writeln('****************************'); writeln('1 Mix'); writeln('2 Primary'); writeln('3 Form'); writeln('9 Quit'); writeln('******************************************'); writeln('All possible colors that can be input are:'); writeln('red, yellow, blue, green, orange, violet'); writeln('******************************************'); Getchoice(Choice); WHILE (Choice<>'9') DO BEGIN CASE Choice OF '1' : BEGIN write('Input primary color1 : '); readln(CS1); write('Input primary color2 : '); readln(CS2); ConvertColor(CS1,C1); ConvertColor(CS2,C2); C:=Mix(C1,C2); CS:=WriteColor(C); writeln('The result of mixing ', CS1, ' and ', CS2, ' is ', CS); END; '2' : BEGIN write('Input color : '); readln(CS); ConvertColor(CS,C); IF Primary(C) THEN writeln(CS, ' is a primary color') ELSE writeln(CS, ' is not a primary color'); END; '3' : BEGIN write('Input a non primary color : '); readln(CS); ConvertColor(CS,C); Form(C,C1,C2); CS1:=WriteColor(C1); CS2:=WriteColor(C2); writeln(CS1, ' and ',CS2,' are two primary colors that form the input color', CS); END; ELSE BEGIN writeln('Not a correct choice, try again'); GetChoice(Choice);
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
30 END; END {CASE}; writeln('******************************************'); GetChoice(Choice); END {WHILE}; writeln('!!! End of program !!! '); END.
85 86 87 88 89 90 91 92 93 94 95
โปรแกรม 2.2 การทดสอบการใชขอมูลแบบคัดยอชนิด “Color” คําอธิบายโปรแกรม 2.2 1. เมือ่ มีการเรียกใช UNIT ColorU ในบรรทัดที่ 2 ชื่อ (identifier) ของ UNIT ColorU ที่โปรแกรม ColorT จะรูจักและเรียกใชไดทันที คือ Color, Mix, Primary, และ Form 2. เนื่องจากในการทดสอบนี้จะใหมีการรับขอมูลจากคียบอรด ซึ่งขอมูลที่มีชนิดเปน Color เปน ชนิดแบบ enumerated ซึง่ ไมสามารถรับคาจากคียบ อรดได จึงตองใหมีการรับคาเปน string แลวใชโพรซี เจอร ConvertColor แปลงชนิด string เปน Color 3. ในทํานองเดียวกันเนือ่ งดวยเราไมสามารถแสดงผลขอมูลชนิด enumerated ดวยคําสัง่ write หรือ writeln ได เราจึงตองมีการแปลงขอมูลจากชนิด Color ไปเปน string ดวยฟงกชัน WriteColor 4. ในโปรแกรมนี้มีการเรียกใชการดําเนินงานของ ADT Color ฟงกชัน Mix ในบรรทัดที่ 58, ฟงกชัน Primary ในบรรทัดที่ 67, โพรซีเจอร Form ในบรรทัดที่ 76 กิจกรรม 2.2 ฝกการทดสอบการใชงานขอมูลแบบคัดยอ 1. จงคอมไพลและรันโปรแกรม ColorT ตามตัวอยาง และตั้งชื่อไฟลชื่อ ColorT.pas และศึกษาตร รกการทํางานของโปรแกรม 2. จงสรางการดําเนินงานขึน้ อีก 1 การดําเนินงานคือ Assign ใน UNIT ColorU และจงทดสอบการ ดําเนินงาน Assign ในโปรแกรม ColorT ดวย 3. จงเขียนโปรแกรม StringT เพื่อทดสอบการใชงานชนิดขอมูล LetterString และตั้งชื่อไฟลชื่อ StringT.pas
31 ตอนที่ 2.2 การวิเคราะหเชิงเสนกํากับและสัญกรณโอใหญ หัวเรื่อง เรือ่ งที่ 2.2.1
แนวคิด
เรือ่ งที่ 2.2.2
การนับจํานวนครั้งของการใชงานคําสั่ง
เรือ่ งที่ 2.2.3
คําสัง่ มาตรเวลา
เรือ่ งที่ 2.2.4
การวิเคราะหเชิงเสนกํากับ
เรือ่ งที่ 2.2.5
สัญกรณโอใหญ
เรือ่ งที่ 2.2.6
ตัวอยางการวิเคราะหโปรแกรมเชิงเสนกํากับ
แนวคิด 1. การวิเคราะหประสิทธิภาพเชิงเวลา อาศัยการนับจํานวนครั้งของการใชงานคําสั่งตางๆ ใน โปรแกรม โดยเขียนจํานวนครั้งนี้เปนฟงกชันของขนาดของขอมูลขาเขา 2. การวิเคราะหจะงายขึ้น ถาพิจารณานับเฉพาะคําสั่งมาตรเวลาในโปรแกรม ซึ่งคือคําสั่งที่ถูกใช ทํางานมากที่สุดในโปรแกรม โดยเวลาการทํางานโดยรวมจะแปรโดยตรงตามจํานวนครั้งที่คําสั่ง มาตรเวลาถูกใชงาน 3. การวิเคราะหเชิงกํากับเปนการศึกษาพฤติกรรมของอัตราการเติบโตของฟงกชันเวลาการ ทํางานของโปรแกรม เมื่อขอมูลขาเขามีขนาดใหญมาก 4. เราใชแนวคิดของสัญกรณโอใหญในการแทนฟงกชันเวลาการทํางานที่ซับซอน ดวยฟงกชันที่ ซับซอนนอยกวาเพื่อใหเขาใจและงายตอการเปรียบเทียบอัตราการเติบโตของเวลาการทํางาน วัตถุประสงค หลังจากที่ศึกษาตอนที่ 2.3 แลว นักศึกษาสามารถ 1. เขาใจการวิเคราะหประสิทธิภาพเชิงเวลาของโปรแกรม 2. เขาใจวิธีการใชสัญกรณโอใหญในการวิเคราะหเวลาการทํางานของโปรแกรมเชิงเสนกํากับ เรื่องที่ 2.2.1
แนวคิด
ปญหาที่นักโปรแกรมควรถามตัวเองเสมอก็คือวา โปรแกรมที่ตนเขียนนั้นมีประสิทธิภาพเชิงเวลา การทํางานอยางไร และเมื่อเทียบกับอีกโปรแกรมที่ใชแกปญหาเดียวกันแลวเราจะรูไดอยางไรวาของใครเร็ว กวากัน คําตอบที่มักพบบอยๆ ก็คอื “ก็ลองใชงานจริงแลวจับเวลาดูจริงๆ กันเลยก็จะรูเ อง” ปญหาของการ ลองใชงานจริงเลย จะอยูตรงที่วาแลวจะใชชุดขอมูลขาเขาใดเปนชุดทดสอบ และเราจะทราบไดอยางไรวาชุด ขอมูลตางๆ ที่นํามาทดสอบนั้นครอบคลุมจุดเดนจุดดอยของโปรแกรมที่เขียนขึ้น
32 การวิเคราะหการทํางานเชิงเวลาโดยทั่วไปอาศัยการนับจํานวนครั้งของการใชงานคําสั่งตางๆ ใน โปรแกรมระหวางการทํางาน ซึ่งเขียนบรรยายจํานวนครั้งที่นับไดนี้ใหเปนฟงกชันของขนาดของขอมูลขาเขา ของปญหา อัตราการเติบโตของฟงกชันนี้เองจะสะทอนใหเห็นถึงแนวโนมการเพิ่มของเวลาการทํางานเมื่อ ขนาดของขอมูลเพิ่มขึ้นวามีลักษณะอยางไร โดยเรามักวิเคราะหเวลาการทํางานสําหรับขอมูลขาเขากรณีเลว สุด (worst case) และกรณีเฉลีย่ (average case) เพื่อใหการวิเคราะหกระทําไดงายขึ้น โดยทั่วไปจะอาศัยวิธีการนับเฉพาะ “คําสัง่ มาตรเวลา” ตางๆ ซึง่ คือคําสัง่ ทีจ่ ะทํางานเปนจํานวนครัง้ ไมนอ ยกวาคําสัง่ อืน่ ๆ ดังนั้นจึงใชเปนตัวแทนเพื่อศึกษาแนวโนมของ เวลาการทํางานโดยรวมได และยังอาศัยการวิเคราะหเชิงเสนกํากับ (asymptotic analysis) โดยใชสัญกรณ เชิงเสนกํากับโอใหญ (Big O) ในการแทนฟงกชัน เพื่อลดรูปฟงกชันใหสามารถตีความไดงายขึ้น อีกทั้งชวย จัดการวิเคราะหไดงา ยขึน้ ดวย ซึง่ จะไดนาํ เสนอในรายละเอียดตอไป เรื่องที่ 2.2.2
การนับจํานวนครั้งของการใชงานคําสั่ง
วิธีหนึ่งที่ใชในการวิเคราะหเชิงเวลาคือการหาผลรวมของเวลาการทํางานของคําสั่งตางๆ ใน โปรแกรมซึ่งถูกใชงาน ลองดูตัวอยางโปรแกรมสั้นๆ ขางลางนี้ กําหนดใหเวลาการทํางานของคําสั่งในบรรทัด ที่ i เปน ti วินาที 01: function sum( var x : vector; n : integer ) : integer; 02: var i, s : integer; 03: begin 04: s := 0; 05: for i:=1 to n do 06: s := s + x[i]; 07: sum := s; 08: end; sum ทําหนาทีห ่ าผลรวมของจํานวนในเวกเตอร
x (ซึง่ สรางดวยแถวลําดับ) ตั้งแตชองที่ 1 ถึง n โดย
ใชเวลารวมทั้งสิ้นเทากับ n
t1 Ι t 2 Ι t 3 Ι t 4 Ι
¦ Φt5 Ι t 6 Γ Ι t5 Ι t 7 Ι t8 i [1
นักศึกษาอาจรูส กึ ตอนนีว้ า ถึงแมวาสามารถเขียนออกมาไดดังแสดงขางบนนี้ แลวสรุปไดวา อะไร เพราะเวลาการทํางานก็ยงั ขึน้ กับคา ti ทัง้ หลายในนิพจน ตองขอบอกตอนนีเ้ ลยวาจุดประสงคของการ วิเคราะหประสิทธิภาพเชิงเวลาก็เพื่อวิเคราะหใหเห็นแนวโนมของเวลาการทํางานของโปรแกรมเมื่อขนาดของ ขอมูลเพิ่มขึ้น นั่นคือทําใหเราประมาณไดวาถาขอมูลเพิ่มขึ้น k เทาแลวเวลาการทํางานจะเพิ่มเทาไร กําหนดให ti ℑ c1 สําหรับทุกๆ i หมายความวาให c1 เปนคาคงตัวซึง่ มีคา เทากับเวลาการทํางาน ของคําสัง่ ทีท่ าํ งานนานสุดในโปรแกรม ดังนัน้ จากตัวอยางเวลาการทํางานทีแ่ สดงขางบนนี้ เราสามารถลดรูป ใหแลดูกระทัดรัดขึน้ ไดเปน n
t1 Ι t 2 Ι t 3 Ι t 4 Ι
n
¦ Φt5 Ι t 6 Γ Ι t5 Ι t 7 Ι t8 ℑ 4c1 Ι ¦ 2c1 Ι 3c1 i [1
i [1 [ c1 Φ2n Ι 7 Γ
สรุปไดวา sum ใชเวลาการทํางานไมเกิน c1 (2n + 7) ซึ่งเปนฟงกชันแปรผันโดยตรงแบบเชิงเสนกับ n
33 ตองขอเนนวาการทีเ่ รากําหนดให "c1 เปนคาคงตัวมีคาเทากับเวลาการทํางานของคําสั่งที่ทํางาน นานสุดในโปรแกรม" ในการวิเคราะหขางบนนี้ คําสั่งตางๆ ที่ใชจะตองเปนคําสั่งซึ่งใชเวลาการทํางานไมแปร ตามจํานวนขอมูล เรียกวาเปนคําสัง่ มูลฐานซึง่ คือคําสัง่ งายๆ เชน บวก ลบ คูณ หาร เปรียบเทียบ หรืออืน่ ๆ ที่ ใชเวลาไมแปรตามจํานวนขอมูล ถึงตรงนี้บางคนอาจสงสัยวาการบวกก็ใชเวลาแปรตามจํานวนบิต ซึง่ ก็เปน ความเขาใจที่ถูกตอง แตเนื่องจากในที่นี้เราใชการบวกขอมูลแบบ integer ซึ่งจํานวนหนึ่งๆ มีขนาดจํากัด เชน 16 บิต จึงถือไดวาใชเวลาคงตัว เพราะบวกอยางไรก็ไมเกิน 16 บิต การวิเคราะหเชิงเวลาทีก่ ระทํามานัน้ อาจดูคลายการนับจํานวนครัง้ ทีค่ าํ สัง่ มูลฐานตางๆ ในโปรแกรม ถูกเรียกใชงาน จากตัวอยาง คําสั่งตางๆ ใน sum ทํางานเปนจํานวน 2n + 7 ครัง้ แตละครั้งใชเวลาไมเกิน c1 ไดผลรวมเปน c1(2n + 7) การนับจํานวนครัง้ ทีค่ าํ สัง่ มูลฐานตางๆ ในโปรแกรมถูกเรียกใชงานนี่เองจึงเปนกล วิธีหลักในการวิเคราะหประสิทธิภาพเชิงเวลา มาดูอกี สักตัวอยาง matrixMult ขางลางนี้มีหนาที่หาผลคูณของเมทริกซ x และ y ซึ่งมีขนาด n∑n ไดผลลัพธเก็บไวในเมทริกซ z (ในทีน่ เ้ี ราสรางเมทริกซตา งๆ ดวยแถวลําดับสองมิต)ิ 01: procedure matrixMult( var x, y, z : matrix; n : integer ); 02: var i, j, k : integer; 03: begin 04: for i:=1 to n do 05: for j:=1 to n do 06: z[i,j] := 0.0; 07: for i:=1 to n do 08: for j:=1 to n do 09: for k:=1 to n do 10: z[i,j] := z[i,j] + x[i,k]*y[k,j]; 11: end;
นับจํานวนครั้งที่แตละคําสั่งถูกใชงานจะไดดังตารางขางลางนี้ บรรทัดที่ จํานวนครั้งที่ทํางาน 1 2 3 4 5 6 7 8 9 10 11
1 1 1 n+1 n(n+1) n2 n+1 n(n+1) n2(n+1) n3 1
รวมจํานวนครั้งของการทํางานของคําสั่งในแตละบรรทัดเขาดวยกัน และคูณกับ c2 ซึ่งกําหนดใหเปน เวลาการทํางานของคําสัง่ ทีท่ าํ งานนานสุดในโปรแกรม จะไดวาเวลาการทํางานของโปรแกรมนี้ไมเกิน c2⌡ ( 2n3 + 4n2 + 4n + 6 )
ถากลับไปดูทต่ี วั matrixMult อีกทีหนึ่ง หลายคนอาจรูสึกวานาจะยุบรวมวงวน for ทีซ่ อ นกันสอง ชั้นในบรรทัดที่ 4 ถึง 6 ไปเปนสวนหนึ่งของวงวนขางลาง นัน่ คือยายคําสัง่ ที่ 6 ไปอยูหลังคําสั่งที่ 8 กลายเปน โปรแกรมใหมขางลางนี้
34 01: procedure matrixMult( var x, y, z : matrix; n : integer ); 02: var i, j, k : integer; 03: begin 04: for i:=1 to n do 05: for j:=1 to n do 06: begin 07: z[i,j] := 0.0; 08: for k:=1 to n do 09: z[i,j] := z[i,j] + x[i,k]*y[k,j]; 10: end; 11: end;
เมื่อวิเคราะหโปรแกรมขางบนนี้จะไดวาใชเวลาการทํางานไมเกิน c2⌡ ( 2n3 + 5n2 + 2n + 5 ) แลวอยาง นี้หมายความวาที่เขียนแบบใหมนี้ชากวาแบบเกาหรือ ? ทั้งๆ ที่แรงจูงในของการเขียนใหมนี้ ก็เพราะรูส กึ วา นาจะไดแบบที่เร็วกวา ตองขอบอกตรงนีว้ า เราคงนําผลลัพธของการวิเคราะหทง้ั สองมาเปรียบเทียบกันโดยดู ที่สัมประสิทธิ์เห็นจะลําบาก เพราะเรานับทุกบรรทัด ซึ่งแตละบรรทัดใชเวลาการทํางานตางกัน (ที่ไมเกิน c2) การคูณดวยคาคงตัว c2 ตามที่ทํามาบอกเราเพียงแคขอบเขตบนของเวลาการทํางาน (นัน่ คือบอกวาเวลาการ ทํางานไมเกินผลทีว่ เิ คราะหได) นอกจากนี้หลายคนอาจตั้งคําถามวาทําไมตองนับบรรทัดที่เปนการประกาศ ตัวแปร begin และ end ดวย ซึ่งดูเหมือนวาจะไมไดถูกแปลเปนคําสั่งเครื่องแตอยางใด การทีส่ มั ประสิทธิ์ ของพจน n2 ตางกันนิดหนอย (4 กับ 5 สําหรับตัวอยางขางตน) จึงบอกอะไรเราไมไดหรอกวาแบบใดจะเร็ว กวากัน อีกทั้งเมื่อ n มีคาเพิ่มขึ้น พจน n2 นั้นก็เปนพจนที่มีคาเพิ่มขึ้นนอยกวาคาที่เพิ่มขึ้นของพจน n3 ความ แตกตางของสัมประสิทธิ์ที่พจน n2 ยิ่งไมคอยมีผลโดยรวม สรุปไดวาเรานาใหความสนใจกับพจนที่มีการเติบ โตเร็วกวาพจนอื่นๆ และสัมประสิทธิ์ที่เปนคาคงตัวที่คูณอยูนั้นนํามาเปรียบเทียบไดไมคอยชัดเจนนักถาตาง กันไมมาก จึงเปนที่มาของกลวิธีการวิเคราะหดวยการนับคําสั่งมาตรเวลา และการวิเคราะหเชิงเสนกํากับ เพือ่ ชวยใหการวิเคราะหกระทําไดงายขึ้น เรื่องที่ 2.2.3
คําสั่งมาตรเวลา
หลายคําสั่งในโปรแกรมที่เขียนขึ้นนั้น บางคําสั่งถูกเรียกใชงานเปนจํานวนคงตัวไมขึ้นกับขนาดของ ขอมูล บางคําสั่งก็ถูกเรียกใชนอยกวาคําสั่งอื่นอยางเห็นไดชัด หมายความวาคําสั่งเหลานี้ไมไดไปมีสวนเปน ตัวกําหนดอัตราการเติบโตของเวลาการทํางานโดยรวมเอาเลย แตเราก็ตองเสียเวลาไปนับจํานวนครั้งที่มันถูก ใชงานอยูดี เพือ่ ลดภาระการนับคําสัง่ เหลานี้ กอนจะเริม่ นับ เราควรพิจารณาเสียกอนวาคําสัง่ ใดในโปรแกรม ทีเ่ ปนตัวกําหนดเวลาการทํางานโดยรวม เราเรียกคําสัง่ ประเภทนีว้ า เปนคําสัง่ มาตรเวลา (ซึ่งมีไดมากกวาหนึ่ง คําสั่งในโปรแกรม) คําสั่งมาตรเวลาเปนคําสั่งที่ถูกใชทํางานมากที่สุดในโปรแกรม นัน่ คือเวลาการทํางานโดย รวมจะแปรโดยตรงตามจํานวนครั้งที่คําสั่งมาตรเวลาถูกใชงาน จาก sum ในหัวขอที่แลวนั้น คําสัง่ for (บรรทัดที่ 5) เปนคําสั่งมาตรเวลาของโปรแกรมนี้ คําสั่งนี้ถูกเรียกใชงานเปนจํานวน n+1 ครัง้ (เนือ่ งจากเปน วงวนแบบ for ซึ่งให i เริ่มที่ 1 เพิ่มทีละหนึ่งจนกระทั่งเมื่อมีคาเทากับ n+1 จึงหลุดจากวงวน) หรือจะใชคําสั่ง ที่บรรทัดที่ 6 ภายในวงวน for ก็ได เมื่อกําหนดให n > 0 ถาเรานับเฉพาะคําสัง่ ทีบ่ รรทัดที่ 6 จะไดจํานวนครั้ง ที่ถูกเรียกใชงานเปนจํานวน n ครัง้ สรุปไดวา sum ใชเวลาการทํางานเปนฟงกชนั เชิงเสนของ n
35 ถามาดูที่ matrixMult แบบแรก จะไดคําสั่งที่บรรทัดที่ 10 เปนคําสัง่ มาตรเวลา (บรรทัดที่ 9 ก็ใช ไดเหมือนกัน) เพราะเปนบรรทัดทีถ่ กู เรียกใชมากกวาบรรทัดอืน่ ๆ บรรทัดที่ 10 นี้อยูภายในวงวนสามวงซอน กันซึง่ แตละวงหมุนเปนจํานวน n รอบ จึงถูกเรียกใชเปนจํานวน
n
n
n
¦¦¦1 [ n 3 ครัง้ ตีความไดวา i [1 j [1 k [1
3
n ขอใหสังเกตตรงนี้วาเราไมสนใจคําสั่งที่บรรทัดที่ 4 ถึง 6 เลย ทีเ่ ปนเชนนีเ้ พราะวาคําสัง่ ทีบ่ รรทัดที่ 6 อยูภายในวงวนสองวงซอนกันซึ่งเพิ่มคาตั้งแต 1 ถึง n ซึ่งหมุน เปนจํานวน n2 ครัง้ ทีน่ อ ยกวาคําสัง่ มาตรเวลาทีเ่ ราเลือก matrixMult ใชเวลาการทํางานเปนฟงกชันแบบ
กิจกรรม 2.2 พิจารณาคําสั่งมาตรเวลา ขอใหนกั ศึกษาพิจารณาดูวา คําสัง่ ใดควรเปนคําสัง่ มาตรเวลาสําหรับ พบวาเมื่อนับแลวจะไดผลเชนเดียวกัน เรื่องที่ 2.2.4
matrixMult
แบบทีส่ อง จะ
การวิเคราะหเชิงเสนกํากับ
เนื่องจากเราใชจํานวนครั้งที่คําสั่งตางๆ ในโปรแกรมที่ถูกใชงาน (หรือจะพิจารณาเฉพาะคําสั่งมาตร เวลาก็ได) เปนตัวสะทอนถึงเวลาการทํางาน การนําผลการวิเคราะหของหลายๆ โปรแกรมมาเปรียบเทียบกัน เปนสิง่ ทีต่ อ งระวังเปนพิเศษ เพราะคําสั่งแตละคําสั่งของโปรแกรมตางๆ อาจใชเวลาการทํางานจริงซึ่งตางกัน แตเราจะมีความมั่นใจสูงมากในการเปรียบเทียบผล ถาเราเลือกใชการเปรียบเทียบเมื่อขอมูลมีจํานวนมาก (ซึ่งหมายถึงคาของตัวแปร n ที่ใชในตัวอยางที่ผานมามีคาสูง) เรียกวาการศึกษาพฤติกรรมของเวลาการ ทํางานของโปรแกรมเชิงเสนกํากับ นัน่ คือศึกษาการเติบโตของเวลาการทํางานเมือ่ n มีคามาก มีคามากแบบ เขาใกลอนันตไปเลย ตัวอยางเชนถาตองการเปรียบเทียบฟงกชัน 1000n กับ 0.1n2 ก็ลองวาดกราฟเสนของ ทั้งสองฟงกชันดูจะไดดังภาพประกอบ 2.1 จะเห็นไดวา 1000n ใหคามากกวา 0.1n2 เมื่อ n ℑ 10000 แตเมื่อ n มีคาเกิน 10000 ฟงกชัน 0.1n2 จะใหคามากกวาเสมอ ทัง้ นีเ้ พราะ n2 มีอัตราการเติบโตที่เร็วกวา n มาก 5.E+07
1000n 0.1n^2
4.E+07
3.E+07
2.E+07
1.E+07
0.E+00 0
5000
10000
15000
20000
25000
36 ภาพประกอบ 2.1 กราฟเสนของฟงกชัน 1000n กับ 0.1n2 หรือจะใชเรื่องของลิมิตเพื่อเปรียบเทียบการเติบโตของฟงกชันโดยไมตองวาดกราฟเสน ก็จะไดวา § 1000n · ¸ ν lim §¨ 10000 ·¸ ν 0 lim ¨ n⇓√© n ¹
n⇓√¨© 0.1n 2 ¸¹
แสดงใหเห็นวาเมื่อ n มีคามากเปนอนันต สัดสวนของ 1000n กับ 0.1n2 มีคาเขาใกลศูนย หมายความ 0.1n2 นั้นใหคาที่เพิ่มขึ้นเมื่อ n เพิ่มมากกวาคาของ 1000n มาก จึงมีอัตราการเติบโตที่เร็วกวา ภาพประกอบ 2.2 แสดงตัวอยางฟงกชันที่มักพบบอยๆ ซึ่งมีอัตราการเติบโตแตกตางกัน
2n
n2
n log n
n ภาพประกอบ 2.2 ตัวอยางฟงกชันที่มีอัตราการเติบโตแตกตางกัน ดังนั้นเมื่อตองการเปรียบเทียบการเติบโตของฟงกชัน f(n) กับ g(n) (ตองขอเนนวาในทีน่ เ้ี ราสนใจ เฉพาะ n และฟงกชันของ n ที่ใหคาไมติดลบ เพราะฟงกชันนี้แทนเวลาการทํางานของโปรแกรม) ก็เพียงแต หาคาลิมิตของ f(n) / g(n) เมื่อ n ⊂℘ ซึ่งสามารถตีความผลที่ไดดังนี้ ถา ถา ถา
f ( n) [0 n⊂℘ g ( n) lim
lim
f ( n)
n⊂℘ g ( n)
[℘
f ( n) [c n⊂℘ g ( n) lim
แสดงวา f(n) โตชากวา g(n) แสดงวา f(n) โตเร็วกวา g(n) โดยที่ c ⋅ 0 และ c ⋅ ℘ แสดงวา f(n) โตในอัตราที่เทากับ g(n)
เมื่อมีการใชลิมิต ก็ขอใหนึกถึงกฎของโลปตาล (l'Hôpital's Rule) ที่เคยเรียนกันในวิชาแคลคูลัส จะชวยหาคํา ตอบจัดการไดงายขึ้น ขอเขียนทบทวนใหดูโดยไมพิสูจนที่มาดังนี้ กฎของโลปตาล ถา f(n) และ g(n) เปนฟงกชนั ทีห่ าอนุพนั ธได โดยที่ lim f (n) ∴ ⊗ และ n ⊆⊗
f (n ) f ℑ(n ) lim g ( n ) ∴ ⊗ แลว lim ∴ lim n ⊆⊗ n ⊆⊗ g ( n ) n ⊆ ⊗ g ℑ( n )
ตัวอยาง 2.1 จงเปรียบเทียบอัตราการเติบโตของ 100n2 + 5n + 1 กับ n2 ใชกฎของโลปตาลไดวา สองโตเร็วเทากัน
lim
n⊆⊗
100n 2 ϑ 5n ϑ 1 n2
200n ϑ 5 200 ∴ lim ∴ 100 n 2 n⊆⊗ n⊆⊗ 2
∴ lim
แสดงวาฟงกชันทั้ง
37 ตัวอยาง 2.2 จงเปรียบเทียบอัตราการเติบโตของ ln9 n กับ n0.1 ใชกฎของโลปตาลไดดังนี้ lim
ln 9 n
n ⊆⊗ n 0.1
∴ lim
n ⊆⊗
∴ lim
(9 ln 8 n )(1 / n ) 0.1n (0.1Λ1)
∴ lim
9 ln 8 n
n⊆⊗ 0.1n 0.1
7
9 8 ln n
n ⊆⊗ ( 0.1) 2 n 0.1
... ∴ lim
9 8 1 ln 0 n
n ⊆⊗ ( 0.1) 9 n 0.1
สรุปไดวา ln9 n โตชากวา n0.1
∴0
อยากจะขอเนนย้ําตรงนี้เลยวาถา f1(n) และ f2(n) เปนฟงกชันของเวลาการทํางานของโปรแกรมที่ 1 และโปรแกรมที่ 2 ตามลําดับ โดยที่ n ขนาดของขอมูลของปญหาที่โปรแกรมทั้งสองรับเขาไปประมวลผล และถา f1(n) เปนฟงกชันที่โตเร็วกวา f2(n) ยอมสรุปไดวาโปรแกรมที่ 1 ทํางานชากวาโปรแกรมที่ 2 เมื่อ n มี คามาก ขอใหนักศึกษาอานขอความนี้ใหมอีกครั้ง สังเกตตรงทีข่ ดี เสนใตอกี ครัง้ เพือ่ กันความสับสน และใน ทางกลับกัน เมื่อ f1(n) เปนฟงกชันที่โตชากวา f2(n) ยอมสรุปไดวาโปรแกรมที่ 1 ทํางานเร็วกวาโปรแกรมที่ 2 เมื่อ n มีคามาก เรื่องที่ 2.2.5 สัญกรณโอใหญ การบรรยายเวลาการทํางานของโปรแกรมดวยฟงกชันซึ่งวิเคราะหมาไดจากการนับคําสั่งมาตรเวลา ตามทีไ่ ดนาํ เสนอมานัน้ บางทีอาจไดผลทีด่ ลู มุ ลาม เชน f(n) = 10n2 + n log n + 27n + 4 เปนตน เรา สามารถแทนตัวฟงกชันที่แลดูยุงๆ ยาวๆ ใหกระทัดรัดมากขึ้นไดดวยการใชสัญกรณโอใหญ (Big O notation) โดยเราเขียน f(n) = O(g(n)) เมื่อ f(n) เปนฟงกชันที่โตไมเร็วกวา g(n) เชิงเสนกํากับ นัน่ คือ f(n) = O(g(n)) เมื่อ
f ( n) [ c โดยที่ g n⊂℘ ( n) lim
c ∇ 0 และ c ⋅ ℘
เชน 10n2 + n log n + 27n + 4 = O(n2) ตีความงายๆ วา 10n2 + n log n + 27n + 4 เปนฟงกชันที่ โตไมเร็วกวา n2 เชิงเสนกํากับ ซึ่งใหความรูสึกกับผูอานไดทันทีวาโปรแกรมที่ใชเวลาการทํางานแบบ O(n2) มี อัตราการเติบโตของเวลาการทํางานไมเลวไปกวาแบบ n2 เมื่อ n มีคามาก ดังนัน้ การเปรียบเทียบประสิทธิ ภาพเชิงเวลาระหวางโปรแกรมตางๆ จึงกระทําไดงายขึ้น เราสามารถใหนิยามกับสัญกรณโอใหญไดในอีกรูปแบบหนึ่ง โดยกําหนดให O(g(n)) คือเซตของ ฟงกชันตางๆ ที่โตไมเร็วกวา g(n) เขียนไดดงั นี้ µ(g(n)) = { f(n) |
มีคาคงตัวบวกสองตัวคือ c และ n0 ที่ทําให f(n) ℑ cg(n) เมื่อ n ∇ n0 }
หมายความวาถา f(n) µ(g(n)) แสดงวาการเติบโตของ f(n) จะถูกกําหนดขอบเขตดานบนไวดวย ลักษณะการเติบโตของ g(n) นั่นคือเราสามารถหาคาคงตัวบวก c ที่ f(n) ℑ cg(n) เมื่อ n ∇ n0 แสดงเปนตัว อยางไดดงั ภาพประกอบ 2.3
38 c g(n) f (n)
n0
n
ภาพประกอบ 2.3 f(n) µ(g(n)) ตัวอยาง 2.1 จงแสดงใหเห็นจริงวา 2n2 + 500n + 1000log n = O(n2) ตองหาคา c และ n0 ที่ทําให 2n2 + 500n + 1000log n ℑ cn2 เปนจริงเสมอเมือ่ n ∇ n0 กําหนด ให c = 2+500+1000 = 1502 ก็สบายใจไดเลยวาอสมการนี้เปนจริงแนเมื่อ n ∇ 1 ตัวอยาง 2.2 จงแสดงใหเห็นจริงวา loga n = O( logb n ) สําหรับคาคงตัว a, b > 1 เนือ่ งจากเราสามารถแปลงฐานของ log จากฐาน a ไปเปนฐาน b ไดดวยการหารดวยคาคงตัว logb a นัน่ คือ loga n = (logb n) / (logb a) ดังนัน้ สรุปไดวา loga n = O( logb n ) ตัวอยางนี้ชี้ให เห็นวาเรามักจะไมใสฐานของ log ในสัญกรณเชิงเสนกํากับ เชน O(log n) เพราะวานอกจากจะ สะดวกแลว ยังไมมีผลใดๆ ดวย ดังนัน้ ในเชิงเสนกํากับแลว log1.1 n กับ log100 n มีอตั ราการเติบ โตเทากัน ตัวอยาง 2.3 :
จงแสดงใหเห็นจริงวา log n! = O( n log n )
จากนิยาม n! = n⌡ (n–1) … 2⌡1 แทนทุกๆ พจนทางขวาดวย n จะไดวา n! ℑ nn หาคา log ทั้ง สองขางได log n! ℑ n log n = µ(n log n) ตัวอยาง 2.4 :
n
จงแสดงใหเห็นจริงวา ¦ i k i [1
Φ Γ โดยที่ k เปนคาคงตัว
[ O n k Ι1
เนื่องจากภายในผลบวกนั้น i มีคาตั้งแต 1 ถึง n แสดงวา i ℑ n สรุปไดวา ik ℑ nk ดังนัน้ เมือ่ รวม ทุกๆ ik ตั้งแต 1 ถึง n ยอมไดวา ¦in[1 i k ℑ ¦in[1 n k = nk+1 = O(nk+1) การใชสัญกรณโอใหญเพื่อแทนประสิทธิภาพเวลาการทํางานนั้น มีประเด็นที่ตองเขาใจดังนี้ 1. หลายคนอาจถามตอนนี้แลววาทําไมบางทีเขียน f(n) = µ(g(n)) บางทีก็เขียน f(n) µ(g(n)) แลวจะตองใช = หรือ กันแน ? แบบที่ถูกตองใช เพราะวาตามนิยามแลว O(g(n)) นัน้ เปน เซต แตเรากลับพบกันบอยมากๆ เลยวาเขาใชเครือ่ งหมาย = กัน เพราะวาสะดวกดี อีกทัง้ อาน
39 ไดราบรืน่ โดยทั่วไปเราอาน f(n) = µ(g(n)) วา "f(n) เปนโอใหญของ g(n)" จึงตองคํานึงไวเสมอ วาเปน = ทางเดียว หมายความวา f(n) = O(g(n)) ไมไดหมายความวา O(g(n)) = f(n) 2. โดยทั่วไปแลวเราจะใชโอใหญเพื่อแทนฟงกชันที่ซับซอนดวยฟงกชันที่แลดูงายๆ เชนเขียน 10n2 + n log n + 27n + 4 = O(n2) สวน 10n2 = O(25n2 + n log n + 93n + 5) ถึงแมจะถูก ตองตามนิยาม แตก็จะไมเขียนกัน เพราะจุดประสงคของการใชสัญกรณโอใหญก็เพื่อแทนสิ่งที่ ยุง ดวยสิ่งที่เขาใจงายกวา 3. จากตัวอยาง 10n2 + n log n + 27n + 4 = O(n2) จะพบวา 10n2 + n log n + 27n + 4 ก็เปน O(n3) เปน O(n90) หรือเปน O(2n) ดวยเชนกัน เพราะ n3, n90 และ 2n ลวนแลวแตเปนฟงกชันที่ โตเร็วกวา n2 เชิงเสนกํากับทัง้ สิน้ แตเรามักเลือกใช g(n) ที่โตชาๆ ชาสุดเทาที่จะชาไดในการ แทน f(n) ดวย O(g(n)) ลองคิดก็แลวกันวาสมมติวาโปรแกรม A เรียกใชคําสั่งมาตรเวลาเปน จํานวน 10n2 + n log n + 27n + 4 ก็คงไมมีเหตุผลที่จะโฆษณาใหคนในวงการทราบวา A ใช เวลาการทํางานเปน O( n90 ) ถึงแมจะไมผิดที่จะบอกวา A ใชเวลาการทํางานไมเลวกวา n90 เชิง เสนกํากับ แตก็นาจะอวดวา A ใชเวลาการทํางานไมเลวกวา n2 เชิงเสนกํากับ จะดีกวา 4. เราใช O(1) แทนเซตของฟงกชันที่ไมโต ซึ่งรวมถึงคาคงตัวทั้งหลายดวย นอกจากวิธีการใชลิมิตและการใชนิยามของขอบเขตบนมาชวยเขียนบรรยายฟงกชันที่ยุงดวย ฟงกชันที่งายในโอใหญแลว มีอีกวิธีหนึ่งที่มักใชไดผลอยางรวดเร็ว ก็คือการตัดพจนที่โตชากวา และการตัด สัมประสิทธิท์ เ่ี ปนคาคงตัวออก เชน f(n) = 10n2 + n log n + 27n + 4 พบวาประกอบดวยพจนยอยๆ ที่เมื่อ เรียงลําดับตามอัตราการเติบโตจากมากไปนอยจะไดลําดับดังนี้คือ 10n2, n log n, 27n, 4 (อยาลืมวา n โตเร็ว กวา log n ดังนัน้ n2 ก็ยอ มโตเร็วกวา n log n) ดังนัน้ ก็เลือกสนใจเฉพาะพจนทโ่ี ตเร็วสุด เพราะในการ วิเคราะหเชิงเสนกํากับพจนที่โตเร็วสุดจะเปนตัวที่มีอิทธิพลสูงสุดในการกําหนดคาของฟงกชัน เมื่อ n มีคา มาก จึงสามารถเขียนไดเลยวา 10n2 + n log n + 27n + 4 = O(10n2) และเมื่อมาดูที่พจน 10n2 จะพบวา สัมประสิทธิซ์ ง่ึ เปนคาคงตัว 10 นัน้ สามารถตัดทิง้ ได เพราะไมมีผลใดๆตออัตราการเติบโต (คาลิมิตของ f(n) / g(n) จะไมเปลี่ยนแปลงเลยไมวาจะมี 10 อยูห รือไม) ดังนั้นจะไดวา 10n2 + n log n + 27n + 4 = O(n2) เรื่องที่ 2.2.6
ตัวอยางการวิเคราะหโปรแกรมเชิงเสนกํากับ
ตัวอยาง 2.5 :
จงวิเคราะหเวลาการทํางานเชิงเสนกํากับของสวนของโปรแกรมขางลางนี้ for i:=1 to 100 do for j:=1 to i do s := s + 1;
01: 02: 03:
ในที่นี้บรรทัดที่ 3 เปนคําสัง่ มาตรเวลา ซึ่งถูกเรียกใชงานเปนจํานวน 100 i
100
¦¦ ¦ i [ i [1 j [1
1[
i [1
100(100 Ι 1) [ 5050 2
ครัง้ หมายความวาใชเวลาคงตัวไมขึ้นกับขนาดของขอ
มูลขาเขาแตอยางใด ดังนั้นสวนของโปรแกรมนี้ใชเวลาเปน O(1)
40 ตัวอยาง 2.6 :
จงวิเคราะหเวลาการทํางานเชิงเสนกํากับของสวนของโปรแกรมขางลางนี้ 01: 02: 03:
for i:=1 to n do for j:=1 to i do s := s + 1;
ในที่นี้บรรทัดที่ 3 เปนคําสัง่ มาตรเวลา จะพบวาถูกเรียกใชงานเปนจํานวน n
i
n
¦¦1 [ ¦ i [ i [1 j [1
ตัวอยาง 2.7 :
i [1
n(n Ι 1) n 2 n [ Ι 2 2 2
ครัง้ ดังนั้นจึงใชเวลาเปน O(n2)
จงวิเคราะหเวลาการทํางานเชิงเสนกํากับของสวนของโปรแกรมขางลางนี้ 01: 02:
while n > 0 do n := n div 2;
ในที่นี้บรรทัดที่ 3 เปนคําสัง่ มาตรเวลา ใหสังเกตวาวงวนนี้จะเลิกทํางานเมื่อ n ℑ 0 ก็ตองมาดูวา คาของ n เปลีย่ นแปลงอยางไร คาของ n นัน้ ลดลงทีละครึง่ (ปดเศษทิ้ง) ก็แสดงวา n จะตองจบ ลงที่ศูนยอยางแนนอน (ในที่นี้ถือวา n มีคาเริ่มดวยจํานวนไมติดลบ) การทีม่ คี า ลดลงทีละครึง่ นัน้ n ในรอบที่ k ยอมมีคา n / 2k โดยกอนที่ n จะมีคา เปนศูนยแลวเลิกทํางานนัน้ n ก็ตอ งเทากับ 1 ดังนั้นรอบที่ทําให n มีคาเปน 1 ก็คอื k = log2 n สรุปไดวาวงวน while หมุนเปนจํานวน 1+log2 n รอบ ดังนัน้ เวลาการทํางานเปน O( log2 n ) ตัวอยาง 2.8 :
จงวิเคราะหเวลาการทํางานเชิงเสนกํากับของสวนของโปรแกรมขางลางนี้ 01: 02: 03: 04: 05: 06:
i := 1; j := n; while i < j do begin i := i + 3; j := j – 5; end;
วงวน while ทํางานตราบเทาที่ i < j โดยที่ i มีคาเริ่มตนที่นอยกวา j คาของ i เพิม่ ทีละสาม ในช ณะทีค่ า j ลดลงทีละหา แสดงวาจะตองมีชวงที่ i ∇ j แลวหลุดจากวงวนแน และคาของ i และ j จะเขยิบเขาหากันทีละ 8 แสดงวา จํานวนรอบที่หมุนในวงวนมีคาอยางมาก n/8 รอบ ดังนัน้ เวลา การทํางานเปน O( n ) โดยสรุปหาก n มาก มาตรวัดประสิทธิภาพสําหรับสัญกรณโอใหญ จากมากไปนอย ดังแสดงในตา รางที่ ตาราง 2.1
41 ตาราง 2.1 มาตรวัดประสิทธิภาพสําหรับสัญกรณโอใหญ จากมากไปนอย n=8
n =128
n = 1024
O(1)
1
1
1
O(log2n)
3
7
10
O(n)
3
11
32
O(n)
8
128
1,024
O(n⌡log2n)
24
896
10,240
O(n2)
64
16,192
1,048,576
O(n3)
512
2,097,152
1,073,741,824
O(2n)
256
3.40 x 1038
1.79 x 10308