มีโครงสร้างข้อมูลใดบ้างที่รักษาชุดของชุด (ของชุดดิน จำกัด ) สนับสนุนการดำเนินการดังต่อไปนี้หรือไม่? เวลาในการทำงานช่วงล่างใด ๆ จะได้รับการชื่นชม?
- เริ่มต้นชุดที่ว่างเปล่า
- เพิ่มองค์ประกอบให้กับชุด
- ให้สองชุดรายงานว่าพวกเขาตัดกัน
มีโครงสร้างข้อมูลใดบ้างที่รักษาชุดของชุด (ของชุดดิน จำกัด ) สนับสนุนการดำเนินการดังต่อไปนี้หรือไม่? เวลาในการทำงานช่วงล่างใด ๆ จะได้รับการชื่นชม?
คำตอบ:
หากแต่ละชุดรักษาระเบียนของชุดอื่น ๆ ที่มีอยู่และคุณมีจำนวนชุดคุณสามารถเปลี่ยนโครงสร้างข้อมูลใด ๆ สำหรับคอลเลกชัน ( เช่นแผนภูมิการค้นหาแบบไบนารี่ฯลฯ ) เป็นชุดที่คุณสามารถเรียกคืนได้ องค์ประกอบของจุดตัดของสองชุดในเวลาs)
แต่ละชุดควรมีตัวระบุที่ไม่ซ้ำกันจากชุดที่สั่งทั้งหมดบางชุด หากคุณตั้งชื่อชุดของคุณอย่างชัดเจนตัวระบุอาจเป็นดัชนีได้
คุณควรใช้ "รีจิสทรี" ของชุด โครงสร้างข้อมูลที่เก็บชุดทั้งหมดที่คุณกำหนดไว้ ควรใช้รีจิสทรีเป็นโครงสร้างข้อมูลการค้นหาแบบทรีเพื่อให้สามารถดึงข้อมูลได้ง่าย ( เช่น หากคุณต้องการลบชุด) และการข้ามเวลาเชิงเส้นของชุด
แต่ละชุดยังรักษา "ดัชนี" ของแต่ละชุดอื่น ๆ - ไม่ใช่สำเนาของพวกเขา แต่ค่อนข้างโครงสร้างข้อมูลที่จัดทำดัชนีโดยป้ายชื่อของชุดอื่น ๆ ดัชนีนี้จะถูกใช้ในการรักษาสำหรับแต่ละชุดต้นไม้ค้นหาแบบทวิภาคของทุกองค์ประกอบของS_k (ทั้งสองชุดและแบ่งปันแผนภูมิการค้นหาหนึ่งสำเนา)S k S j ∩ S k S j S k
การเริ่มต้น
การเริ่มต้นของชุดประกอบด้วยการดำเนินงานเพื่อเริ่มต้นต้นไม้ขององค์ประกอบการดำเนินงานในขณะที่คุณเริ่มต้น (คัดลอกจากรีจิสทรี) ดัชนีสำหรับชุดและการดำเนินงานในขณะที่คุณสำรวจรีจิสทรีเพื่อเพิ่มลงในดัชนีของแต่ละชุดอื่น ๆS_jในดัชนีของเราจะสร้างค้นหาซึ่งเป็นตัวแทนของสำหรับชุดอื่น ; เราคัดลอกตัวชี้เหมือนกันสำหรับดัชนีของS_jO ( 1 ) O ( s ) T O ( s บันทึกs ) T S j T T ∩ S j = ∅ S j S j
การเพิ่มองค์ประกอบให้กับชุด
การเพิ่มให้กับชุดต้องใช้เวลาตามปกติโดยที่. นอกจากนี้เรายังทดสอบการเป็นสมาชิกของในแต่ละชุดอื่น ๆซึ่งต้องใช้เวลาที่คือขนาดของจักรวาล (หรือชุดที่ใหญ่ที่สุด ) และคือจำนวนชุดในรีจิสทรี สำหรับแต่ละชุดเช่นว่ายังแทรกลงในดัชนีสำหรับชุดT สำหรับแต่ละชุดดังกล่าวT O ( บันทึกn T ) n T = | T | x S 1 , S 2 , … O ( บันทึกn S 1 + บันทึกn S 2 + ⋯ ) ⊆ O ( s บันทึกn ) , n = | V | S j s S j x ∈ S j
หากคุณไม่อนุญาตให้ซ้ำกันในชุดเราสามารถประหยัดเวลาในกรณีที่แล้วโดยละทิ้งการทดสอบการเป็นสมาชิกและการแทรกสำหรับชุดอื่น ๆT"แทรก" ในกรณีที่มีอยู่แล้วจากนั้นใช้เวลาเพียงn_T)T x O ( log n T )
การทดสอบทางแยก
ดัชนีของแต่ละชุดได้รับการดูแลรักษาอย่างแม่นยำเพื่อให้สามารถประเมินได้อย่างรวดเร็วว่ามีสองชุดและตัดกันหรือไม่ สำหรับชุดเพียงแค่ตรวจสอบดัชนีของชุดเราไม่สามารถตัดสินได้เฉพาะในเวลาไม่ว่าตัดกันแต่เราสามารถดึงต้นไม้ไบนารีที่มีทั้งชุดS_kS k S j S k O ( บันทึกs ) S j S k S j ∩ S k
การกำจัดองค์ประกอบ
ในการลบองค์ประกอบออกจากชุดเราไม่เพียง แต่ลบออกจากการค้นหาสำหรับตัวแต่จากจุดตัดแต่ละสำหรับชุดในดัชนี สิ่งนี้ต้องใช้เวลาโดยที่.T T S j ∩ T S j O ( s บันทึกn T ) n T = | T |
ตั้งค่าการลบ
เนื่องจากค่าใช้จ่ายในการค้นหารีจิสทรีหากคุณมีหลายชุดคุณอาจต้องการลบชุดเมื่อไม่จำเป็นต้องใช้อีกต่อไป โดยการข้ามรีจิสทรีทั้งหมดเราอาจลบออกจากดัชนีของชุดอื่น ๆ ทั้งหมดในเวลาซึ่งมีค่าใช้จ่ายในการลบการค้นหาที่เป็นตัวแทนของสำหรับชุดอื่น ๆ แต่ละโดยที่.S j O ( s n T ) S j ∩ T S j n T = | T |
หมายเหตุ
หากคุณคาดว่าจะใช้จำนวนชุดคงที่เท่านั้นดังนั้นเวลาทำงานข้างต้นจะลดลงเป็น:
การเริ่มต้น:
การแทรกองค์ประกอบ:
การทดสอบทางแยก (และการดึงของทางแยก):
การลบองค์ประกอบ:
การลบการตั้งค่า:
โดยที่คือขนาดของชุดที่ใหญ่ที่สุดในรีจิสตรีและn T = | T | สำหรับชุดTที่คุณใช้งาน
หากคุณคาดว่าจะมีการตั้งค่าโดยที่Vคือจักรวาลของคุณคุณอาจต้องการโครงสร้างข้อมูลที่แตกต่างกันหากคุณต้องการให้การดำเนินการเหล่านี้ทำงานในเวลาเชิงเส้นย่อย อย่างไรก็ตามหากคุณมีคู่ของชุดที่มีจุดตัดคุณรู้ว่าคุณจะไม่ทดสอบคุณอาจลดขนาดของดัชนีสำหรับชุด (โดยไม่รวมชุดที่คุณจะทดสอบ) หรือใช้มากกว่าหนึ่งรีจิสทรี ( หนึ่งชุดสำหรับชุดแต่ละชุดที่มีสี่แยกที่คุณอาจทดสอบ) ในความเป็นจริงแล้วรีจิสทรีจะมีประโยชน์ก็ต่อเมื่อคุณต้องการควบคุมจากส่วนกลางเพื่อให้แน่ใจว่าแต่ละชุดมีการบันทึกของกันและกันในดัชนี: มันอาจเป็นประโยชน์ในบางกรณีเมื่อเริ่มต้นชุดSเพียงบันทึกเฉพาะกิจแต่ละชุดใหม่เข้าไปในดัชนีของชุดอื่นซึ่งมีจุดตัดกับS ที่คุณสนใจ
มีโครงสร้างข้อมูลที่อนุญาตให้คุณทำสิ่งนี้ในเวลาที่น้อยกว่าเชิงเส้นแม้แต่ในกรณีที่เลวร้ายที่สุด ดูhttp://research.microsoft.com/pubs/173795/vldb11intersection.pdf (และเอกสารอ้างอิงในนั้น)
หากทั้งสองชุด S และ T ของคุณมีจุดตัดขนาดใหญ่และคุณมีพจนานุกรมสำหรับ S การค้นหาองค์ประกอบของ T ตามลำดับแบบสุ่มควรให้องค์ประกอบทั่วไปอย่างรวดเร็ว กรณีที่ยากที่สุดคือเมื่อขนาดทางแยกเป็น 0 หรือ 1
โดยปกติภาษาการเขียนโปรแกรมที่คุณเลือกจะสนับสนุนโครงสร้างข้อมูลที่มีองค์ประกอบที่ไม่ซ้ำกัน โดยทั่วไปมีสามวิธีที่ได้รับความนิยม: ต้นไม้แฮชและบิตมาสก์ องค์ประกอบแบบต้นไม้จะต้องเปรียบเทียบกันได้องค์ประกอบแบบแฮชจะต้องเป็นแบบแฮชและองค์ประกอบแบบ Bitmask จะต้องมีวิธีการแปลงเป็นจำนวนเต็ม
ชุดต้นไม้จะรองรับการแทรกใน O (log n) และการทดสอบจุดตัดในกรณีที่แย่ที่สุด O (n log n)
ชุดแฮชจะรองรับการแทรกใน Amortized O (1 * h) โดยที่ 'h' เป็นเวลาทำงานของอัลกอริทึมการแปลงแป้นพิมพ์และการทดสอบการแยกในกรณีที่เลวร้ายที่สุด O (n)
โดยทั่วไปแล้วชุด Bitmask ไม่ได้ใช้เหมือนชุดต้นไม้และชุดแฮช
หากกรณีของคุณอนุญาตคำตอบที่เป็นเท็จฉันจะใช้Bloom Filterพร้อมฟังก์ชันแฮชเดียว
คุณสามารถใช้มันได้ดังต่อไปนี้:
เริ่มต้นชุดที่ว่างเปล่า
เพิ่มองค์ประกอบให้กับชุด
รับสองชุด (B1, B2) ให้รายงานว่าพวกเขาตัดกันหรือไม่
ความซับซ้อน