เวกเตอร์กับรายการใน STL


238

ฉันสังเกตเห็นใน Effective STL

vector เป็นชนิดของลำดับที่ควรใช้เป็นค่าเริ่มต้น

มันหมายความว่าอะไร? ดูเหมือนว่าการเพิกเฉยต่อประสิทธิภาพvectorสามารถทำอะไรก็ได้

ใครช่วยเสนอสถานการณ์ที่vectorไม่มีตัวเลือกที่เป็นไปได้ แต่listต้องใช้?


6
แม้ว่ามันจะไม่ใช่สิ่งที่คุณถาม แต่มันก็คุ้มค่าที่จะชี้ให้เห็นว่าการเริ่มต้นกับเวกเตอร์นั้นหมายความว่าคุณสามารถโต้ตอบกับโค้ดเก่า ๆ ไลบรารี C หรือไลบรารีที่ไม่ใช่เท็มเพลตได้ง่ายกว่าเนื่องจากเวกเตอร์ และขนาด

18
Bjarne Strostrup ทำการทดสอบโดยที่เขาสร้างตัวเลขสุ่มแล้วเพิ่มลงในรายการและเวกเตอร์ตามลำดับ การแทรกถูกสร้างขึ้นเพื่อให้รายการ / เวกเตอร์ถูกสั่งตลอดเวลา แม้ว่าโดยทั่วไปจะเป็น "โดเมนรายการ" เวกเตอร์มีประสิทธิภาพสูงกว่ารายการด้วยระยะขอบขนาดใหญ่ สาเหตุที่หน่วยความจำ acces ช้าและแคชทำงานได้ดีขึ้นสำหรับข้อมูลตามลำดับ มันมีอยู่ในคำปราศรัยของเขาจาก "GoingNative 2012"
หลีกเลี่ยง


1
หากคุณต้องการดูคำปราศรัยโดย Bjarne Stroustrup ที่ @evading กล่าวถึงฉันพบที่นี่: youtu.be/OB-bdWKwXsU?t=2672
brain56

คำตอบ:


98

สถานการณ์ที่คุณต้องการแทรกรายการจำนวนมากลงในที่ใดก็ได้ แต่จุดสิ้นสุดของลำดับซ้ำ ๆ

ตรวจสอบการรับประกันความซับซ้อนของคอนเทนเนอร์แต่ละประเภท:

การรับประกันความซับซ้อนของคอนเทนเนอร์มาตรฐานคืออะไร?


2
การแทรกองค์ประกอบในตอนท้ายก็นับด้วยเช่นกันเพราะสามารถนำไปสู่การจัดสรรหน่วยความจำและค่าใช้จ่ายในการคัดลอกองค์ประกอบ และการแทรก elenets ที่จุดเริ่มต้นของเวกเตอร์เป็นไปไม่listได้มีpush_front
Notinlist

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

16
@Notinlist - "ต่อไปนี้เป็นไปไม่ได้" สำหรับคุณหรือไม่ v.insert (v.begin (), i)
Manuel

5
@Notinlist - ฉันเห็นด้วยกับคุณก็แค่ว่าฉันไม่ต้องการให้ OP คิดว่าอินเทอร์เฟซไม่ได้มีในกรณีที่เราต้องการยิงตัวเองด้วยเท้า (การแสดง)
Manuel

16
Bjarne Strostrup ทำการทดสอบโดยที่เขาสร้างตัวเลขสุ่มแล้วเพิ่มลงในรายการและเวกเตอร์ตามลำดับ การแทรกถูกสร้างขึ้นเพื่อให้รายการ / เวกเตอร์ถูกสั่งตลอดเวลา แม้ว่าโดยทั่วไปจะเป็น "โดเมนรายการ" เวกเตอร์มีประสิทธิภาพสูงกว่ารายการด้วยระยะขอบขนาดใหญ่ สาเหตุที่หน่วยความจำ acces ช้าและแคชทำงานได้ดีขึ้นสำหรับข้อมูลตามลำดับ มันมีอยู่ในคำปราศรัยของเขาจาก "GoingNative 2012"
หลีกเลี่ยง

409

เวกเตอร์:

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

รายการ:

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

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


2
นอกจากนี้การจัดสรรจากร้านค้าฟรีไม่ฟรี :) การเพิ่มไอเท็มใหม่ให้กับเวกเตอร์เป็นการดำเนินการจัดสรรร้านค้าฟรี O (log n) แต่คุณสามารถโทรหาreserve()เพื่อลดรายการนั้นเป็น O (1) การเพิ่มรายการใหม่ลงในรายการ (เช่นไม่ใช่การต่อข้อมูล) ดำเนินการจัดสรรร้านค้าฟรี O (n)
bk1e

7
ข้อควรพิจารณาอีกประการหนึ่งคือเพิ่มlistหน่วยความจำเมื่อคุณลบองค์ประกอบ แต่vectorไม่ A vectorไม่ลดกำลังการผลิตเมื่อคุณลดขนาดยกเว้นว่าคุณใช้swap()เคล็ดลับ
bk1e

@ bk1e: ฉันต้องการทราบเคล็ดลับของคุณในการสงวน () และแลกเปลี่ยน () :)
Dzung Nguyen

2
@nXqd: หากคุณต้องการเพิ่มองค์ประกอบ N ให้กับเวกเตอร์ให้โทร v.reserve (v.size () + N) เพื่อให้ดำเนินการปันส่วนร้านค้าฟรีเพียงแห่งเดียว เคล็ดลับ swap () อยู่ที่นี่: stackoverflow.com/questions/253157/how-to-downsize-stdvector
bk1e

1
@simplename ไม่สิ่งที่กล่าวถูกต้อง เวกเตอร์จัดสรรพื้นที่เพิ่มเติมนอกเหนือจากพื้นที่สำหรับองค์ประกอบในปัจจุบันเวกเตอร์; ความสามารถพิเศษนั้นจะใช้ในการขยายเวกเตอร์เพื่อให้การเติบโตนั้นถูกตัดจำหน่าย O (1)
Jonathan M Davis

35

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


32

คำตอบส่วนใหญ่ที่นี่พลาดรายละเอียดที่สำคัญอย่างหนึ่ง: เพื่ออะไร

คุณต้องการเก็บไว้ในที่เก็บอะไร

หากเป็นคอลเล็กชันints ดังนั้นstd::listจะสูญเสียในทุกสถานการณ์โดยไม่คำนึงว่าคุณสามารถจัดสรรใหม่ได้หรือไม่คุณจะลบออกจากด้านหน้าเท่านั้นเป็นต้นรายการจะช้ากว่าในการสำรวจการแทรกทุกครั้งจะทำให้คุณต้องเสียค่าใช้จ่าย มันจะยากมากที่จะเตรียมความพร้อมตัวอย่างที่เต้นlist<int> vector<int>และยิ่งกว่านั้นdeque<int>อาจจะดีกว่าหรือใกล้กว่าไม่ใช่แค่เพียงการใช้รายการซึ่งจะมีค่าใช้จ่ายในหน่วยความจำมากขึ้น

อย่างไรก็ตามหากคุณกำลังจัดการกับข้อมูลขนาดใหญ่น่าเกลียด - และไม่กี่ของพวกเขา - คุณไม่ต้องการ overallocate เมื่อแทรกและคัดลอกเนื่องจากการจัดสรรใหม่จะเป็นภัยพิบัติ - แล้วคุณอาจจะดีกว่าด้วยกว่าlist<UglyBlob>vector<UglyBlob>

ยังถ้าคุณเปลี่ยนเป็นvector<UglyBlob*>หรือแม้กระทั่งvector<shared_ptr<UglyBlob> >อีกครั้ง - รายการจะล้าหลัง

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


1
หนึ่งสะท้อนมากขึ้นซึ่งผมมีเมื่ออ่าน "STL ที่มีประสิทธิภาพ" โดยเมเยอร์ส: ที่พักที่แปลกประหลาดของlist<T>ความเป็นไปได้ที่จะspliceอยู่ในO (1) หากคุณต้องการการต่อเวลาคงที่รายการอาจเป็นโครงสร้างของทางเลือก;)
Tomasz Gandor

+1 - ไม่จำเป็นต้องเป็นUglyBlob- แม้แต่วัตถุที่มีสมาชิกสตริงเพียงไม่กี่คนก็อาจมีราคาแพงในการคัดลอกได้อย่างง่ายดายดังนั้นการจัดสรรใหม่จะมีค่าใช้จ่าย นอกจากนี้: อย่าละเลยช่องว่างเหนือศีรษะการเติบโตแบบเอ็กซ์โปเนนเชียลของvectorวัตถุโฮลดิ้งที่มีขนาดไม่กี่สิบไบต์อาจทำให้เกิด (หากคุณไม่สามารถreserveล่วงหน้าได้)
Martin Ba

สำหรับvector<smart_ptr<Large>>vs. list<Large>- ฉันว่าถ้าคุณต้องการเข้าถึงองค์ประกอบแบบสุ่มvectorความสมเหตุสมผล หากคุณไม่ต้องการเข้าถึงแบบสุ่มlistดูเหมือนจะง่ายกว่าและควรทำงานอย่างเท่าเทียมกัน
Martin Ba

19

ความสามารถพิเศษอย่างหนึ่งของ std :: list คือการประกบกัน (การเชื่อมโยงหรือย้ายส่วนหนึ่งของหรือรายการทั้งหมดลงในรายการอื่น)

หรือบางทีถ้าเนื้อหาของคุณมีราคาแพงมากในการคัดลอก ในกรณีเช่นนี้อาจมีราคาถูกกว่าเช่นเรียงลำดับรายการด้วยรายการ

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

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


1
+1 การประกบถูกมองข้ามไป แต่น่าเสียดายที่ไม่ใช่เวลาคงที่ตามที่ต้องการ : (((เป็นไปไม่ได้ถ้ารายการ :: ขนาดเป็นค่าคงที่)

ฉันค่อนข้างแน่ใจว่ารายการ :: ขนาดเป็นเส้นตรง (อนุญาตให้) ด้วยเหตุผลอย่างนี้
UncleBens

1
@Roger: list::sizeไม่จำเป็นต้องเป็นเวลาคงที่ ดูstackoverflow.com/questions/228908/is-listsize-really-onและgcc.gnu.org/ml/libstdc++/2005-11/msg00219.html
Potatoswatter

@Potatoswatter: มาตรฐานนั้นคลุมเครือและดังนั้นคุณไม่สามารถพึ่งพาการใช้งาน "ตามมาตรฐาน" ทำให้มีปัญหามากขึ้น คุณต้องหลีกเลี่ยง stdlib ที่จะได้รับการรับประกันแบบพกพาและเชื่อถือได้

@Roger: ใช่น่าเสียดาย โครงการปัจจุบันของฉันต้องอาศัยการดำเนินการรอยต่ออย่างมากและโครงสร้างนั้นเกือบจะเป็นแนวตรง C. น่าเสียดายยิ่งกว่านั้นในลำดับ N3000 spliceระหว่างรายการต่าง ๆ ถูกระบุว่ามีความซับซ้อนเชิงเส้นและsizeคงที่โดยเฉพาะ ดังนั้นเพื่อรองรับสามเณรที่ทำซ้ำในsizeหรืออะไรก็ตามคลาสอัลกอริธึมทั้งหมดพ้นจาก STL หรือช่วงเวลาคอนเทนเนอร์ "ที่สอดคล้อง"
Potatoswatter

13

นักเรียนในชั้นเรียนของฉันดูเหมือนไม่สามารถอธิบายให้ฉันได้เมื่อมันมีประสิทธิภาพมากกว่าในการใช้เวกเตอร์ แต่พวกเขาดูมีความสุขมากเมื่อแนะนำฉันให้ใช้รายการ

นี่คือวิธีที่ฉันเข้าใจ

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

เวกเตอร์ : เมื่อใช้เวกเตอร์หน่วยความจำจะถูกจัดระเบียบมากขึ้นเช่นอาร์เรย์ปกติ: รายการ n-th แต่ละรายการจะถูกจัดเก็บหลังรายการ (n-1) th และก่อน (n + 1) รายการ th ทำไมดีกว่ารายการ? เพราะอนุญาตให้เข้าถึงแบบสุ่มได้อย่างรวดเร็ว นี่คือวิธี: หากคุณทราบขนาดของรายการในเวกเตอร์และหากมีขนาดต่อเนื่องกันในหน่วยความจำคุณสามารถคาดการณ์ได้อย่างง่ายดายว่ารายการที่ n นั้นคืออะไร คุณไม่จำเป็นต้องเรียกดูรายการทั้งหมดของรายการเพื่ออ่านสิ่งที่คุณต้องการด้วยเวกเตอร์คุณสามารถอ่านได้โดยตรงด้วยรายการที่คุณไม่สามารถทำได้ ในทางตรงกันข้ามปรับเปลี่ยนอาร์เรย์เวกเตอร์หรือเปลี่ยนค่าช้ากว่ามาก

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

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


"แก้ไขอาร์เรย์เวกเตอร์หรือเปลี่ยนค่าช้ากว่ามาก" - ตามที่อ่านนี่ดูเหมือนจะขัดแย้งกับสิ่งที่คุณพูดก่อนหน้านี้เกี่ยวกับเวกเตอร์ที่มีใจโอนเอียงเพื่อประสิทธิภาพที่ดีเนื่องจากธรรมชาติในระดับต่ำและต่อเนื่องกัน คุณหมายถึงว่าการจัดสรรใหม่ที่vectorเกิดจากการเปลี่ยนขนาดสามารถช้าได้หรือไม่ ตกลงกันแล้ว แต่ในกรณีที่reserve()สามารถใช้งานได้เพื่อหลีกเลี่ยงปัญหาเหล่านั้น
underscore_d

10

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

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

เพื่อตอบคำถามของคุณโดยเฉพาะฉันจะเสนอราคาหน้านี้

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


9

เมื่อใดก็ตามที่คุณไม่สามารถยกเลิกตัววนซ้ำได้


2
แต่อย่าข้ามไปที่ข้อสรุปเกี่ยวกับตัววนซ้ำโดยไม่ถามว่าการอ้างอิงแบบถาวรเป็นdequeพอหรือไม่
Potatoswatter

8

เมื่อคุณมีการแทรกหรือลบจำนวนมากในช่วงกลางของลำดับ เช่นผู้จัดการหน่วยความจำ


ดังนั้นความแตกต่างระหว่างพวกเขาจึงเป็นเพียงประสิทธิภาพไม่ใช่เรื่องของหน้าที่
skydoor

พวกเขาทั้งคู่จำลองลำดับขององค์ประกอบแน่นอน มีการใช้งานที่แตกต่างกันเล็กน้อยตามที่ระบุโดย @dirkgently แต่คุณต้องดูความซับซ้อนของการดำเนินการ "ทำเสร็จแล้ว" เพื่อตัดสินใจว่าจะเลือกลำดับใด (@Martin answer)
AraK

@skydoor - มีความแตกต่างการทำงานเล็กน้อย ตัวอย่างเช่นเฉพาะเวกเตอร์ที่สนับสนุนการเข้าถึงแบบสุ่ม (เช่นสามารถทำดัชนีได้)
Manuel

2
@skydoor: ประสิทธิภาพแปลว่าประสิทธิภาพ ประสิทธิภาพที่ไม่ดีอาจทำลายฟังก์ชันการทำงาน ประสิทธิภาพเป็นข้อดีของ C ++ หลังจากทั้งหมด
Potatoswatter

4

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


4

list::spliceเมื่อคุณต้องการที่จะย้ายวัตถุระหว่างภาชนะบรรจุที่คุณสามารถใช้

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

แก้ไข:เมื่อไลบรารีเตรียมใช้ C ++ 0x กรณีทั่วไปของการต่อเรียงลำดับลงในรายการกำลังกลายเป็นความซับซ้อนเชิงเส้นด้วยความยาวของลำดับ นี่เป็นเพราะsplice(ตอนนี้) จำเป็นต้องวนซ้ำลำดับเพื่อนับจำนวนองค์ประกอบในนั้น (เนื่องจากรายการต้องการบันทึกขนาดของมัน) เพียงแค่นับและเชื่อมโยงใหม่รายการก็ยังเร็วกว่าทางเลือกใด ๆ และการประกบทั้งรายการหรือองค์ประกอบเดียวเป็นกรณีพิเศษที่มีความซับซ้อนคงที่ แต่ถ้าคุณมีฉากต่อเนื่องที่ต่อเนื่องกันนานคุณอาจต้องขุดหาภาชนะที่ดีกว่าเก่าและไม่เข้ากัน


2

กฎฮาร์ดเดียวที่listต้องใช้คือที่ที่คุณต้องการกระจายพอยน์เตอร์ไปยังองค์ประกอบของคอนเทนเนอร์

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

(เทคนิคvectorของ*_ptrก็จะทำงาน แต่ในกรณีที่คุณกำลังลอกเลียนแบบlistเพื่อให้เป็นเพียงความหมาย.)

กฎอ่อนอื่น ๆ เกี่ยวข้องกับปัญหาประสิทธิภาพการทำงานที่เป็นไปได้ของการแทรกองค์ประกอบเข้าไปตรงกลางของคอนเทนเนอร์ซึ่งlistจะเป็นที่นิยมมากกว่า


2

ทำให้มันง่าย -
ในตอนท้ายของวันที่คุณสับสนในการเลือกคอนเทนเนอร์ใน C ++ ใช้อิมเมจแผนภูมิผังงานนี้ (กล่าวขอบคุณฉัน): - ป้อนคำอธิบายภาพที่นี่

เวกเตอร์ -
1. เวกเตอร์ขึ้นอยู่กับหน่วยความจำต่อเนื่อง
2. เวกเตอร์เป็นวิธีที่จะไปสำหรับชุดข้อมูลขนาดเล็ก
3. เวกเตอร์ทำงานได้เร็วที่สุดในขณะที่อยู่ในชุดข้อมูล
4. การลบการแทรกเวกเตอร์จะช้าในชุดข้อมูลขนาดใหญ่

รายการ -
1. รายการจะขึ้นอยู่กับหน่วยความจำฮีป
2. รายการเป็นวิธีที่จะไปสำหรับชุดข้อมูลขนาดใหญ่มาก
3. รายการค่อนข้างช้าในการข้ามชุดข้อมูลขนาดเล็ก แต่รวดเร็วที่ชุดข้อมูลขนาดใหญ่
4. การลบการแทรกรายการรวดเร็ว ชุดข้อมูลขนาดใหญ่ แต่ทำงานช้าลงสำหรับเครื่องที่เล็กกว่า


1

รายชื่อเป็นเพียงเสื้อคลุมสำหรับรายการที่เชื่อมโยงเป็นสองเท่าใน stl ดังนั้นจึงนำเสนอคุณลักษณะที่คุณอาจคาดหวังจาก d-linklist คือการแทรก O (1) และการลบ ในขณะที่เวกเตอร์เป็นลำดับข้อมูลติดต่อซึ่งทำงานเหมือนอาเรย์แบบไดนามิก PS- ง่ายต่อการสำรวจ


0

ในกรณีของเวกเตอร์และรายการความแตกต่างหลักที่ยื่นออกมาจากฉันมีดังต่อไปนี้:

เวกเตอร์

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

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

  • มันไม่ใช้หน่วยความจำเพิ่มเติมเพื่อเก็บพอยน์เตอร์ใด ๆ ไปยังองค์ประกอบอื่น ๆ ภายใน

รายการ

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

  • เนื่องจากรายการใช้หน่วยความจำที่ไม่ต่อเนื่องกันเวลาที่ใช้ในการแทรกองค์ประกอบภายในรายการนั้นมีประสิทธิภาพมากกว่าในกรณีของเวกเตอร์ของมันเนื่องจากหลีกเลี่ยงการจัดสรรหน่วยความจำใหม่

  • มันใช้หน่วยความจำเพิ่มเติมเพื่อเก็บพอยน์เตอร์ไปยังองค์ประกอบก่อนและหลังองค์ประกอบเฉพาะ

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


0

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

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