ควรใช้ vector / list เมื่อใด


17

ฉันสามารถเข้าใจได้ว่าจะใช้รายการเมื่อใด แต่ฉันไม่เข้าใจว่าเมื่อใดควรใช้เวกเตอร์ดีกว่าการใช้รายการในวิดีโอเกม: เมื่อใดจึงจะมีการเข้าถึงแบบสุ่มอย่างรวดเร็ว

(และฉันเข้าใจว่าทำไมการแทรก / ลบในรายการเร็วขึ้นเพราะเพิ่งลบ / เพิ่มตัวชี้ แต่ยังต้องค้นหารายการที่เกี่ยวข้อง ... )


เพิ่มแท็กเวกเตอร์อีกครั้งในรายการนี้ - ถ้ารายการเป็นแท็กที่ถูกต้องแสดงว่าเวกเตอร์นั้นเกินไป
Kylotan

สมมุติว่าเวกเตอร์ถูกลบเพราะมันใช้เพื่อหมายถึงเวกเตอร์เชิงคณิตศาสตร์ไม่ใช่ std :: vector

1
containerวิธีการเกี่ยวกับระวังพวกเขาทั้งสองและวาง
deft_code

@Kylotan: มันเป็นโจพูด คำถามนี้เกี่ยวกับเวกเตอร์แน่นอน แต่มันไม่ได้อยู่ในแท็กเวกเตอร์
doppelgreener

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

คำตอบ:


29

กฎง่ายๆของฉันและฉันแน่ใจว่าจะมีการอภิปรายในเรื่องนี้คือไม่เคยใช้รายการ (เว้นแต่คุณจะต้องลบสิ่งต่าง ๆ ออกจากรายการขนาดใหญ่บ่อยมาก)

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

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


1
ฉันคิดว่ามันขึ้นอยู่กับความต้องการของคุณเป็นอย่างมากหากคุณไม่จำเป็นต้องเข้าถึงองค์ประกอบที่เฉพาะเจาะจงและเพียงแค่ต้องอ่านทั้งหมดและคุณต้องเพิ่มและลบองค์ประกอบต่างๆบ่อยครั้งรายการนี้เป็นทางออกที่ดีกว่า
Frédérick Imbeault

11
@ Frédérick: นั่นคือภูมิปัญญา C ++ มาตรฐาน แต่ก็เกือบจะผิดเสมอไป เวกเตอร์โดยเฉพาะอย่างยิ่งเมื่อต้องรับมือกับพาหะของพอยน์เตอร์ (ซึ่งคุณมักจะเป็นเกม) มีความรวดเร็วมากที่จะลบสิ่งต่าง ๆ ออกจากกลาง - มันเป็นเวลาเชิงเส้น แต่มันเป็นค่าใช้จ่ายที่เล็กมากต่อรายการ นอกจากนี้ยังเร็วกว่ามากในการวนซ้ำตามลำดับในเวกเตอร์

1
ฉันไม่แน่ใจว่าโครงสร้างแบบไหนที่คุณได้รับ - การเพิ่มประสิทธิภาพแบบนี้ต้องการตัวอย่างที่เป็นรูปธรรมในการพูดอะไรที่ชัดเจน ตัวอย่างเช่นปฏิกิริยาแรกของฉันต่อกรณีการใช้งานของคุณจะเป็นชุดที่ไม่เรียงลำดับซึ่งอนุญาตให้มีการแทรกการลบและการค้นหาอย่างรวดเร็ว ในชุดประสบการณ์ของฉันนั้นยอดเยี่ยมสำหรับวัตถุในบรรณาธิการ แต่ในขณะที่บรรณาธิการมีข้อกำหนดด้านประสิทธิภาพแบบเรียลไทม์ที่เข้มงวดมากเช่นการตอบสนองต่อการกดปุ่ม "ลบ" จะใช้เวลา 1/20 วินาทีหรือใช้เวลา 1/2 ของ 10% ของวินาที - การเพิ่มประสิทธิภาพในระดับนี้ ก็ไม่ค่อยมีผลกับพวกเขา

1
@ Frédérick Imbeault Modified ไม่ได้เป็นปัญหามากนักคือ Add \ Remove ที่ทำให้เกิดปัญหา ตั้งแต่จุดเพิ่ม \ ลบไปจนถึงจุดสิ้นสุดของเวกเตอร์จะถูกคัดลอกเพื่อให้เวกเตอร์อยู่ติดกัน หากลำดับองค์ประกอบไม่สำคัญคุณสามารถสลับองค์ประกอบที่ถูกลบด้วยองค์ประกอบสุดท้ายจากนั้นป๊อปอัพเพื่อลบและเพิ่มไปยังจุดสิ้นสุดสำหรับการเพิ่ม
หินใน

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

8

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

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


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

5

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

รายการ:

  • แต่ละองค์ประกอบใช้จำนวนเต็ม 2 จำนวนในการชี้องค์ประกอบก่อนหน้าและถัดไปดังนั้นโดยทั่วไปแล้วนั่นคือ 8 ไบต์สำหรับแต่ละองค์ประกอบในรายการของคุณ
  • ส่วนแทรกเป็นเส้นตรงในเวลา: O (n)
  • การลบคือการทำงานที่คงที่: O (1)
  • การเข้าถึงองค์ประกอบ x เป็นเส้นตรงเวลา: O (n)

เวกเตอร์:

  • ต้องการหน่วยความจำน้อยกว่า (ไม่มีตัวชี้องค์ประกอบอื่น ๆ มันเป็นอัลกอริทึมทางคณิตศาสตร์อย่างง่าย)
  • การลบเป็นเส้นตรงในเวลา: O (n)
  • การเข้าถึงองค์ประกอบ x เป็นค่าคงที่: O (1) (นั่นเป็นเพราะองค์ประกอบมีความต่อเนื่องในหน่วยความจำดังนั้นจึงเป็นการดำเนินการทางคณิตศาสตร์อย่างง่าย vectorPtr + (x * bytesOfTheType))
  • การแทรกสามารถอยู่ในเวลาเชิงเส้น แต่โดยทั่วไปแล้วมันเป็นการดำเนินการคงที่: O (1) (นั่นเป็นเพราะเวกเตอร์ในอาร์เรย์ แต่มักจะสำรอง 2 เท่าของความจุเมื่ออาร์เรย์เต็มดังนั้นการคัดลอกอาร์เรย์จึงไม่บ่อย)

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

ตรวจสอบโพสต์นี้ใน stackoverflow มันมีกราฟที่ดีจริงๆพร้อมคำถามพื้นฐานเกี่ยวกับความต้องการของคุณที่นำคุณไปยังที่เก็บเฉพาะโดยขึ้นอยู่กับคำตอบของคุณ:

/programming/366432/extending-stdlist


3
กราฟนั้นต้องเริ่มต้นด้วย "คุณเก็บพอยน์เตอร์และน้อยกว่าหนึ่งพันหรือไม่ไม่ใช่ -> เวกเตอร์" โหนด

ใช่บางทีคุณพูดถูกฉันไม่ได้พิจารณาประเภทที่จัดเก็บที่ควรวิเคราะห์
Frédérick Imbeault

2

รายการมักจะใช้สำหรับโครงสร้างเช่นคิวที่มีจำนวนมากผนวกและลบการดำเนินงาน ตัวอย่าง:รายการเอนทิตีที่เปลี่ยนแปลงตลอดเวลาที่ควรได้รับการอัพเดต รายการตัวเองมีเอนทิตีบนหน้าจอเท่านั้นดังนั้นจึงเปลี่ยนบ่อย

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

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


ฉันอาจใส่ C ลงไปด้วย แต่ก็ไม่มีตู้คอนเทนเนอร์ดังกล่าวใน C แต่นั่นเป็นสิ่งที่ควรคำนึงถึง: มีห้องสมุดเหมือน STL สำหรับ C หรือไม่
jokoon

ฉันเคยใช้ glib ( library.gnome.org/devel/glib ) ในอดีตซึ่งใช้โครงสร้างข้อมูลมาตรฐานจำนวนมากสำหรับ C. ฉันเกลียดเพราะมักจะ verbose มากเกินไปและอยากจะเป็น C ++ แต่มันเป็นผู้ใหญ่และ มีเสถียรภาพ

0

ในเกมคอนโซลเราไม่เคยใช้ std :: list เพราะ:

  1. มันจะจัดสรรหน่วยความจำทุกครั้งที่คุณเพิ่มรายการใหม่ การจัดสรรหน่วยความจำช้า
  2. มันเต็มไปด้วยพอยน์เตอร์ พอยน์เตอร์ไม่ดี ตัวชี้คือแคชพลาด แคชที่ไม่ดี

แม้ std :: vector สูญเสียความนิยมบนคอนโซลเพราะ:

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

5
@bmcnett "[] .. แต่ std :: vector ต้องการให้คุณเก็บทุกอย่างสำหรับแต่ละวัตถุในหน่วยความจำอันต่อเนื่อง" - นั่นไม่ใช่คำถามของคอนเทนเนอร์มันเป็นคำถามเกี่ยวกับโครงร่างข้อมูลของคุณคุณสามารถมีตำแหน่งทั้งหมดได้ ในหน่วยความจำที่ต่อเนื่องกับ std :: vector:struct point{float x, y, z, w}; std::vector<point> positions;
Maik Semder

โรงเรียนของฉันจะรักสิ่งนี้ :)
jokoon

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

คุณเข้าใจผิดการเรียกร้องของฉัน ฉันไม่เคยพูดว่าในบรรดาทุกคอนเทนเนอร์ std :: vector มีความผิดโดยเฉพาะอย่างยิ่งที่ทำให้เกิดมลพิษแคช ภาชนะทั้งหมดและในความเป็นจริงแม้กระทั่งอาร์เรย์มีความผิดเท่ากัน std :: vector หลุดออกจากความโปรดปรานเพราะวัตถุ C ++ เองนั้นหลุดลอยไป C ++ กำหนดว่าข้อมูลของแต่ละวัตถุจะต่อเนื่องกันในหน่วยความจำ คุณสามารถหลีกเลี่ยงสิ่งนั้นได้โดยหลีกเลี่ยงวัตถุ C ++ เช่นโดยใช้ std :: vector <position> ตามที่กล่าวไว้ข้างต้น
bmcnett

3
ยกเว้นpointเป็นวัตถุ C ++ (เช่นstd::vectorเดียวกับเป็นสิ่งที่ง่ายเหมือนfloat) ฉันรู้ความแตกต่างที่คุณพยายามวาด แต่คุณทำงานได้ไม่ดีในการอธิบาย
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.