อะไรคือจุดใช้ของรายการเหนือเวคเตอร์ใน C ++?


32

ฉันใช้การทดลอง 3 แบบที่เกี่ยวข้องกับรายการ C ++ และเวกเตอร์

ผู้ที่มีเวกเตอร์พิสูจน์ได้ว่ามีประสิทธิภาพมากขึ้นแม้ว่าจะมีการแทรกอยู่ตรงกลางจำนวนมาก

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

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

  1. สร้างจำนวนเต็ม N และวางไว้ในคอนเทนเนอร์เพื่อให้คอนเทนเนอร์ยังคงเรียงลำดับ การแทรกได้รับการดำเนินการอย่างไร้เดียงสาโดยการอ่านองค์ประกอบทีละหนึ่งและแทรกใหม่ขวาก่อนที่จะมีขนาดใหญ่ขึ้นครั้งแรก
    ด้วยรายการเวลาจะผ่านหลังคาเมื่อมิติเพิ่มขึ้นเมื่อเทียบกับเวกเตอร์

  2. แทรกจำนวนเต็ม N ที่ส่วนท้ายของคอนเทนเนอร์
    สำหรับรายการและเวกเตอร์เวลาเพิ่มขึ้นตามลำดับความสำคัญเท่ากันแม้ว่ามันจะเร็วขึ้น 3 เท่าเมื่อใช้เวกเตอร์

  3. แทรกจำนวนเต็ม N ในคอนเทนเนอร์
    เริ่มจับเวลา
    เรียงลำดับคอนเทนเนอร์โดยใช้ list.sort สำหรับรายการและ std :: sort สำหรับเวกเตอร์ หยุดจับเวลา
    อีกครั้งเวลาเพิ่มขึ้นตามลำดับความสำคัญเท่ากัน แต่มันจะเร็วขึ้นโดยเฉลี่ย 5 เท่าด้วยเวกเตอร์

ฉันอาจทำการทดสอบต่อไปและหาตัวอย่างสองสามข้อที่รายการจะพิสูจน์ได้ดีขึ้น

แต่ประสบการณ์ร่วมกันของพวกคุณที่อ่านข้อความนี้อาจให้คำตอบที่มีประสิทธิผลมากขึ้น

คุณอาจเจอสถานการณ์ที่รายการใช้งานได้สะดวกกว่าหรือทำได้ดีกว่า



1
ต่อไปนี้เป็นแหล่งข้อมูลที่ดีอีกเรื่องในเรื่อง: stackoverflow.com/a/2209564/8360นอกจากนี้คำแนะนำ C ++ ส่วนใหญ่ที่ฉันเคยได้ยินคือใช้เวกเตอร์ตามค่าเริ่มต้นแสดงรายการเฉพาะเมื่อคุณมีเหตุผลเฉพาะ
Zachary Yates

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

1
listอาจจะดีกว่าถ้าคุณลบจำนวนมากขององค์ประกอบ ฉันไม่เชื่อว่าvectorจะส่งหน่วยความจำกลับคืนสู่ระบบจนกว่าจะลบเวกเตอร์ทั้งหมด โปรดทราบว่าการทดสอบ # 1 ของคุณไม่ได้ทดสอบเวลาการแทรกเพียงอย่างเดียว เป็นการทดสอบที่รวมการค้นหาและการแทรกเข้าด้วยกัน มันคือการหาสถานที่ที่จะแทรกที่ซึ่งlistช้า เม็ดมีดจริงจะเร็วกว่าเวกเตอร์
Gort the Robot

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

คำตอบ:


34

คำตอบสั้น ๆ คือกรณีดูเหมือนจะน้อยและไกล อาจมีบางอย่าง

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

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

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

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

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

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

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


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

2
กรณีวัตถุขนาดใหญ่ไม่ทำงานเลย การใช้พstd::vectorอยน์เตอร์จะมีประสิทธิภาพมากกว่าดังนั้นวัตถุโหนดรายการที่ลิงก์ทั้งหมด
Winston Ewert

มีประโยชน์หลายอย่างสำหรับรายการที่เชื่อมโยง - มันเป็นเพียงแค่ว่ามันไม่เหมือนกันกับอาร์เรย์แบบไดนามิก แคช LRU เป็นหนึ่งในการใช้งานทั่วไปของรายการที่เชื่อมโยง
Charles Salvia

นอกจากนี้std::vector<std::unique_ptr<T>>อาจเป็นทางเลือกที่ดี
Deduplicator

24

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

เขาพูดถึงเรื่องนี้ในงานนำเสนอนี้

เมื่อเวลาประมาณ 0:44 น. เขาพูดเกี่ยวกับเวกเตอร์กับรายการโดยทั่วไป

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

เมื่อเวลาประมาณ 1:08 เขาจะได้รับคำถามเกี่ยวกับปัญหานี้

สิ่งที่เราควรเห็นว่าเราต้องการลำดับขององค์ประกอบ และลำดับเริ่มต้นขององค์ประกอบใน C ++ คือเวกเตอร์ ตอนนี้เพราะมันกะทัดรัดและมีประสิทธิภาพ การนำไปใช้การทำแผนที่กับฮาร์ดแวร์เป็นสิ่งสำคัญ ตอนนี้ถ้าคุณต้องการปรับให้เหมาะสมสำหรับการแทรกและการลบ - คุณพูดว่า 'ดีฉันไม่ต้องการลำดับเวอร์ชันเริ่มต้น ฉันต้องการคนพิเศษซึ่งเป็นรายการ ' และถ้าคุณทำเช่นนั้นคุณควรรู้พอที่จะพูดว่า 'ฉันยอมรับค่าใช้จ่ายและปัญหาบางอย่างเช่นการสำรวจเส้นทางช้าและการใช้หน่วยความจำเพิ่มเติม'


1
คุณคิดจะเขียนโดยย่อสิ่งที่พูดในงานนำเสนอที่คุณเชื่อมโยงกับ "ที่เกี่ยวกับ 0:44 และ 1:08"
ริ้น

2
@gnat - แน่นอน ฉันพยายามที่จะพูดสิ่งที่ทำให้รู้สึกแยกจากกันและนั่นก็ต้องบริบทของสไลด์
Pete

11

ที่เดียวที่ฉันมักจะใช้ลิสต์คือที่ที่ฉันต้องการลบอิลิเมนต์และไม่ทำให้การวนซ้ำใช้ไม่ได้ std::vectorยกเลิกการทำซ้ำทั้งหมดในการแทรกและลบ std::listรับประกันว่าตัววนซ้ำสำหรับองค์ประกอบที่มีอยู่จะยังคงใช้ได้หลังจากใส่หรือลบ


4

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

แต่ถ้าคุณไม่จำเป็นต้องทำการดำเนินการเหล่านี้ก็อาจจะไม่


3

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

รายการที่เชื่อมโยงยังคงยอดเยี่ยม

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

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

ตัวเร่งกริดแบบง่าย

เป็นตัวอย่างที่ใช้งานได้จริงให้พิจารณาการจำลองด้วยภาพ 2D มันมีหน้าจอเลื่อนพร้อมแผนที่ซึ่งมีช่วง 400x400 (160,000 เซลล์กริด) ที่ใช้สำหรับเร่งสิ่งต่าง ๆ เช่นการตรวจจับการชนกันระหว่างอนุภาคนับล้านเคลื่อนที่รอบ ๆ ในแต่ละเฟรม (เราหลีกเลี่ยงต้นไม้แบบคี่ที่นี่ ข้อมูลไดนามิก) อนุภาคจำนวนมากเคลื่อนย้ายไปมาอย่างต่อเนื่องในทุก ๆ เฟรมซึ่งหมายความว่าพวกมันเปลี่ยนจากการอยู่ในเซลล์กริดหนึ่งไปอีกเซลล์หนึ่งอย่างต่อเนื่อง

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

สิ่งนี้สามารถมีประสิทธิภาพมากกว่าการจัดเก็บ 160,000 vectorsสำหรับแต่ละตารางเซลล์และผลักกลับและลบจากตรงกลางตลอดเวลาแบบทีละเฟรม

มาตรฐาน :: รายการ

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

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


1
มีมาตรฐานหลายอย่างที่เชื่อมโยงรายการตั้งแต่ C ++ std::forward_list11,
Sharyex

2

คุณควรพิจารณาขนาดขององค์ประกอบในภาชนะ

int เวกเตอร์องค์ประกอบนั้นเร็วมากเนื่องจากข้อมูลส่วนใหญ่จะอยู่ในแคชแคช (และอาจใช้คำสั่ง SIMD สำหรับการคัดลอกข้อมูล)

หากขนาดขององค์ประกอบใหญ่กว่าผลของการทดสอบ 1 และ 3 อาจเปลี่ยนไปอย่างมาก

จากการเปรียบเทียบประสิทธิภาพที่ครอบคลุมมาก :

ข้อสรุปง่ายๆนี้เกี่ยวกับการใช้งานโครงสร้างข้อมูลแต่ละอัน:

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

(เป็นหมายเหตุด้านข้างstd::dequeเป็นโครงสร้างข้อมูลที่ประเมินต่ำมาก)

จากมุมมองที่สะดวกสบายstd::listให้การรับประกันว่าตัววนซ้ำจะไม่กลายเป็นโมฆะเมื่อคุณแทรกและลบองค์ประกอบอื่น ๆ มันมักจะเป็นสิ่งสำคัญ


2

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

นี่ไม่ใช่กรณีที่มีรายการ

กฎที่แม่นยำสำหรับคอนเทนเนอร์มาตรฐานทั้งหมดจะได้รับในโพสต์ StackOverflowนี้


0

ในระยะสั้นไม่มีเหตุผลที่ดีสำหรับการใช้งานstd::list<>:

  • หากคุณต้องการคอนเทนเนอร์ที่ไม่เรียงลำดับstd::vector<>กฎ
    (ลบองค์ประกอบโดยแทนที่ด้วยองค์ประกอบสุดท้ายของเวกเตอร์)

  • หากคุณต้องการจัดเรียงคอนเทนเนอร์std::vector<shared_ptr<>>กฎ

  • หากคุณต้องการดัชนีกระจัดกระจายstd::unordered_map<>กฎ

แค่นั้นแหละ.

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


-1

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

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

ลำดับการใช้งานทั่วไปสำหรับคอนเทนเนอร์คือ vector, deque จากนั้นแสดงรายการ ตัวเลือกของคอนเทนเนอร์มักจะขึ้นอยู่กับ push_back select vector, pop_front select deque, insert select list


3
เมื่อลบรายการออกในขณะที่วนซ้ำจะเป็นการดีกว่าถ้าใช้เวกเตอร์และเพียงแค่สร้างเวกเตอร์ใหม่สำหรับผลลัพธ์
amara

-1

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

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

ฉันไม่รู้ว่านี่เป็นปัญหาใหญ่หรือไม่ แต่เป็นเหตุผลที่ทำให้ฉันในที่ทำงาน (การพัฒนาเกมมือถือ) เพื่อหลีกเลี่ยงเวกเตอร์


1
ไม่เวคเตอร์จะคัดลอกและมีราคาแพง แต่การข้ามผ่านรายการที่เชื่อมโยง (เพื่อค้นหาว่าจะแทรกที่ใด) ก็มีราคาแพงเช่นกัน ที่สำคัญคือการวัด
เคทเกรกอรี่

@KateGregory ฉันหมายถึงนอกเหนือไปจากนั้นขอให้ฉันแก้ไขตาม
Karthik T

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