วิธีการใช้คิวที่มีสามกอง?


136

ฉันเจอคำถามนี้ในหนังสืออัลกอริทึม ( อัลกอริทึมรุ่นที่ 4โดย Robert Sedgewick และ Kevin Wayne)

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

ฉันรู้วิธีสร้างคิวด้วยสแต็ค 2 ชุด แต่ฉันไม่พบวิธีแก้ปัญหาด้วยสแต็ค 3 ตัว ความคิดใด ๆ

(โอ้และนี่ไม่ใช่การบ้าน :))


30
ผมคิดว่ามันเป็นหอคอยฮานอยตัวแปร
Gumbo

14
@ Jason: คำถามนั้นไม่ซ้ำกันเพราะจะขอเวลา O (1) ที่ถูกตัดจำหน่ายในขณะที่คำถามนี้ถามถึง O (1) กรณีที่เลวร้ายที่สุดสำหรับแต่ละการดำเนินการ โซลูชันสองสแต็กของ DuoSRX เป็นเวลา O (1) ที่ถูกตัดจำหน่ายต่อการดำเนินการ
ระหว่าง

15
ผู้เขียนแน่ใจว่าไม่ได้ล้อเล่นเมื่อเขาพูดว่า "คำเตือน: ความยากระดับสูง"
BoltClock

9
@Gumbo โชคไม่ดีที่ความซับซ้อนของเวลาของหอคอยแห่งฮานอยอยู่ใกล้แค่ไหน!
prusswan

12
หมายเหตุ: คำถามในข้อความได้รับการอัปเดตเป็นสิ่งนี้: ใช้คิวที่มีจำนวนสแต็คคงที่ [ไม่ใช่ "3"] เพื่อให้การดำเนินการแต่ละคิวใช้จำนวนการดำเนินการสแต็ก (กรณีแย่ที่สุด) คำเตือน: ความยากระดับสูง ( algs4.cs.princeton.edu/13stacks - ส่วน 1.3.43) ดูเหมือนว่าศ. Sedgewick ได้ยอมรับความท้าทายดั้งเดิม
Mark Peters

คำตอบ:


44

สรุป

  • อัลกอริทึม O (1) เป็นที่รู้จักกันใน 6 กอง
  • O (1) อัลกอริธึมเป็นที่รู้จักกันใน 3 กอง แต่การใช้การประเมินแบบขี้เกียจซึ่งในทางปฏิบัติสอดคล้องกับการมีโครงสร้างข้อมูลภายในเพิ่มเติมดังนั้นจึงไม่ได้เป็นการแก้ปัญหา
  • ผู้คนที่อยู่ใกล้กับ Sedgewick ได้ยืนยันว่าพวกเขาไม่ได้ตระหนักถึงวิธีการแก้ปัญหา 3 สแต็กภายในข้อ จำกัด ทั้งหมดของคำถามเดิม

รายละเอียด

มีการใช้งานสองตัวที่อยู่เบื้องหลังลิงก์นี้: http://www.eecs.usma.edu/webs/people/okasaki/jfp95/index.html

หนึ่งในนั้นคือ O (1) ที่มีสามกอง แต่จะใช้การประมวลผลที่ไม่ต่อเนื่องซึ่งในทางปฏิบัติจะสร้างโครงสร้างข้อมูลระดับกลางพิเศษ (การปิด)

อีกอันคือ O (1) แต่ใช้ SIX stack อย่างไรก็ตามมันจะทำงานโดยไม่มีการประมวลผลที่ขี้เกียจ

อัปเดต: กระดาษของ Okasaki มาที่นี่แล้ว: http://www.eecs.usma.edu/webs/people/okasaki/jfp95.psและดูเหมือนว่าเขาใช้เพียง 2 กองสำหรับรุ่น O (1) ที่มีการประเมินที่ขี้เกียจ ปัญหาคือว่ามันขึ้นอยู่กับการประเมินผลที่ขี้เกียจจริงๆ คำถามคือถ้ามันสามารถแปลเป็นอัลกอริทึม 3 กองโดยไม่ต้องประเมินขี้เกียจ

ปรับปรุง: อัลกอริทึมที่เกี่ยวข้องอีกอธิบายไว้ในกระดาษ "กองซ้อนกับ Deques" โดย Holger Petersen เผยแพร่ในการประชุมประจำปีครั้งที่ 7 ในคอมพิวเตอร์และ Combinatorics คุณสามารถค้นหาบทความจาก Google หนังสือ ตรวจสอบหน้า 225-226 แต่อัลกอริทึมนั้นไม่ใช่การจำลองแบบเรียลไทม์ แต่เป็นการจำลองเชิงเส้นเวลาของคิวสองครั้งในสามกอง

gusbro: "ตามที่ @Leonel พูดเมื่อหลายวันก่อนฉันคิดว่ามันน่าจะตรวจสอบกับศาสตราจารย์ Sedgewick ถ้าเขารู้วิธีแก้ปัญหาหรือมีข้อผิดพลาดบางอย่างฉันจึงเขียนถึงเขาฉันเพิ่งได้รับการตอบกลับ (แม้ว่าจะไม่ใช่ ตัวเอง แต่มาจากเพื่อนร่วมงานที่ Princeton) ดังนั้นฉันชอบที่จะแบ่งปันกับคุณทุกคนเขาบอกว่าเขารู้ว่าไม่มีอัลกอริธึมที่ใช้สามกองซ้อนและข้อ จำกัด อื่น ๆ ที่บังคับใช้ (เช่นไม่ใช้การประเมินสันหลังยาว) 6 กองในขณะที่เรารู้คำตอบที่นี่แล้วดังนั้นฉันเดาว่าคำถามยังคงเปิดให้ค้นหาอัลกอริทึม (หรือพิสูจน์ไม่พบ)


ฉันเพิ่งบินผ่านเอกสารและ programms ในลิงค์ของคุณ แต่ถ้าฉันเห็นถูกต้องพวกเขาไม่ได้ใช้สแต็คพวกเขาใช้รายการเป็นประเภทพื้นฐาน และโดยเฉพาะ ในรายการเหล่านี้ถูกสร้างขึ้นด้วยส่วนหัวและส่วนที่เหลือดังนั้นจึงดูคล้ายกับโซลูชันของฉัน (และฉันคิดว่าไม่ถูกต้อง)
flolo

1
สวัสดีการใช้งานเป็นภาษาที่ใช้งานได้ซึ่งรายการนั้นสอดคล้องกับสแต็คตราบใดที่ไม่มีการใช้พอยน์เตอร์พอยน์เตอร์ เวอร์ชันหกสแต็กสามารถนำไปใช้ได้จริงโดยใช้หกกอง "ธรรมดา" ปัญหาของรุ่นสแต็คสอง / สามคือการใช้โครงสร้างข้อมูลที่ซ่อนอยู่ (การปิด)
Antti Huima

คุณแน่ใจหรือว่าโซลูชันหกสแต็กไม่แชร์พอยน์เตอร์? ในrotateจะมีลักษณะเช่นเดียวกับfrontรายการที่ได้รับมอบหมายให้ทั้งสองoldfrontและfและสิ่งเหล่านี้มีการแก้ไขแล้วแยกกัน
ระหว่าง

14
วัสดุต้นฉบับที่algs4.cs.princeton.edu/13stacksมีการเปลี่ยนแปลง: 43. ใช้คิวที่มีจำนวนคงที่ [ไม่ใช่ "3"] สแต็คเพื่อให้แต่ละการดำเนินการคิวใช้จำนวนคงที่ (กรณีที่แย่ที่สุด) การดำเนินงาน คำเตือน: ความยากระดับสูง ชื่อของความท้าทายยังคงระบุว่า "Queue with สามกอง" แต่ :-)
Mark Peters

3
@AnttiHuima ลิงก์หกกองตายไปแล้วคุณรู้ไหมว่ามันมีอยู่ที่ไหนซักแห่ง?
Quentin Pradet

12

ตกลงนี่ยากจริงๆและวิธีแก้ปัญหาเดียวที่ฉันนึกขึ้นได้คือจำปัญหา Kirks ให้กับการทดสอบ Kobayashi Maru (โกงอย่างใด): ความคิดคือเราใช้สแต็คสแต็ก (และใช้สิ่งนี้เพื่อสร้างแบบจำลองรายการ ) ฉันเรียกการดำเนินการ en / dequeue และกดและป๊อปอัพแล้วเราจะได้รับ:

queue.new() : Stack1 = Stack.new(<Stack>);  
              Stack2 = Stack1;  

enqueue(element): Stack3 = Stack.new(<TypeOf(element)>); 
                  Stack3.push(element); 
                  Stack2.push(Stack3);
                  Stack3 = Stack.new(<Stack>);
                  Stack2.push(Stack3);
                  Stack2 = Stack3;                       

dequeue(): Stack3 = Stack1.pop(); 
           Stack1 = Stack1.pop();
           dequeue() = Stack1.pop()
           Stack1 = Stack3;

isEmtpy(): Stack1.isEmpty();

(StackX = StackY ไม่มีการคัดลอกเนื้อหาเพียงแค่สำเนาของการอ้างอิงมันเพียงเพื่ออธิบายได้ง่ายคุณยังสามารถใช้อาร์เรย์ 3 กองและเข้าถึงได้ผ่านดัชนีคุณจะเปลี่ยนค่าของตัวแปรดัชนี ) ทุกอย่างอยู่ใน O (1) ในข้อกำหนดการใช้งานสแต็ก

และใช่ฉันรู้ว่ามันโต้แย้งได้เพราะเรามีสแต็คมากกว่า 3 กอง แต่บางทีมันอาจทำให้คุณมีความคิดที่ดี

แก้ไข: ตัวอย่างคำอธิบาย:

 | | | |3| | | |
 | | | |_| | | |
 | | |_____| | |
 | |         | |
 | |   |2|   | |
 | |   |_|   | |
 | |_________| |
 |             |
 |     |1|     |
 |     |_|     |
 |_____________|

ฉันลอง ASCII-art เล็ก ๆ เพื่อแสดง Stack1

ทุกองค์ประกอบถูกห่อในสแต็กองค์ประกอบเดียว (ดังนั้นเราจึงมีสแต็ก typesafe เท่านั้น)

คุณเห็นว่าจะลบเราก่อนปรากฏองค์ประกอบแรก (สแต็คที่มีองค์ประกอบที่นี่ 1 และ 2) จากนั้นป๊อปองค์ประกอบถัดไปและแกะที่ 1 หลังจากนั้นเราบอกว่าสแต็กที่ป๊อปอัพแรกคือตอนนี้สแต็ก 1 ใหม่ของเรา เพื่อพูดคุยเล็ก ๆ น้อย ๆ ทำงานได้มากขึ้น - เหล่านี้เป็นรายการที่ดำเนินการโดยสแต็คของ 2 องค์ประกอบที่องค์ประกอบด้านบน ist CDRและ / แรกด้านล่างองค์ประกอบด้านบนเป็นรถ อีกสองคนกำลังช่วยสแต็ค

Esp หากินคือการแทรกเนื่องจากคุณจะต้องดำดิ่งลึกลงไปในกองซ้อนเพื่อเพิ่มองค์ประกอบอื่น นั่นเป็นเหตุผลที่ Stack2 อยู่ที่นั่น Stack2 เป็นกองซ้อนด้านในสุดเสมอ การเพิ่มนั้นเพียงแค่ผลักองค์ประกอบเข้ามาแล้วผลักดันให้กับ Stack2 ใหม่ (และนั่นคือสาเหตุที่เราไม่ได้รับอนุญาตให้สัมผัส Stack2 ในการดำเนินการตามขั้นตอน)


คุณสนใจที่จะอธิบายว่ามันทำงานอย่างไร อาจติดตามการกด 'A', 'B', 'C', 'D' แล้วก็โผล่ 4 ครั้ง?
MAK

1
@Iceman: ไม่มี Stack2 ที่ถูกต้อง มันจะไม่สูญหายไปเพราะ Stack มักอ้างถึง stack ด้านในใน Stack1 ดังนั้นพวกเขาจึงยังคงอยู่โดยนัยใน Stack1
flolo

3
ฉันเห็นด้วยว่ามันเป็นการโกง :-) นั่นไม่ใช่สแต็ค 3 อันมันคือ 3 การอ้างอิงสแต็ก แต่อ่านสนุก
Mark Peters

1
มันเป็นรูปแบบที่ฉลาด แต่ถ้าฉันเข้าใจอย่างถูกต้องมันจะจบลงด้วยการต้องการสแต็ค n เมื่อมีองค์ประกอบที่ผลักเข้าไปในคิว คำถามจะถามว่ามี 3 กองอย่างแน่นอน
MAK

2
@MAK: ฉันรู้ว่านั่นคือเหตุผลที่ระบุไว้อย่างชัดเจนว่ามันโกง (ฉันใช้ชื่อเสียงในความโปรดปรานเพราะฉันก็อยากรู้วิธีแก้ปัญหาที่แท้จริง) แต่อย่างน้อยก็สามารถตอบความคิดเห็นปรัสเซียได้: จำนวนของสแต็คนั้นสำคัญเพราะโซลูชันของฉันนั้นใช้ได้จริงเมื่อคุณสามารถใช้งานได้มากเท่าที่คุณต้องการ
flolo

4

ฉันจะพยายามพิสูจน์เพื่อแสดงว่าไม่สามารถทำได้


สมมติว่ามีคิว Q ที่จำลองโดย 3 กอง A, B และ C

ยืนยัน

  • ASRT0: = นอกจากนี้สมมติว่า Q สามารถจำลองการทำงาน {คิว, dequeue} ใน O (1) ซึ่งหมายความว่ามีลำดับเฉพาะของการพุช / ป๊อปที่ระบุสำหรับการดำเนินการคิว / การแยกทั้งหมดที่จะจำลอง

  • โดยไม่มีการสูญเสียความคิดทั่วไปการสันนิษฐานว่าการดำเนินการคิวนั้นถูกกำหนด

ปล่อยให้อิลิเมนต์ที่ถูกจัดคิวเข้าคิวเป็นหมายเลข 1, 2, ... ตามลำดับคิวโดยอิลิเมนต์แรกที่ถูกจัดคิวเป็นคิวจะถูกกำหนดเป็น 1, อันที่สองเป็น 2 และอื่น ๆ

กำหนด

  • Q(0) := สถานะของ Q เมื่อมี 0 องค์ประกอบใน Q (และทำให้ 0 องค์ประกอบใน A, B และ C)
  • Q(1) := สถานะของ Q (และ A, B และ C) หลังจากเปิด 1 คิว Q(0)
  • Q(n) := สถานะของ Q (และ A, B และ C) หลังจากการดำเนินการ n คิวบน Q(0)

กำหนด

  • |Q(n)| :=จำนวนองค์ประกอบในQ(n)(ดังนั้น|Q(n)| = n)
  • A(n) := สถานะของสแต็ก A เมื่อสถานะของ Q คือ Q(n)
  • |A(n)| := จำนวนองค์ประกอบใน A(n)

และคำจำกัดความที่คล้ายกันสำหรับสแตก B และ C

นิด ๆ ,

|Q(n)| = |A(n)| + |B(n)| + |C(n)|

---

|Q(n)| เห็นได้ชัดว่าไม่มีข้อ จำกัด ใน n

ดังนั้นอย่างน้อยหนึ่ง|A(n)|, |B(n)|หรือ|C(n)|เป็นมากมายบน n

WLOG1สมมติว่า stack A ไม่มีขอบเขตและสแต็ก B และ C ถูกผูกไว้

กำหนด * B_u :=ขอบเขตบนของ B * C_u :=ขอบเขตบนของ C *K := B_u + C_u + 1

WLOG2, สำหรับ n เช่นที่|A(n)| > Kเลือกองค์ประกอบ K Q(n)จาก สมมติว่า 1 ขององค์ประกอบเหล่านั้นมีอยู่A(n + x)สำหรับทุกคนx >= 0นั่นคือองค์ประกอบนั้นจะอยู่ในสแต็ก A เสมอไม่ว่าจะดำเนินการคิวจำนวนเท่าใด

  • X := องค์ประกอบนั้น

จากนั้นเราสามารถกำหนด

  • Abv(n) :=จำนวนรายการในสแต็กA(n)ที่สูงกว่า X
  • Blo(n) :=จำนวนองค์ประกอบในสแต็กA(n)ที่ต่ำกว่า X

    | A (n) | = Abv (n) + Blo (n)

ASRT1 :=จำนวนของ pops ที่ต้องใช้ในการ dequeue X Q(n)เป็นอย่างน้อยAbv(n)

จะต้องมีขอบเขตจาก ( ASRT0) และ ( ASRT1)ASRT2 := Abv(n)

หากAbv(n)ไม่ถูก จำกัด ดังนั้นหากต้องการ 20 dequeue เพื่อ dequeue X จากQ(n)จะต้องAbv(n)/20ปรากฏอย่างน้อย ซึ่งมีมากมาย 20 สามารถคงที่ใด ๆ

ดังนั้น,

ASRT3 := Blo(n) = |A(n)| - Abv(n)

จะต้องไม่ถูก จำกัด


WLOG3เราสามารถเลือกองค์ประกอบ K จากด้านล่างของA(n)และหนึ่งในนั้นคือA(n + x)สำหรับทั้งหมดx >= 0

X(n) := องค์ประกอบนั้นสำหรับ n ใด ๆ ก็ตาม

ASRT4 := Abv(n) >= |A(n)| - K

เมื่อใดก็ตามที่องค์ประกอบเข้าคิวQ(n)...

WLOG4สมมติว่า B และ C เต็มไปด้วยขอบเขตแล้ว สมมติว่าถึงขอบเขตบนขององค์ประกอบด้านบนX(n)แล้ว จากนั้นองค์ประกอบใหม่จะเข้าสู่ A

WLOG5X(n)สมมติว่าเป็นผลให้องค์ประกอบใหม่จะต้องป้อนด้านล่าง

ASRT5 := จำนวนของป็อปที่ต้องใช้เพื่อวางองค์ประกอบด้านล่าง X(n) >= Abv(X(n))

จาก(ASRT4), Abv(n)เป็นมากมายบน n

ดังนั้นจำนวนของ pops ที่จำเป็นต้องใส่องค์ประกอบด้านล่างX(n)จึงไม่ได้ จำกัด


ตรงกันข้ามนี้ASRT1จึงเป็นไปไม่ได้ที่จะจำลองO(1)คิวมี 3 กอง


กล่าวคือ

อย่างน้อย 1 กองจะต้องไม่ถูก จำกัด

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

อย่างไรก็ตามหากจำนวนองค์ประกอบด้านบนถูก จำกัด ขอบเขตก็จะถึงขีด จำกัด ในบางจุดองค์ประกอบใหม่จะต้องป้อนด้านล่าง

เนื่องจากเราสามารถเลือกองค์ประกอบเก่าจากหนึ่งในองค์ประกอบไม่กี่แห่งที่น้อยที่สุดของสแต็กนั้นจึงอาจมีองค์ประกอบที่ไม่ จำกัด จำนวนอยู่ด้านบน (ขึ้นอยู่กับขนาดที่ไม่ จำกัด ของสแต็กที่ไม่ถูก จำกัด )

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

และทำให้เกิดความขัดแย้ง


มีข้อความ WLOG 5 ข้อความ ในบางแง่พวกเขาสามารถเข้าใจได้โดยสัญชาตญาณว่าเป็นจริง (แต่เนื่องจากพวกเขาเป็น 5 มันอาจใช้เวลาสักครู่) การพิสูจน์อย่างเป็นทางการว่าไม่มีการสูญหายใด ๆ เกิดขึ้นได้ แต่มีความยาวมาก พวกเขากำลังละเว้น

ฉันยอมรับว่าการละเลยดังกล่าวอาจทำให้คำสั่ง WLOG เป็นปัญหา ด้วยความหวาดระแวงของโปรแกรมเมอร์สำหรับข้อบกพร่องโปรดตรวจสอบคำสั่ง WLOG หากคุณต้องการ

กองซ้อนที่สามนั้นไม่เกี่ยวข้องด้วย สิ่งที่สำคัญคือมีชุดของกองที่ถูกล้อมรอบและชุดของกองที่ไม่มีขอบเขต ขั้นต่ำที่จำเป็นสำหรับตัวอย่างคือ 2 กอง จำนวนสแต็คต้องแน่นอนแน่นอน

ท้ายที่สุดถ้าฉันพูดถูกว่าไม่มีข้อพิสูจน์ก็ควรมีหลักฐานทางอุปนัยที่ง่ายกว่า อาจขึ้นอยู่กับสิ่งที่เกิดขึ้นหลังจากทุกคิว (ติดตามว่ามันมีผลต่อกรณี dequeue ที่เลวร้ายที่สุดที่กำหนดชุดขององค์ประกอบทั้งหมดในคิว)


2
ฉันคิดว่าข้อพิสูจน์นั้นใช้ได้กับสมมติฐานเหล่านั้น - แต่ฉันไม่แน่ใจว่าสแต็กทั้งหมดต้องว่างเปล่าเพื่อให้คิวว่างเปล่าหรือว่าผลรวมของขนาดของสแต็กต้องเท่ากับขนาดของคิว
Mikeb

3
"WLOG1 สมมติว่าสแตก A ไม่ได้ถูก จำกัด และสแต็ก B และ C จะถูก จำกัด " คุณไม่สามารถสรุปได้ว่าสแต็คบางตัวถูกล้อมรอบเนื่องจากจะทำให้มันไร้ค่า (มันจะเหมือนกับ O (1) ที่เก็บข้อมูลเพิ่มเติม)
ระหว่าง

3
บางครั้งสิ่งเล็ก ๆ น้อย ๆ นั้นไม่สำคัญ: | Q | = | A | + | B | + | C | ถูกต้องเท่านั้นถ้าคุณคิดว่าทุกรายการใน Q คุณเพิ่มอันที่แน่นอนลงใน A, B หรือ C แต่มันอาจเป็นไปได้ว่า theer เป็นอัลกอริทึมบางอย่างที่เพิ่มองค์ประกอบสองครั้งเป็นสองเท่าหรือทั้งสามอย่างเสมอกัน และถ้ามันทำงานในลักษณะนี้คุณ WLOG1 จะไม่ถืออีกต่อไป (เช่นลองนึกภาพสำเนาของ A (ไม่ใช่ว่ามันสมเหตุสมผล แต่อาจมีอัลกอริทึมที่มีลำดับอื่นหรืออะไรก็ตาม ... )
flolo

@flolo และ @mikeb: คุณทั้งคู่พูดถูก | Q (n) | ควรกำหนดเป็น | A (n) | + | B (n) | + | C (n) | จากนั้น | Q (n) | > = n จากนั้นหลักฐานจะทำงานร่วมกับ n และโปรดทราบว่าตราบใดที่ | Q (n) | ขนาดใหญ่ข้อสรุปใช้
Dingfeng Quek

@interjay: คุณสามารถมี 3 กองที่ไม่มีขอบเขตและไม่มีกองที่ถูกผูกไว้ จากนั้นแทนที่จะเป็น "B_u + C_u + 1" การพิสูจน์สามารถใช้ "1" ได้ โดยพื้นฐานแล้วนิพจน์แสดงถึง "ผลรวมของขอบเขตบนในสแต็กที่ถูกล้อมรอบ + 1" ดังนั้นจำนวนสแต็กที่ถูกล้อมรอบจะไม่สำคัญ
Dingfeng Quek

3

หมายเหตุ: นี่หมายถึงการแสดงความคิดเห็นต่อการใช้งานของคิวแบบเรียลไทม์ (กรณีที่แย่ที่สุดในเวลาคงที่) ที่มีรายการที่เชื่อมโยงโดยลำพัง ฉันไม่สามารถเพิ่มความคิดเห็นเนื่องจากชื่อเสียง แต่มันจะดีถ้ามีใครสามารถเปลี่ยนความคิดเห็นนี้ต่อท้ายคำตอบโดย antti.huima จากนั้นอีกครั้งมันค่อนข้างยาวสำหรับความคิดเห็น

@ antti.huima: รายการที่เชื่อมโยงไม่เหมือนกับสแต็ก

  • s1 = (1 2 3 4) --- รายการที่เชื่อมโยงกับ 4 โหนดแต่ละรายการชี้ไปทางขวาและถือค่า 1, 2, 3 และ 4

  • s2 = popped (s1) --- s2 คือตอนนี้ (2 3 4)

ณ จุดนี้ s2 เทียบเท่ากับ popped (s1) ซึ่งทำหน้าที่เหมือนกองซ้อน อย่างไรก็ตาม s1 ยังคงมีอยู่สำหรับการอ้างอิง!

  • s3 = popped (popped (s1)) --- s3 คือ (3 4)

เรายังสามารถมองเข้าไปที่ s1 เพื่อรับ 1 ในขณะที่การใช้งานสแต็กที่เหมาะสมองค์ประกอบ 1 หายไปจาก s1!

สิ่งนี้หมายความว่า?

  • s1 คือการอ้างอิงถึงด้านบนของสแต็ก
  • s2 เป็นการอ้างอิงถึงองค์ประกอบที่สองของสแต็ก
  • s3 คือการอ้างอิงถึงสาม ...

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

จากสิ่งที่ฉันเห็นในเอกสาร / รหัสอัลกอริทึมทั้งหมดใช้ประโยชน์จากคุณสมบัตินี้ของรายการที่ลิงก์เพื่อเก็บการอ้างอิง

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


ความเกียจคร้านยังสามารถจำลองการทำงานของตัวชี้ในลักษณะที่คล้ายกัน


การใช้ลิสต์รายการแก้ปัญหาที่แตกต่าง กลยุทธ์นี้สามารถใช้เพื่อสร้างคิวเรียลไทม์ใน Lisp (หรืออย่างน้อย Lisps ที่ยืนยันในการสร้างทุกสิ่งจากรายการที่ลิงก์): อ้างอิงถึง "การดำเนินการคิวเรียลไทม์ใน Pure Lisp" (เชื่อมโยงผ่านลิงก์ของ antti.huima) นอกจากนี้ยังเป็นวิธีที่ดีในการออกแบบรายการที่ไม่เปลี่ยนรูปด้วย O (1) เวลาดำเนินการและโครงสร้างที่ใช้ร่วมกัน (ไม่เปลี่ยนรูป)


1
ฉันไม่สามารถพูดกับอัลกอริทึมอื่น ๆ ในคำตอบของ antti ได้ แต่โซลูชันหกเวลาคงที่ ( eecs.usma.edu/webs/people/okasaki/jfp95/queue.hm.sml ) ไม่ได้ใช้คุณสมบัติของรายการนี้ เนื่องจากฉันได้ติดตั้งใหม่ใน Java โดยใช้java.util.Stackวัตถุ สถานที่เดียวที่ใช้คุณลักษณะนี้คือการปรับให้เหมาะสมซึ่งอนุญาตให้สแต็กที่ไม่เปลี่ยนรูปจะ "ซ้ำซ้อน" ในเวลาคงที่ซึ่งสแต็ก Java พื้นฐานไม่สามารถทำได้ (แต่สามารถนำมาใช้ใน Java) เนื่องจากเป็นโครงสร้างที่ไม่แน่นอน
Welbog

หากเป็นการเพิ่มประสิทธิภาพที่ไม่ลดความซับซ้อนของการคำนวณก็ไม่ควรส่งผลกระทบต่อข้อสรุป ดีใจที่มีทางออกในตอนนี้เพื่อตรวจสอบ: แต่ฉันไม่ชอบอ่าน SML ต้องการแบ่งปันรหัส java ของคุณหรือไม่ (:
Dingfeng Quek

มันไม่ใช่ทางออกสุดท้ายเพราะใช้หกกองแทนที่จะเป็นสามอย่างน่าเสียดาย แต่ก็อาจเป็นไปได้ที่จะพิสูจน์ว่าหกสแต็คเป็นวิธีการแก้ปัญหาน้อยที่สุด ...
Welbog

@Welbog! คุณสามารถแบ่งปันการใช้งาน 6 สแต็กได้หรือไม่ :) มันจะเจ๋งดีที่ได้เห็น :)
Antti Huima

1

คุณสามารถทำได้ในเวลาคงที่ตัดจำหน่ายด้วยสองกอง:

------------- --------------
            | |
------------- --------------

การเพิ่มO(1)และลบคือO(1)ถ้าด้านที่คุณต้องการใช้ไม่ว่างเปล่าและเป็นO(n)อย่างอื่น (แยกสแต็กอื่นเป็นสอง)

เคล็ดลับคือการเห็นว่าการO(n)ดำเนินการจะต้องทำทุกO(n)ครั้ง (ถ้าคุณแยกเช่นในครึ่ง) O(1)+O(n)/O(n) = O(1)ดังนั้นเวลาเฉลี่ยสำหรับการดำเนินงานคือ

ในขณะที่สิ่งนี้อาจดูเหมือนเป็นปัญหาหากคุณใช้ภาษาที่จำเป็นกับสแต็กตามอาเรย์ (เร็วที่สุด) คุณจะมีเวลาคงที่เพียงตัดจำหน่ายเท่านั้น


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