มีวิธีการที่เป็นไปได้มากมายหลากหลาย สิ่งที่เหมาะสมที่สุดขึ้นอยู่กับ
- สิ่งที่คุณพยายามแสดง
- คุณต้องการหรือต้องการรายละเอียดมากน้อยเพียงใด
หากอัลกอริทึมเป็นที่รู้จักอย่างกว้างขวางซึ่งคุณใช้เป็นรูทีนย่อยคุณมักจะอยู่ในระดับที่สูงขึ้น หากอัลกอริทึมเป็นวัตถุหลักที่อยู่ระหว่างการตรวจสอบคุณอาจต้องการรายละเอียดเพิ่มเติม สามารถพูดเช่นเดียวกันสำหรับการวิเคราะห์: ถ้าคุณต้องการรันไทม์บนคร่าวๆที่คุณจะดำเนินการแตกต่างจากเมื่อคุณต้องการนับงบที่แม่นยำ
ฉันจะให้คุณสามตัวอย่างสำหรับอัลกอริทึมที่รู้จักกันดีการผสานซึ่งหวังว่าจะแสดงสิ่งนี้
ระดับสูง
อัลกอริทึมที่ผสานรับรายการแบ่งออกเป็นสองส่วน (ประมาณ) ส่วนเท่า ๆ กันยาวซ้ำในรายการบางส่วนเหล่านั้นและผสานผลลัพธ์ (เรียงลำดับ) เพื่อผสานผลลัพธ์สุดท้าย ในรายการเดี่ยวหรือเปล่ามันจะส่งกลับเข้า
เห็นได้ชัดว่าอัลกอริทึมนี้เป็นอัลกอริทึมการเรียงลำดับที่ถูกต้อง การแยกรายการและการรวมมันสามารถทำได้ในเวลาซึ่งทำให้เราเกิดซ้ำสำหรับกรณีที่เลวร้ายที่สุดT ( n ) = 2 T ( n)Θ(n)) โดยทฤษฎีบทโทประเมินนี้เพื่อT(n)∈Θ(nlogn)T(n)=2T(n2)+Θ(n)T(n)∈Θ(nlogn)
ระดับปานกลาง
การรวมอัลกอริทึมได้รับจากรหัสหลอกต่อไปนี้:
procedure mergesort(l : List) {
if ( l.length < 2 ) {
return l
}
left = mergesort(l.take(l.length / 2)
right = mergesort(l.drop(l.length / 2)
result = []
while ( left.length > 0 || right.length > 0 ) {
if ( right.length == 0 || (left.length > 0 && left.head <= right.head) ) {
result = left.head :: result
left = left.tail
}
else {
result = right.head :: result
right = right.tail
}
}
return result.reverse
}
เราพิสูจน์ความถูกต้องโดยอุปนัย สำหรับรายการที่มีความยาวเป็นศูนย์หรืออย่างใดอย่างหนึ่งอัลกอริทึมนั้นถูกต้องเล็กน้อย ในฐานะที่เป็นสมมติฐานเหนี่ยวนำสมมติmergesort
ดำเนินการอย่างถูกต้องในรายชื่อที่มีความยาวมากที่สุดสำหรับพลบางส่วน แต่คงธรรมชาติn > 1 ตอนนี้ขอLเป็นรายการยาวn + 1 โดยสมมติฐานการเหนี่ยวนำและการจัดเรียงรุ่นแรกของ resp แรก ครึ่งหลังของLหลังจากการเรียกซ้ำ ดังนั้นการเลือกวงในทุกองค์ประกอบที่เล็กย้ำไม่ตรวจสอบและยังผนวกมัน; จึงเป็นรายการที่ไม่เรียงลำดับมากขึ้นที่มีองค์ประกอบทั้งหมดnn>1Ln+1left
right
Lwhile
result
result
left
right
และ ย้อนกลับเป็นรุ่นเรียงลำดับแบบไม่ลดลงซึ่งเป็นผลลัพธ์ที่ส่งคืนและที่ต้องการL
สำหรับรันไทม์ให้เรานับการเปรียบเทียบองค์ประกอบและการดำเนินการรายการ (ซึ่งครองไทม์ asymptotically) รายการความยาวน้อยกว่าสองสาเหตุไม่ สำหรับรายการของความยาวเรามีการดำเนินงานที่เกิดจากการจัดเตรียมปัจจัยการผลิตสำหรับการโทรซ้ำผู้ที่มาจากสาย recursive ตัวเองบวกห่วงและเป็นหนึ่งใน พารามิเตอร์แบบเรียกซ้ำทั้งสองสามารถคำนวณได้ด้วยการดำเนินรายการไม่เกินnรายการแต่ละรายการ การวนซ้ำถูกดำเนินการอย่างแน่นอนnครั้งและการวนซ้ำทุกครั้งจะทำให้เกิดการเปรียบเทียบองค์ประกอบหนึ่งรายการและการดำเนินการรายการสองรายการ สุดท้ายสามารถนำมาใช้เพื่อใช้2 nn>1while
reverse
nwhile
nreverse
2nการดำเนินการรายการ - ทุกองค์ประกอบจะถูกลบออกจากอินพุตและใส่ลงในรายการเอาท์พุท ดังนั้นการดำเนินการนับตอบสนองการเกิดซ้ำดังต่อไปนี้:
T(0)=T(1)T(n)=0≤T(⌈n2⌉)+T(⌊n2⌋)+7n
เนื่องจากเห็นได้ชัดว่าไม่ลดลงจึงเพียงพอที่จะพิจารณาn = 2 kสำหรับการเจริญเติบโตของซีมโทติค ในกรณีนี้การเกิดซ้ำจะง่ายขึ้นTn=2k
T(0)=T(1)T(n)=0≤2T(n2)+7n
โดยทฤษฎีบทปริญญาโทที่เราได้รับซึ่งทอดตัวรันไทม์ของT∈Θ(nlogn)mergesort
ระดับต่ำพิเศษ
พิจารณานี้ (ทั่วไป) การดำเนินงานของ mergesort ในอิสซาเบล / HOL :
types dataset = "nat * string"
fun leq :: "dataset \<Rightarrow> dataset \<Rightarrow> bool" where
"leq (kx::nat, dx) (ky, dy) = (kx \<le> ky)"
fun merge :: "dataset list \<Rightarrow> dataset list \<Rightarrow> dataset list" where
"merge [] b = b" |
"merge a [] = a" |
"merge (a # as) (b # bs) = (if leq a b then a # merge as (b # bs) else b # merge (a # as) bs)"
function (sequential) msort :: "dataset list \<Rightarrow> dataset list" where
"msort [] = []" |
"msort [x] = [x]" |
"msort l = (let mid = length l div 2 in merge (msort (take mid l)) (msort (drop mid l)))"
by pat_completeness auto
termination
apply (relation "measure length")
by simp+
ซึ่งรวมถึงบทพิสูจน์ของความชัดเจนและการเลิกจ้าง ค้นหาหลักฐานถูกต้อง (เกือบ) สมบูรณ์ที่นี่
สำหรับ "รันไทม์" นั่นคือจำนวนการเปรียบเทียบการเกิดซ้ำที่คล้ายกับที่อยู่ในส่วนก่อนหน้านั้นสามารถตั้งค่าได้ แทนที่จะใช้ทฤษฎีบทต้นแบบและลืมค่าคงที่คุณสามารถวิเคราะห์เพื่อให้ได้ค่าประมาณที่เท่ากับเชิงปริมาณเท่ากับจำนวนจริง คุณสามารถค้นหาการวิเคราะห์แบบเต็มได้ใน [1]; นี่คือคร่าวๆ (มันไม่จำเป็นต้องพอดีกับรหัส Isabelle / HOL):
ดังกล่าวข้างต้นการเกิดซ้ำของจำนวนการเปรียบเทียบคือ
f0=f1fn=0=f⌈n2⌉+f⌊n2⌋+en
โดยที่คือจำนวนการเปรียบเทียบที่จำเป็นสำหรับการผสานผลลัพธ์บางส่วน² เพื่อกำจัดพื้นและเพดานเราดำเนินการแยกความแตกต่างของเคสว่าnคือ:enn
{f2mf2m+1=2fm+e2m=fm+fm+1+e2m+1
การใช้ความแตกต่างไปข้างหน้า / ถอยหลังแบบซ้อนของและe nเราได้สิ่งนั้นfnen
1∑k=1n−1(n−k)⋅Δ∇fk=fn−nf1
ผลรวมตรงด้านขวามือของสูตร Perron ของ เรากำหนดชุดสร้าง Dirichletของเป็นΔ∇fk
W(s)=∑k≥1Δ∇fkk−s=11−2−s⋅∑k≥1Δ∇ekks=: ⊟(s)
ซึ่งพร้อมกับสูตรของ Perron ทำให้เรา
sfn=nf1+n2πi∫3−i∞3+i∞⊟(s)ns(1−2−s)s(s+1)ds
การประเมินผลของขึ้นอยู่กับกรณีที่มีการวิเคราะห์ นอกเหนือจากนั้นเราสามารถ - หลังจากใช้เล่ห์เหลี่ยมบางอย่าง - ใช้ทฤษฎีที่เหลือเพื่อรับ⊟(s)
fn∼n⋅log2(n)+n⋅A(log2(n))+1
ที่เป็นฟังก์ชั่นระยะที่มีค่าใน[ - 1 , - 0.9 ]A[−1,−0.9]
- Mellin แปลงและ asymptotics: การเกิดซ้ำของการควบรวมกิจการโดย Flajolet และ Golin (1992)
- en=⌊n2⌋
en=n−1
en=n−⌊n2⌋⌈n2⌉+1−⌈n2⌉⌊n2⌋+1