ไลบรารีมาตรฐาน C ++ มีชุดที่เรียงลำดับตามคำสั่งการแทรกหรือไม่

ไลบรารีมาตรฐาน C ++ มีโครงสร้างข้อมูล "ชุดสั่ง" หรือไม่ ตามชุดคำสั่ง ฉันหมายถึงบางสิ่งที่เหมือนกับชุด std::set ทั่วไปทุกประการ แต่จะจำลำดับที่คุณเพิ่มรายการเข้าไป

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


person Seth Carnegie    schedule 18.10.2011    source แหล่งที่มา
comment
คุณต้องการที่จะสามารถเข้าถึงได้อย่างรวดเร็วทั้งตามลำดับการเรียงลำดับและลำดับการแทรกหรือไม่   -  person Cascabel    schedule 18.10.2011
comment
จริงๆ แล้วคุณลักษณะอื่นๆ ของ set ที่คุณสนใจคืออะไร เอกลักษณ์? ประสิทธิภาพการกำจัด?   -  person Robᵩ    schedule 18.10.2011
comment
@Jefromi ฉันต้องการบอกอย่างรวดเร็วว่ามีรายการอยู่ในชุดหรือไม่และวนซ้ำตามลำดับที่แทรกถ้าเป็นไปได้   -  person Seth Carnegie    schedule 18.10.2011
comment
สิ่งที่คุณอธิบายคือสถานการณ์ที่แน่นอน Boost.MultiIndex ถูกสร้างขึ้นเพื่อ (ดูคำตอบของ @ KerrekSB)   -  person ildjarn    schedule 18.10.2011
comment
@Rob ความเป็นเอกลักษณ์และความเร็วในการตรวจสอบว่ามีบางอย่างอยู่ในชุดหรือไม่   -  person Seth Carnegie    schedule 18.10.2011


คำตอบ (6)


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

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

person Kerrek SB    schedule 18.10.2011
comment
+1 สำหรับการแนะนำ Boost.MultiIndex -- มันเป็นทางออกที่ดีที่สุดสำหรับคำถามประเภทนี้จริงๆ - person ildjarn; 18.10.2011
comment
คุณสามารถใช้แลมบ์ดาสำหรับฟังก์ชันการเปรียบเทียบเมื่อเริ่มต้นชุด เขาต้องการความเป็นเอกลักษณ์ขององค์ประกอบแต่ต้องเรียงลำดับการแทรก ฉันคิดว่านี่อาจจะเป็นไปได้? ไม่เข้าใจว่าทำไมถึงห้าม - person dylan; 16.09.2017
comment
อาจใช้เวกเตอร์และอัลกอริธึมเฉพาะเพื่อลบองค์ประกอบที่ไม่ซ้ำกัน หรือช้ากว่าวิธีอื่น? ฉันเดาว่าอัลกอริธึมการค้นหาจะช้ากว่าการเก็บดัชนีเพียงอย่างเดียว - person dylan; 16.09.2017
comment
@dylan: ใช่ แต่นั่นจะไม่ใช่คอนเทนเนอร์เดียว คุณสามารถสร้างพฤติกรรมใดๆ ก็ตามเท่าที่จินตนาการได้ด้วยอาเรย์และอัลกอริธึม (หน่วยความจำคอมพิวเตอร์เป็นเพียงอาเรย์ขนาดใหญ่เพียงอันเดียว)... - person Kerrek SB; 16.09.2017

แทนที่จะสร้าง std::set ประเภทใดก็ตามที่คุณใช้อยู่ ทำไมไม่ลองส่ง std::pair ของอ็อบเจ็กต์และดัชนีที่จะเพิ่มขึ้นในการแทรกแต่ละครั้งล่ะ

person pg1989    schedule 18.10.2011
comment
นั่นคงจะได้ผลหากคุณใช้ความระมัดระวังในการแทรกค่าที่มีอยู่ และหากคุณมีนโยบายว่าจะค้นหาดัชนีที่ใหญ่ที่สุดในเวลาคงที่ได้อย่างไร บางที std::map<T, unsigned int> อาจจะดูหรูหรากว่าเล็กน้อย เนื่องจากประเภทค่าของมันเป็นคู่อยู่แล้ว (และคุณจะได้รับองค์ประกอบที่แมปที่ไม่แน่นอน) - person Kerrek SB; 18.10.2011
comment
@SethCarnegie: โปรดทราบว่าคุณยังคงต้องสามารถค้นหาดัชนีปัจจุบันสูงสุดได้และนั่นอาจไม่สามารถทำได้ในเวลาคงที่หรือแม้แต่ลอการิทึม - person Kerrek SB; 18.10.2011
comment
@Kerrek ทำไม? ถ้าคุณเริ่มจาก 0 (ซึ่งผมเป็น) คุณสามารถใช้ map::size เพื่อค้นหาดัชนีที่ใหญ่ที่สุดได้ใช่ไหม? - person Seth Carnegie; 18.10.2011
comment
@SethCarnegie: ใช่ คุณสามารถใช้ size() ได้ ฉันไม่ได้คิดเรื่องนั้นมาก่อน! - person Kerrek SB; 18.10.2011
comment
คำตอบอื่นของ Kerrek ยังคงดีกว่าโดยทั่วไป เนื่องจาก Boost.MultiIndex จะช่วยให้คุณ มีประสิทธิภาพ เข้าถึงคอนเทนเนอร์ที่จัดทำดัชนีตามลำดับการแทรก เนื่องจากสิ่งต่าง ๆ เป็นไปตาม map<T, unsigned int> นี้ จึงเป็นการดำเนินการ O(n) เพื่อค้นหาองค์ประกอบที่มีดัชนีที่กำหนด การวนซ้ำในลำดับการแทรกคือ O(n^2) โดยไม่มีหน่วยความจำเพิ่มเติม หรือ O(n log n) พร้อมหน่วยความจำเพิ่มเติม O(n) หากคุณคัดลอกล็อตทั้งหมดลงในอาร์เรย์และเรียงลำดับก่อนวนซ้ำ อาจจะดีสำหรับจุดประสงค์ของ Seth แต่ค่อนข้างเข้มงวด... - person Steve Jessop; 18.10.2011

ไม่มันไม่ได้

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

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

person Steve Jessop    schedule 18.10.2011
comment
อ่า แย่จังเลย คุณแนะนำให้ทำอะไรแทน? - person Seth Carnegie; 18.10.2011

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

person Jun    schedule 21.03.2014

[ข้อจำกัดความรับผิดชอบ: ฉันได้ให้คำตอบที่คล้ายกันกับคำถามนี้ แล้ว]

หากคุณสามารถใช้ Boost ได้ วิธีแก้ปัญหาที่ตรงไปตรงมามากคือใช้ไลบรารี่เฉพาะส่วนหัว Boost.Bimap (แผนที่แบบสองทิศทาง)

พิจารณาโปรแกรมตัวอย่างต่อไปนี้ที่จะแสดงรายการจำลองบางส่วนตามลำดับการแทรก (ลองที่นี่ ):

#include <iostream>
#include <string>
#include <type_traits>
#include <boost/bimap.hpp>

using namespace std::string_literals;

template <typename T>
void insertByOrder(boost::bimap<T, size_t>& mymap, const T& element) {
  using pos = typename std::remove_reference<decltype(mymap)>::type::value_type;
  // We use size() as index, therefore indexing the elements with 0, 1, ...
  mymap.insert(pos(element, mymap.size()));
}

int main() {
  boost::bimap<std::string, size_t> mymap;

  insertByOrder(mymap, "stack"s);
  insertByOrder(mymap, "overflow"s);

  // Iterate over right map view (integers) in sorted order
  for (const auto& rit : mymap.right) {
    std::cout << rit.first << " -> " << rit.second << std::endl;
  }
}

จำเป็นต้องใช้นามแฝงประเภท funky ใน insertByOrder() เพื่อแทรกองค์ประกอบลงใน boost::bimap ในบรรทัดต่อไปนี้ (ดูเอกสารอ้างอิง)

person andreee    schedule 03.05.2019

ใช่ มันเรียกว่าเวกเตอร์หรือรายการ (หรืออาร์เรย์) เพียงต่อท้ายเวกเตอร์เพื่อเพิ่มองค์ประกอบให้กับเซต

person Lie Ryan    schedule 18.10.2011
comment
ใช่ แต่ทั้งหมดนี้อนุญาตให้มีองค์ประกอบที่ซ้ำซ้อน ซึ่งเป็นไปได้มากว่าสิ่งที่ OP พยายามหลีกเลี่ยง - person pg1989; 18.10.2011
comment
pg1989 ถูกต้อง ฉันไม่ต้องการองค์ประกอบที่ซ้ำกัน และฉันไม่ต้องการค้นหาเชิงเส้นในอาร์เรย์เพื่อตรวจสอบ - person Seth Carnegie; 18.10.2011