ความแตกต่างระหว่างอัลกอริทึมของ Prim และ Dijkstra?


102

อะไรคือความแตกต่างที่แน่นอนระหว่างอัลกอริทึมของ Dijkstra และ Prim ฉันรู้ว่า Prim จะให้ MST แต่ต้นไม้ที่ Dijkstra สร้างขึ้นก็จะเป็น MST เช่นกัน แล้วความแตกต่างที่แน่นอนคืออะไร?


5
มันคือ Dijkstra "ij" เป็นคำควบกล้ำ (สระร่อน) ในภาษาดัตช์และเป็นที่เดียวที่ "j" ไม่ใช่พยัญชนะ

23
วิธีใดก็ได้ที่คุณมีคำถาม
anuj pradhan

5
วิธีที่ดีที่สุดที่จะแยกแยะความแตกต่างของพวกเขาจะอ่านรหัสที่มา , DijkstraและPrim ความแตกต่างที่สำคัญคือที่นี่: สำหรับ Prim graph[u][v] < key[v]และสำหรับ dist[u]+graph[u][v] < dist[v]Dijkstra ดังที่คุณเห็นจากกราฟในสองหน้านั้นส่วนใหญ่แตกต่างกันเนื่องจากโค้ดสองบรรทัดนี้
JW.ZG

คำตอบ:


156

อัลกอริทึมของ Prim สร้างต้นไม้ที่มีระยะขั้นต่ำสำหรับกราฟซึ่งเป็นต้นไม้ที่เชื่อมต่อโหนดทั้งหมดในกราฟและมีต้นทุนรวมน้อยที่สุดในบรรดาต้นไม้ทั้งหมดที่เชื่อมต่อโหนดทั้งหมด อย่างไรก็ตามความยาวของเส้นทางระหว่างสองโหนดใน MST อาจไม่ใช่เส้นทางที่สั้นที่สุดระหว่างสองโหนดในกราฟดั้งเดิม MST มีประโยชน์เช่นหากคุณต้องการเชื่อมต่อโหนดในกราฟทางกายภาพเพื่อให้กระแสไฟฟ้าแก่พวกเขาโดยมีต้นทุนรวมน้อยที่สุด ไม่สำคัญว่าความยาวเส้นทางระหว่างสองโหนดอาจไม่เหมาะสมที่สุดเนื่องจากสิ่งที่คุณสนใจคือความจริงที่ว่าเชื่อมต่อกัน

อัลกอริทึมของ Dijkstra สร้างแผนผังเส้นทางที่สั้นที่สุดโดยเริ่มจากโหนดต้นทาง แผนผังเส้นทางที่สั้นที่สุดคือต้นไม้ที่เชื่อมต่อโหนดทั้งหมดในกราฟกลับไปยังโหนดต้นทางและมีคุณสมบัติที่ความยาวของเส้นทางใด ๆ จากโหนดต้นทางไปยังโหนดอื่น ๆ ในกราฟจะถูกย่อให้เล็กที่สุด สิ่งนี้มีประโยชน์เช่นหากคุณต้องการสร้างเครือข่ายถนนที่ทำให้ทุกคนไปถึงจุดสังเกตสำคัญ ๆ ได้อย่างมีประสิทธิภาพมากที่สุด อย่างไรก็ตามไม่รับประกันว่าต้นไม้พา ธ ที่สั้นที่สุดจะเป็นต้นไม้ที่มีการขยายขั้นต่ำและผลรวมของต้นทุนบนขอบของต้นไม้เส้นทางที่สั้นที่สุดอาจมากกว่าต้นทุนของ MST มาก

ความแตกต่างที่สำคัญอีกประการหนึ่งเกี่ยวกับประเภทของกราฟที่อัลกอริทึมทำงาน อัลกอริทึมของ Prim ทำงานบนกราฟที่ไม่ได้กำหนดทิศทางเท่านั้นเนื่องจากแนวคิดของ MST ถือว่ากราฟไม่ได้ถูกกำหนดทิศทางโดยเนื้อแท้ (มีบางสิ่งที่เรียกว่า "การขยายระยะห่างขั้นต่ำ" สำหรับกราฟที่กำหนดทิศทาง แต่อัลกอริทึมในการค้นหานั้นซับซ้อนกว่ามาก) อัลกอริทึมของ Dijkstra จะทำงานได้ดีกับกราฟที่กำหนดทิศทางเนื่องจากต้นไม้เส้นทางที่สั้นที่สุดสามารถกำหนดทิศทางได้ นอกจากนี้อัลกอริทึมของ Dijkstra ไม่จำเป็นต้องให้คำตอบที่ถูกต้องในกราฟที่มีน้ำหนักขอบลบในขณะที่อัลกอริทึมของ Prim สามารถจัดการสิ่งนี้ได้

หวังว่านี่จะช่วยได้!


ย่อหน้าแรกไม่สมเหตุสมผลผู้ชาย คำถามคืออะไรคือความแตกต่างระหว่างDijkstraและ Prim โดยที่Dijkstraไม่เกี่ยวกับสิ่งที่คุณพูดthe length of a path between **any** two nodesคุณควรโฟกัสว่าทำไมระยะห่างระหว่างโหนด src และโหนดอื่น ๆ ใน Prim จึงไม่สั้นที่สุดหากไม่สั้นที่สุด ผมคิดว่าเขาจะต้องขอให้โหนด src ใน Prim ไปยังโหนดอื่น ทำไมคุณถึงพูดถึงสองโหนดใน Prim? นั่นไม่ใช่สิ่งที่สั้นที่สุด
JW.ZG

2
ฉันได้ทำความสะอาดถ้อยคำในย่อหน้าเกี่ยวกับอัลกอริทึมของ Dijkstra เพื่อชี้แจงว่าแผนผังเส้นทางที่สั้นที่สุดเป็นเพียงตัวย่อสำหรับเส้นทางที่สั้นที่สุดที่มาจากโหนดต้นทาง เหตุผลที่ฉันจัดโครงสร้างคำตอบของฉันนี้เป็นวิธีการแสดงให้เห็นว่าอัลกอริทึมค้นหาอะไรมากกว่าวิธีที่พวกเขาทำงานเพื่อแสดงในระดับที่สูงขึ้นว่าเหตุใดจึงให้ผลลัพธ์ที่แตกต่างกันและทำไมคุณไม่คาดหวังให้พวกเขาเหมือนกัน
templatetypedef

1
คำอธิบายที่ง่ายที่สุดคือใน Prims คุณไม่ได้ระบุโหนดเริ่มต้นแต่ใน dijsktra คุณ (ต้องมีโหนดเริ่มต้น) ต้องหาเส้นทางที่สั้นที่สุดจากโหนดที่กำหนดไปยังโหนดอื่น ๆ ทั้งหมด ดูstackoverflow.com/a/51605961/6668734
Deepak Yadav

1
@templatetypedef - เมื่อคุณบอกว่า: "และค่าใช้จ่ายของการสร้างเช่นต้นไม้ [กับ Dijkstra] อาจจะมีขนาดใหญ่กว่าค่าใช้จ่ายของ MST ได้." ช่วยอธิบายให้ละเอียดหน่อยได้ไหม
Amelio Vazquez-Reina

1
@ AmelioVazquez-Reina ขออภัยบิตนั้นคลุมเครือ สิ่งที่ฉันหมายถึงคือผลรวมของน้ำหนักบนขอบของต้นไม้เส้นทางที่สั้นที่สุดอาจมากกว่าผลรวมของน้ำหนักบนขอบใน MST
templatetypedef

88

อัลกอริทึมของ Dijkstra ไม่ได้สร้าง MST แต่พบว่าเส้นทางที่สั้นที่สุด

พิจารณากราฟนี้

       5     5
  s *-----*-----* t
     \         /
       -------
         9

เส้นทางที่สั้นที่สุดคือ 9 ในขณะที่ MST เป็น 'เส้นทาง' ที่แตกต่างกันที่ 10


2
โอเคขอบคุณ ... คุณเคลียร์ประเด็นดีๆที่จะแจ้งให้ทราบ จนถึงตอนนี้ฉันกำลังพิจารณาว่าผลลัพธ์ที่สร้างโดย dijkstra จะเป็น MST แต่คุณเคลียร์ข้อสงสัยด้วยตัวอย่างที่ดีฉันเห็นได้ชัดเจนว่าฉันจะพบ MST โดยใช้คำว่า 'kruskal' จากนั้นฉันจะได้รับเส้นทางเดียวกันกับที่คุณพูดถึง . ขอบคุณมาก
anuj pradhan

8
อย่างถูกต้องมากขึ้น - The shortest path is 9... จาก s ถึง t น้ำหนักของกราฟที่สร้างโดยอัลกอริทึมของ Dijkstra เริ่มต้นที่ s คือ 14 (5 + 9)
Bernhard Barker

1
@ ดูเกลิง - หือ? น้ำหนักของต้นไม้ / กราฟใน Dijkstra ไม่มีความหมายนั่นคือประเด็น ....
dfb

4
ภาพประกอบรวบรัดมาก!
Ram Narasimhan

1
@dfb: โดยปกติเราจะเรียกใช้อัลกอริทึมของ Dijkstra เพื่อให้ได้เส้นทางที่สั้นที่สุดระหว่างจุดยอดคู่หนึ่ง แต่ในความเป็นจริงคุณสามารถดำเนินการต่อไปได้จนกว่าจะมีการเยี่ยมชมจุดยอดทั้งหมดและนี่จะทำให้คุณมี "เส้นทางที่สั้นที่สุด" เป็นคำตอบของ templatetypedef อธิบาย
j_random_hacker

69

อัลกอริทึม Prim และ Dijkstra เกือบจะเหมือนกันยกเว้น "ฟังก์ชันผ่อนคลาย"

พริม:

MST-PRIM (G, w, r) {
    for each key ∈ G.V
        u.key = ∞
        u.parent = NIL
    r.key = 0
    Q = G.V

    while (Q ≠ ø)
        u = Extract-Min(Q)
        for each v ∈ G.Adj[u]
            if (v ∈ Q)
                alt = w(u,v)    <== relax function, Pay attention here
                if alt < v.key
                    v.parent = u
                    v.key = alt
}

Dijkstra:

Dijkstra (G, w, r) {
    for each key ∈ G.V
        u.key = ∞
        u.parent = NIL
    r.key = 0
    Q = G.V

    while (Q ≠ ø)
        u = Extract-Min(Q)
        for each v ∈ G.Adj[u]
            if (v ∈ Q)
                alt = w(u,v) + u.key  <== relax function, Pay attention here
                if alt < v.key
                    v.parent = u
                    v.key = alt
}

ข้อแตกต่างเพียงอย่างเดียวคือลูกศรชี้ซึ่งเป็นฟังก์ชันผ่อนคลาย

  • Prim ซึ่งค้นหาต้นไม้ที่มีระยะทอดน้อยที่สุดจะสนใจเฉพาะค่าต่ำสุดของขอบทั้งหมดที่ครอบคลุมจุดยอดทั้งหมด ฟังก์ชั่นการผ่อนคลายคือalt = w(u,v)
  • Dijkstra ซึ่งค้นหาความยาวเส้นทางขั้นต่ำดังนั้นจึงให้ความสำคัญกับการสะสมขอบ ฟังก์ชั่นการผ่อนคลายคือalt = w(u,v) + u.key

ในระดับโค้ดความแตกต่างอื่น ๆ คือ API Prim มีวิธีการedges()ที่จะกลับขอบ MST ขณะ Dijkstra มีdistanceTo(v), pathTo(v)ซึ่งตามลำดับผลตอบแทนระยะทางจากต้นทางไปยังจุดสุดยอดวีและเส้นทางจากแหล่งที่จุดสุดยอดวีซึ่งคือจุดสุดยอดการเริ่มต้นของคุณ Dijkstra กับ
nethsix

2
ข้อพิสูจน์เริ่มต้น Prim กับจุดสุดยอดแหล่งใด, s ผลตอบแทนเอาท์พุทเดียวกันedges()แต่การเริ่มต้นกับ Dijkstra s แตกต่างกันจะส่งกลับผลลัพธ์ที่แตกต่างกันสำหรับ,distanceTo(v) pathTo(v)
nethsix

รองพื้นอนุญาตให้น้ำหนักติดลบหรือไม่? ถ้าใช่กว่านี้ก็เป็นอีกความแตกต่าง ฉันอ่านว่าคุณสามารถอนุญาตน้ำหนักเชิงลบของไพรม์ได้โดยการเพิ่มจำนวนบวกมาก แต่ละค่าทำให้เป็นบวกทั้งหมด
Akhil Dad

1
แก้ไขความสับสนของฉัน! ตอบโจทย์เป๊ะ !!
Dhananjay Sarsonia

ที่นี่จุดยอดที่ประมวลผลจะต้องถูกละเว้นสำหรับกราฟที่ไม่ได้บอกทิศทาง
Mr AJ

53

อัลกอริทึมของ Dijsktra ค้นหาระยะทางต่ำสุดจากโหนด i ถึงโหนดทั้งหมด (คุณระบุ i) ดังนั้นในทางกลับกันคุณจะได้โครงสร้างระยะทางต่ำสุดจากโหนด i

อัลกอริทึม Prims ช่วยให้คุณมีระยะห่างขั้นต่ำสำหรับกราฟที่กำหนดสำหรับกราฟที่กำหนดต้นไม้ที่เชื่อมต่อโหนดทั้งหมดในขณะที่ผลรวมของต้นทุนทั้งหมดต่ำสุดที่เป็นไปได้

ดังนั้นด้วย Dijkstra คุณสามารถเปลี่ยนจากโหนดที่เลือกไปยังโหนดอื่น ๆ ได้ด้วยต้นทุนขั้นต่ำคุณจะไม่ได้รับสิ่งนี้ด้วย Prim's


คำอธิบายที่ง่ายที่สุดคือใน Prims คุณไม่ได้ระบุโหนดเริ่มต้นแต่ใน dijsktra คุณ (ต้องมีโหนดเริ่มต้น) ต้องหาเส้นทางที่สั้นที่สุดจากโหนดที่กำหนดไปยังโหนดอื่น ๆ ทั้งหมด ดูstackoverflow.com/a/51605961/6668734
Deepak Yadav

32

ข้อแตกต่างเพียงอย่างเดียวที่ฉันเห็นคืออัลกอริทึมของ Prim จัดเก็บขอบต้นทุนขั้นต่ำในขณะที่อัลกอริทึมของ Dijkstra เก็บต้นทุนทั้งหมดจากจุดยอดต้นทางไปยังจุดยอดปัจจุบัน

Dijkstra ช่วยให้คุณมีทางจากโหนดต้นทางไปยังโหนดปลายทางเพื่อให้ต้นทุนต่ำสุด อย่างไรก็ตามอัลกอริทึมของ Prim ช่วยให้คุณมีโครงสร้างการขยายขั้นต่ำเพื่อที่จะเชื่อมต่อโหนดทั้งหมดและต้นทุนรวมต่ำสุด

พูดง่ายๆคือ

ดังนั้นหากคุณต้องการใช้รถไฟเพื่อเชื่อมต่อหลายเมืองคุณควรใช้ Prim's algo แต่ถ้าคุณต้องการเดินทางจากเมืองหนึ่งไปยังเมืองอื่นโดยประหยัดเวลาให้มากที่สุดคุณจะใช้ Algo ของ Dijkstra


24

ทั้งสองสามารถใช้งานได้โดยใช้อัลกอริทึมทั่วไปที่เหมือนกันทุกประการดังนี้

Inputs:
  G: Graph
  s: Starting vertex (any for Prim, source for Dijkstra)
  f: a function that takes vertices u and v, returns a number

Generic(G, s, f)
    Q = Enqueue all V with key = infinity, parent = null
    s.key = 0
    While Q is not empty
        u = dequeue Q
        For each v in adj(u)
            if v is in Q and v.key > f(u,v)
                v.key = f(u,v)
                v.parent = u

สำหรับ Prim ผ่านf = w(u, v)และ Dijkstra f = u.key + w(u, v)ผ่าน

สิ่งที่น่าสนใจอีกประการหนึ่งคือข้างต้น Generic ยังสามารถใช้ Breadth First Search (BFS) ได้แม้ว่าจะใช้งานมากเกินไปเนื่องจากไม่จำเป็นต้องใช้คิวลำดับความสำคัญที่มีราคาแพง ในการเปลี่ยนอัลกอริทึมทั่วไปใน BFS ให้ส่งผ่านf = u.key + 1ซึ่งเหมือนกับการบังคับใช้น้ำหนักทั้งหมดเป็น 1 (เช่น BFS ให้จำนวนขอบขั้นต่ำที่จำเป็นในการเคลื่อนที่จากจุด A ถึง B)

ปรีชา

นี่เป็นวิธีที่ดีวิธีหนึ่งในการคิดเกี่ยวกับอัลกอริทึมทั่วไปข้างต้น: เราเริ่มต้นด้วยสองถัง A และ B ในขั้นต้นให้ใส่จุดยอดทั้งหมดของคุณใน B เพื่อให้ที่เก็บข้อมูล A ว่างเปล่า จากนั้นเราย้ายจุดยอดหนึ่งจาก B ไป A ตอนนี้ดูที่ขอบทั้งหมดจากจุดยอดใน A ที่ข้ามไปยังจุดยอดใน B เราเลือกขอบเดียวโดยใช้เกณฑ์บางอย่างจากขอบกากบาทเหล่านี้และย้ายจุดยอดที่เกี่ยวข้องจาก B ไปยัง A. ทำซ้ำขั้นตอนนี้จนกว่า B จะว่างเปล่า

วิธีบังคับแบบเดรัจฉานในการนำแนวคิดนี้ไปใช้คือการรักษาลำดับความสำคัญของขอบสำหรับจุดยอดใน A ที่ข้ามไปยัง B แน่นอนว่าจะเป็นปัญหาหากกราฟไม่เบาบาง คำถามก็คือเราจะรักษาลำดับความสำคัญของจุดยอดได้หรือไม่? ในความเป็นจริงเราสามารถตัดสินใจได้ในที่สุดว่าจุดยอดใดที่จะเลือกจาก B

บริบททางประวัติศาสตร์

เป็นที่น่าสนใจว่าเทคนิคทั่วไปที่อยู่เบื้องหลังอัลกอริทึมทั้งสองนั้นมีแนวคิดที่เก่าแก่ถึงปี 1930 แม้ว่าคอมพิวเตอร์อิเล็กทรอนิกส์จะไม่อยู่ในบริเวณนั้นก็ตาม

เรื่องราวเริ่มต้นด้วย Otakar Borůvkaที่ต้องการอัลกอริทึมสำหรับเพื่อนในครอบครัวที่พยายามหาวิธีเชื่อมต่อเมืองต่างๆในประเทศ Moravia (ปัจจุบันเป็นส่วนหนึ่งของสาธารณรัฐเช็ก) ด้วยสายไฟฟ้าที่มีต้นทุนน้อยที่สุด เขาตีพิมพ์อัลกอริทึมของเขาในปี 1926 ในวารสารที่เกี่ยวข้องกับคณิตศาสตร์เนื่องจากวิทยาการคอมพิวเตอร์ไม่มีอยู่จริง สิ่งนี้เกิดขึ้นในความสนใจของVojtěchJarníkซึ่งคิดจะปรับปรุงอัลกอริทึมของBorůvkaและเผยแพร่ในปี 1930 อันที่จริงเขาได้ค้นพบอัลกอริทึมเดียวกับที่เรารู้จักกันในชื่ออัลกอริทึมของ Prim ซึ่งค้นพบอีกครั้งในปี 2500

เป็นอิสระจากสิ่งเหล่านี้ในปีพ. ศ. 2499 Dijkstra จำเป็นต้องเขียนโปรแกรมเพื่อแสดงให้เห็นถึงความสามารถของคอมพิวเตอร์เครื่องใหม่ที่สถาบันของเขาได้พัฒนาขึ้น เขาคิดว่าคงเป็นการดีที่จะให้คอมพิวเตอร์ค้นหาการเชื่อมต่อเพื่อเดินทางระหว่างสองเมืองของเนเธอร์แลนด์ เขาออกแบบอัลกอริทึมใน 20 นาที เขาสร้างกราฟของ 64 เมืองโดยมีการปรับให้เรียบง่าย (เนื่องจากคอมพิวเตอร์ของเขาเป็น 6 บิต) และเขียนโค้ดสำหรับคอมพิวเตอร์ปี 1956 เครื่องนี้ อย่างไรก็ตามเขาไม่ได้เผยแพร่อัลกอริทึมของเขาเนื่องจากโดยหลักแล้วไม่มีวารสารวิทยาศาสตร์คอมพิวเตอร์และเขาคิดว่าสิ่งนี้อาจไม่สำคัญมากนัก ในปีถัดไปเขาได้เรียนรู้เกี่ยวกับปัญหาการเชื่อมต่อเทอร์มินัลของคอมพิวเตอร์เครื่องใหม่ซึ่งทำให้ความยาวของสายไฟลดลง เขาคิดถึงปัญหานี้และค้นพบJarník / Prim 'อีกครั้ง s อัลกอริทึมซึ่งใช้เทคนิคเดียวกับอัลกอริทึมเส้นทางที่สั้นที่สุดที่เขาค้นพบเมื่อปีก่อนอีกครั้ง เขากล่าวว่าอัลกอริทึมทั้งสองของเขาได้รับการออกแบบโดยไม่ใช้ปากกาหรือกระดาษ ในปีพ. ศ. 2502 เขาได้ตีพิมพ์อัลกอริทึมทั้งสองในกระดาษที่มีความยาวเพียง 2 หน้าครึ่ง


ขอบคุณ! ทางออกนั้นคลุมเครือทำไมมันถึงออกจากวงแม้ว่าจะไม่มีอะไรเกิดขึ้น?
amirouche

15

Dijkstra ค้นหาเส้นทางที่สั้นที่สุดระหว่างโหนดเริ่มต้นกับโหนดอื่น ๆ ดังนั้นในทางกลับกันคุณจะได้รับต้นไม้ระยะทางต่ำสุดจากโหนดเริ่มต้นนั่นคือคุณสามารถเข้าถึงโหนดอื่น ๆ ได้อย่างมีประสิทธิภาพที่สุด

อัลกอริทึม Prims ทำให้คุณได้รับ MST สำหรับกราฟที่กำหนดเช่นต้นไม้ที่เชื่อมต่อโหนดทั้งหมดในขณะที่ผลรวมของต้นทุนทั้งหมดต่ำสุดที่เป็นไปได้

หากต้องการสร้างเรื่องสั้นด้วยตัวอย่างที่เป็นจริง:

  1. Dijkstra ต้องการทราบเส้นทางที่สั้นที่สุดไปยังแต่ละจุดปลายทางโดยประหยัดเวลาและเชื้อเพลิงในการเดินทาง
  2. พริมต้องการทราบวิธีการใช้ระบบรางรถไฟอย่างมีประสิทธิภาพนั่นคือการประหยัดค่าวัสดุ

10

โดยตรงจากบทความวิกิพีเดียของ Algorithm ของ Dijkstra :

กระบวนการที่อยู่ภายใต้อัลกอริทึมของ Dijkstra นั้นคล้ายกับกระบวนการโลภที่ใช้ในอัลกอริทึมของ Prim จุดประสงค์ของ Prim คือการค้นหาต้นไม้ที่มีระยะห่างขั้นต่ำที่เชื่อมต่อโหนดทั้งหมดในกราฟ Dijkstra เกี่ยวข้องกับโหนดเพียงสองโหนด Prim's ไม่ได้ประเมินน้ำหนักรวมของเส้นทางจากโหนดเริ่มต้นเพียงแต่ละเส้นทาง


5
"Dijkstra เกี่ยวข้องกับโหนดเพียงสองโหนด" เป็นสองชั้น
tmyklebu

5

เมื่อเร็ว ๆ นี้ฉันรู้สึกกังวลกับคำถามเดิม ๆ และฉันคิดว่าฉันอาจจะแบ่งปันความเข้าใจของฉัน ...

ฉันคิดว่าความแตกต่างที่สำคัญระหว่างสองอัลกอริทึม (Dijkstra และ Prim) รากในปัญหาที่พวกเขาออกแบบมาเพื่อแก้ปัญหากล่าวคือเส้นทางที่สั้นที่สุดระหว่างสองโหนดและต้นไม้ที่มีการขยายน้อยที่สุด (MST) ทางการคือการค้นหาเส้นทางที่สั้นที่สุดระหว่าง say, node sและtและข้อกำหนดที่เป็นเหตุเป็นผลคือการไปที่ขอบกราฟแต่ละด้านมากที่สุดในครั้งเดียว อย่างไรก็ตามเราไม่จำเป็นต้องไปที่โหนดทั้งหมด ประการหลัง (MST) คือการให้เราเยี่ยมชมALLที่โหนด (มากที่สุดครั้งเดียว) และด้วยความต้องการเหตุผลเดียวกันในการเยี่ยมชมแต่ละขอบพร้อมกันมากที่สุด

ตามที่กล่าวไว้ Dijkstra ช่วยให้เรา "ใช้ทางลัด" ได้นานมากที่ฉันจะได้รับจากsไปtโดยไม่ต้องกังวลกับผลลัพธ์ - เมื่อฉันไปถึงtฉันก็ทำสำเร็จ! แม้ว่าจะมีเส้นทางจากsถึงtใน MST แต่เส้นทางs - tนี้ถูกสร้างขึ้นโดยคำนึงถึงโหนดที่เหลือทั้งหมดดังนั้นเส้นทางนี้อาจยาวกว่าเส้นทางs - t ที่พบโดยอัลกอริทึมของ Dijstra ด้านล่างนี้เป็นตัวอย่างสั้น ๆ ที่มี 3 โหนด:

                                  2       2  
                          (s) o ----- o ----- o (t)     
                              |               |
                              -----------------
                                      3

สมมติว่าขอบด้านบนแต่ละด้านมีต้นทุนเป็น 2 และขอบด้านล่างมีต้นทุนเป็น 3 จากนั้น Dijktra จะบอกให้เราใช้เส้นทางด้านล่างเนื่องจากเราไม่สนใจโหนดตรงกลาง ในทางกลับกัน Prim จะส่ง MST กลับมาให้เราพร้อมกับขอบ 2 ด้านบนโดยทิ้งขอบด้านล่าง

ความแตกต่างดังกล่าวสะท้อนให้เห็นจากความแตกต่างเล็กน้อยในการนำไปใช้: ในอัลกอริทึมของ Dijkstra เราต้องมีขั้นตอนการเก็บหนังสือ (สำหรับทุกโหนด) เพื่ออัปเดตเส้นทางที่สั้นที่สุดจากsหลังจากดูดซับโหนดใหม่ในขณะที่ในอัลกอริทึมของ Prim มี ไม่มีความจำเป็นเช่นนั้น


3

ความแตกต่างที่สำคัญระหว่างอัลกอริทึมพื้นฐานอยู่ที่เกณฑ์การเลือกขอบที่แตกต่างกัน โดยทั่วไปทั้งคู่ใช้ลำดับความสำคัญในการเลือกโหนดถัดไป แต่มีเกณฑ์ที่แตกต่างกันในการเลือกโหนดที่อยู่ติดกันของโหนดการประมวลผลปัจจุบัน: อัลกอริทึมของ Prim ต้องการให้โหนดที่อยู่ติดกันถัดไปต้องเก็บไว้ในคิวด้วยในขณะที่อัลกอริทึมของ Dijkstra ไม่:

def dijkstra(g, s):
    q <- make_priority_queue(VERTEX.distance)
    for each vertex v in g.vertex:
        v.distance <- infinite
        v.predecessor ~> nil
        q.add(v)
    s.distance <- 0
    while not q.is_empty:
        u <- q.extract_min()
        for each adjacent vertex v of u:
            ...

def prim(g, s):
    q <- make_priority_queue(VERTEX.distance)
    for each vertex v in g.vertex:
        v.distance <- infinite
        v.predecessor ~> nil
        q.add(v)
    s.distance <- 0
    while not q.is_empty:
        u <- q.extract_min()
        for each adjacent vertex v of u:
            if v in q and weight(u, v) < v.distance:// <-------selection--------
            ...

การคำนวณของvertex.distanceมีจุดที่แตกต่างกันสอง


3

อัลกอริทึมของ Dijkstra เป็นปัญหาพา ธ ที่สั้นที่สุดแหล่งเดียวระหว่างโหนด i และ j แต่อัลกอริทึมของ Prim เป็นปัญหาที่น้อยที่สุด อัลกอริทึมเหล่านี้ใช้แนวคิดการเขียนโปรแกรมที่ชื่อว่า 'greedy algorithm'

หากคุณตรวจสอบแนวคิดเหล่านี้โปรดไปที่

  1. บันทึกการบรรยายของ Greedy algorithm: http://jeffe.cs.illinois.edu/teaching/algorithms/notes/07-greedy.pdf
  2. ต้นไม้ขยายขั้นต่ำ: http://jeffe.cs.illinois.edu/teaching/algorithms/notes/20-mst.pdf
  3. เส้นทางที่สั้นที่สุดของแหล่งเดียว: http://jeffe.cs.illinois.edu/teaching/algorithms/notes/21-sssp.pdf

2

อัลกอริทึม Dijkstrasใช้เพื่อค้นหาเส้นทางที่สั้นที่สุดเท่านั้น

ในต้นไม้ Spanning ขั้นต่ำ (อัลกอริทึมของ Prim หรือ Kruskal)คุณจะได้รับ egdes ขั้นต่ำพร้อมค่าขอบขั้นต่ำ

ตัวอย่างเช่น: - พิจารณาสถานการณ์ที่คุณไม่ต้องการสร้างเครือข่ายขนาดใหญ่ซึ่งคุณจะต้องใช้สายจำนวนมากดังนั้นการนับสายเหล่านี้สามารถทำได้โดยใช้ขั้นตอนขั้นต่ำของ Spanning Tree (อัลกอริทึมของ Prim หรือ Kruskal) (เช่นจะ ให้จำนวนสายขั้นต่ำเพื่อสร้างการเชื่อมต่อเครือข่ายแบบใช้สายขนาดใหญ่โดยมีต้นทุนขั้นต่ำ)

ในขณะที่"Dijkstras algorithm"จะใช้เพื่อให้ได้เส้นทางที่สั้นที่สุดระหว่างสองโหนดในขณะที่เชื่อมต่อโหนดใด ๆ เข้าด้วยกัน


2

คำอธิบายที่ง่ายที่สุดคือใน Prims คุณไม่ได้ระบุโหนดเริ่มต้นแต่ใน dijsktra คุณ (ต้องมีโหนดเริ่มต้น) ต้องหาเส้นทางที่สั้นที่สุดจากโหนดที่กำหนดไปยังโหนดอื่น ๆ ทั้งหมด


0

@templatetypedef ได้กล่าวถึงความแตกต่างระหว่าง MST และเส้นทางที่สั้นที่สุด ฉันได้ครอบคลุมความแตกต่างของอัลกอริทึมในอีกคำตอบดังนั้นโดยแสดงให้เห็นว่าทั้งสองสามารถดำเนินการได้โดยใช้วิธีเดียวกันกับที่ทั่วไปจะใช้เวลาหนึ่งพารามิเตอร์เพิ่มเติมเป็น input: f(u,v)ฟังก์ชั่น ความแตกต่างระหว่างอัลกอริทึมของ Prim และ Dijkstra นั้นอยู่ที่f(u,v)คุณใช้


0

ในระดับโค้ดความแตกต่างอื่น ๆ คือ API

คุณเริ่มต้น Prim ด้วยจุดยอดต้นทางsเช่นPrim.new(s); sสามารถเป็นจุดยอดใดก็ได้และไม่ว่าsผลลัพธ์สุดท้ายซึ่งเป็นขอบของต้นไม้ที่มีระยะต่ำสุด (MST) จะเหมือนกัน ในการรับ MST edge เราเรียกเมธอดedges()ที่เราเรียกวิธี

คุณเริ่มต้น Dijkstra ด้วยจุดยอดต้นทางsนั่นคือDijkstra.new(s)คุณต้องการได้เส้นทาง / ระยะทางที่สั้นที่สุดไปยังจุดยอดอื่น ๆ ทั้งหมด ผลลัพธ์สุดท้ายซึ่งเป็นเส้นทาง / ระยะทางที่สั้นที่สุดจากsไปยังจุดยอดอื่น ๆ ทั้งหมด จะแตกต่างกันขึ้นอยู่กับs เพื่อให้ได้เส้นทางที่สั้นที่สุด / ระยะทางจากsจุดสุดยอดใด ๆวีเราเรียกวิธีการdistanceTo(v)และpathTo(v)ตามลำดับ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.