Quadtree พร้อมรายการที่ซ้ำกัน


10

ฉันกำลังใช้ควอดทรี สำหรับผู้ที่ไม่ทราบโครงสร้างข้อมูลนี้ฉันรวมถึงคำอธิบายเล็ก ๆ ต่อไปนี้:

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

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

ดังนั้นควอดทรีเป็นทั้งใบและมีองค์ประกอบน้อยกว่าความสามารถของมันหรือต้นไม้ที่มี 4 ควอดทรีเป็นเด็ก ๆ

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

ตัวอย่างเช่นถ้าคุณทำงานกับควอดทรีที่มีความจุ 1 และหน่วยสี่เหลี่ยมผืนผ้าเป็นกล่องขอบเขต:

[(0,0),(0,1),(1,1),(1,0)]

และคุณลองแทรกสี่เหลี่ยมสองอันบนขอบเขตซ้ายบนซึ่งเป็นจุดกำเนิด: (หรือในทำนองเดียวกันถ้าคุณลองแทรก N + 1 ครั้งในควอดทรีที่มีความจุ N> 1)

quadtree->insert(0.0, 0.0, 0.1, 0.1)
quadtree->insert(0.0, 0.0, 0.1, 0.1)

ส่วนแทรกครั้งแรกจะไม่มีปัญหา: แทรกครั้งแรก

แต่เมื่อแทรกครั้งแรกจะก่อให้เกิดการแบ่ง (เพราะความจุเป็น 1): เม็ดมีดที่สองแผนกแรก

สี่เหลี่ยมทั้งสองจึงใส่ในทรีย่อยเดียวกัน

จากนั้นอีกครั้งทั้งสององค์ประกอบจะมาถึงในควอดทรีเดียวกันและก่อให้เกิดการแบ่งย่อย ... ส่วนที่สองแทรกส่วนที่สอง

และอื่น ๆ เป็นต้นวิธีการจัดสรรจะทำงานอย่างไม่มีกำหนดเพราะ (0, 0) จะอยู่ในทรีย่อยเดียวกันจากสี่ที่สร้างขึ้นซึ่งหมายถึงปัญหาการวนซ้ำแบบไม่สิ้นสุด

เป็นไปได้หรือไม่ที่จะมีควอดทรีที่ซ้ำซ้อน? (หากไม่ใช่อาจใช้เป็นกSet)

เราจะแก้ปัญหานี้โดยไม่ทำลายสถาปัตยกรรมของควอดทรีได้อย่างไร


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

@ ไม่มีประโยชน์นั่นเป็นเรื่องจริงมาก อย่างไรก็ตามต้องมีการวิจัยค่อนข้างมากในหัวข้อและฉันไม่ต้องการบูรณาการล้อทั้ง TBH ฉันยังไม่รู้ว่าคำถามนี้เป็นของ SO, ในโปรแกรมเมอร์, gamedev.SE หรือคณิตศาสตร์หรือไม่ ...
Pierre Arlaud

คำตอบ:


3

คุณกำลังนำโครงสร้างข้อมูลมาใช้ดังนั้นคุณต้องตัดสินใจใช้งาน

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

การตัดสินใจติดตั้งใช้งานนั้นไม่ได้มีการคิดค้นขึ้นใหม่อย่างน้อยก็ไม่มากไปกว่าการเขียนการติดตั้งของคุณเอง

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

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


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

สำหรับโครงสร้างของต้นไม้บางครั้งโหนดที่มีค่าบางครั้งก็ให้ช่อง "นับ" ที่เพิ่มและลดลงสำหรับการทำซ้ำ
J Trana

2

ฉันคิดว่ามีความเข้าใจผิดที่นี่

ดังที่ฉันเข้าใจแล้วโหนดควอดทรีทุกอันจะมีค่าที่ดัชนีโดยจุด มันมีสาม (x, y, value)

นอกจากนี้ยังมี 4 ตัวชี้ไปยังโหนดลูกซึ่งอาจเป็นโมฆะ มีความสัมพันธ์อัลกอริทึมระหว่างปุ่มและลิงก์ลูก

ส่วนแทรกของคุณควรมีลักษณะเช่นนี้

quadtree->insert(0.0, 0.0, value1)
quadtree->insert(0.0, 0.0, value2)

การแทรกครั้งแรกสร้างโหนด (พาเรนต์) และแทรกค่าลงในมัน

การแทรกครั้งที่สองจะสร้างโหนดลูกเชื่อมโยงกับมันและแทรกค่าลงในนั้น (ซึ่งอาจเกิดขึ้นเหมือนกับค่าแรก)

โหนดลูกใดที่อินสแตนซ์ขึ้นอยู่กับอัลกอริทึม หากอัลกอริทึมอยู่ในรูปแบบ [x) และพื้นที่ประสานงานอยู่ในช่วง [0,1) จากนั้นเด็กแต่ละคนจะขยายช่วง [0,0.5) และจุดจะถูกวางไว้ในเด็ก ๆ NW

ฉันไม่เห็นการวนซ้ำไม่มีที่สิ้นสุด


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

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

2

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

ฉันคิดว่าประเด็นหลักในความโปรดปรานคือมันง่ายที่จะทำ


2

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

โหนด Quadtree ไม่จำเป็นต้องมีความจุคงที่ กำลังการผลิตที่ใช้ในการ

  • อนุญาตให้แต่ละโหนดต้นไม้มีขนาดคงที่ในหน่วยความจำหรือบนดิสก์ - ไม่จำเป็นถ้าโหนดต้นไม้มีชุดองค์ประกอบขนาดตัวแปรและคุณใช้ระบบการจัดสรรพื้นที่ที่ copes (เช่นวัตถุ java / c # ในหน่วยความจำ)
  • ตัดสินใจว่าจะแยกโหนดเมื่อใด
    • คุณสามารถกำหนดกฎใหม่เพื่อให้โหนดถูกแบ่งหากมันมีองค์ประกอบอำเภอมากกว่า "n" โดยที่เขตพื้นที่ถูกกำหนดตามสถานที่ตั้งขององค์ประกอบ
    • หรือใช้“ องค์ประกอบประกอบ ” ดังนั้นหากมีองค์ประกอบหลายรายการในตำแหน่งเดียวกันคุณแนะนำองค์ประกอบใหม่ที่มีรายการองค์ประกอบคูณเหล่านี้

2

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

ป้อนคำอธิบายรูปภาพที่นี่

... และเข้าใจจุดอ่อนของมันก่อนที่จะย้ายไปยังโครงสร้างต้นไม้ที่อนุญาตให้มีการกระจัดกระจาย

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

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

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

ป้อนคำอธิบายรูปภาพที่นี่

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

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

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

แต่ถ้าคุณคิดว่าต้นไม้สี่ควมเป็นประโยชน์สูงสุดเหนือกริดสำหรับกรณีการใช้งานที่เฉพาะเจาะจงแล้วมันจะช่วยให้ยังคงคิดของ "ขนาดเซลล์ขั้นต่ำ" เพื่อจำกัดความลึกของแผนกย่อยแบบเรียกซ้ำของโหนดแบบควอดทรี เมื่อคุณทำเช่นนั้นสถานการณ์ที่เลวร้ายที่สุดของ quad-tree จะยังคงลดลงในกริดหนาแน่นที่ใบไม้เพียง แต่มีประสิทธิภาพน้อยกว่ากริดเนื่องจากมันจะต้องใช้เวลาลอการิทึมเพื่อทำงานในแบบของคุณจากรูทถึงเซลล์กริดแทน คงเวลา ทว่าการคิดขนาดเซลล์ขั้นต่ำนั้นจะหลีกเลี่ยงสถานการณ์ลูป / การวนซ้ำที่ไม่สิ้นสุด สำหรับองค์ประกอบขนาดใหญ่นอกจากนี้ยังมีตัวแปรทางเลือกบางอย่างเช่นต้นไม้สี่ต้นที่ไม่จำเป็นต้องแบ่งเท่า ๆ กันและอาจมี AABB สำหรับโหนดลูกที่ทับซ้อนกัน BVHs ยังน่าสนใจเช่นโครงสร้างการจัดทำดัชนีเชิงพื้นที่ซึ่งไม่แบ่งย่อยโหนดของพวกเขาอย่างเท่าเทียมกัน สำหรับองค์ประกอบที่สอดคล้องกันกับโครงสร้างต้นไม้ สิ่งสำคัญคือการกำหนดขีด จำกัด ของแผนก (หรือตามที่คนอื่น ๆ แนะนำปฏิเสธพวกเขาหรือหาวิธีที่จะปฏิบัติต่อพวกเขาราวกับว่าพวกเขาไม่ได้มีส่วนร่วมกับจำนวนองค์ประกอบที่ไม่ซ้ำกันในใบไม้เมื่อพิจารณาเมื่อใบไม้ ควรแบ่งย่อย) ต้นไม้ Kd อาจมีประโยชน์ถ้าคุณคาดว่าอินพุตที่มีองค์ประกอบหลาย ๆ อย่างบังเอิญเนื่องจากคุณต้องพิจารณาเพียงมิติเดียวเมื่อพิจารณาว่าโหนดควรแบ่งค่ามัธยฐานหรือไม่


เป็นการอัปเดตสำหรับควอดทรีบางคนถามคำถามที่ค่อนข้างกว้าง (แต่ฉันชอบพวกนั้น) เกี่ยวกับวิธีทำให้มีประสิทธิภาพสำหรับการตรวจจับการชนกันของข้อมูล นอกจากนี้ยังควรตอบคำถามของคุณ: stackoverflow.com/questions/41946007/…
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.