เหตุใด C ++ STL จึงไม่ให้บริการคอนเทนเนอร์ "ต้นไม้"


373

เหตุใด C ++ STL จึงไม่ให้บริการคอนเทนเนอร์ "ต้นไม้" และสิ่งที่ดีที่สุดที่จะใช้แทนคืออะไร

ฉันต้องการจัดเก็บลำดับชั้นของวัตถุเป็นต้นไม้แทนที่จะใช้ต้นไม้เป็นการปรับปรุงประสิทธิภาพ ...


7
ฉันต้องการต้นไม้เพื่อจัดเก็บการแสดงลำดับชั้น
Roddy

20
ฉันกับคนที่ลงคะแนนตอบ "ถูกต้อง" ซึ่งดูเหมือนจะเป็น; "ต้นไม้ไร้ประโยชน์" มีความสำคัญหากการใช้ต้นไม้คลุมเครือ
Joe Soul-bringer

ฉันคิดว่าเหตุผลนั้นสำคัญเล็กน้อย - ยังไม่มีใครนำไปใช้ในห้องสมุดมาตรฐาน มันเหมือนห้องสมุดมาตรฐานไม่มีstd::unordered_mapและstd::unordered_setจนกระทั่งเมื่อเร็ว ๆ และก่อนหน้านั้นไม่มีคอนเทนเนอร์ STL ในไลบรารีมาตรฐานเลย
doc

1
ความคิดของฉัน (ไม่เคยอ่านมาตรฐานที่เกี่ยวข้องแม้ว่านี่คือความเห็นที่ไม่ใช่คำตอบ) คือ STL ไม่สนใจโครงสร้างข้อมูลที่เฉพาะเจาะจงมันใส่ใจกับข้อกำหนดที่เกี่ยวข้องกับความซับซ้อนและการดำเนินการที่สนับสนุน ดังนั้นโครงสร้างพื้นฐานที่ใช้อาจแตกต่างกันระหว่างการนำไปใช้งานและ / หรือสถาปัตยกรรมเป้าหมายหากเป็นไปตามข้อกำหนด ฉันค่อนข้างมั่นใจstd::mapและstd::setจะใช้ต้นไม้ในการติดตั้งทุกครั้งที่มี แต่พวกเขาไม่จำเป็นต้องทำหากโครงสร้างที่ไม่ใช่โครงสร้างบางส่วนนั้นตรงตามข้อกำหนด
Mark K Cowan

คำตอบ:


182

มีสองเหตุผลที่คุณอาจต้องการใช้ทรี:

คุณต้องการสะท้อนปัญหาโดยใช้โครงสร้างแบบต้นไม้:
สำหรับเรื่องนี้เรามีห้องสมุดกราฟเพิ่ม

หรือคุณต้องการภาชนะที่มีต้นไม้เหมือนลักษณะการเข้าถึงสำหรับสิ่งนี้เรามี

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

ดูคำถามนี้ด้วย: การใช้ C tree


64
มีหลายเหตุผลมากมายที่จะใช้ต้นไม้แม้ว่าสิ่งเหล่านี้จะเป็นเรื่องธรรมดา พบมากที่สุด! เท่ากับทั้งหมด
Joe Soul-bringer

3
เหตุผลหลักที่สามในการต้องการแผนผังสำหรับรายการที่เรียงลำดับเสมอพร้อมการแทรก / กำจัดอย่างรวดเร็ว แต่สำหรับ std: multiset
VoidStar

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

14
ฉันไม่เห็นด้วยกับคำตอบนี้ทั้งในปี 2008 และตอนนี้ ไลบรารี่มาตรฐานไม่มี "มี" การเพิ่มและความพร้อมใช้งานของบางสิ่งที่บูทไม่ควรมี (และยังไม่ได้รับ) เหตุผลที่จะไม่นำมันมาใช้เป็นมาตรฐาน นอกจากนี้ BGL นั้นเป็นเรื่องทั่วไปและมีส่วนร่วมมากพอที่จะรับคลาสต้นไม้พิเศษโดยไม่ขึ้นอยู่กับมัน นอกจากนี้ความจริงที่ว่า std :: map และ std :: set ต้องการ tree คือ IMO อาร์กิวเมนต์อีกอันสำหรับการมีstl::red_black_treeเป็นต้นในที่สุดต้นไม้std::mapและstd::setต้นไม้มีความสมดุลstd::treeอาจไม่เป็นเช่นนั้น
einpoklum

1
@ einpoklum: "ความพร้อมของบางสิ่งบางอย่างในการเพิ่มไม่ควรมีเหตุผลที่จะไม่นำมันมาใช้ในมาตรฐาน" - หนึ่งในวัตถุประสงค์ของการส่งเสริมคือการทำหน้าที่เป็นพื้นที่พิสูจน์สำหรับห้องสมุดที่มีประโยชน์ก่อนที่จะรวมตัวกันในมาตรฐาน พูดว่า "แน่นอน!"
Martin Bonner สนับสนุน Monica

94

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

บางประเด็นที่ต้องพิจารณา:

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

ในท้ายที่สุดปัญหาก็คือภาชนะต้นไม้ที่จะมีประโยชน์มากพอสำหรับทุกคนจะหนักเกินไปที่จะทำให้คนส่วนใหญ่ใช้งาน หากคุณกำลังมองหาบางสิ่งที่ทรงพลังBoost Graph Libraryเป็นสิ่งที่สำคัญอย่างยิ่งในสิ่งที่สามารถใช้ไลบรารีต้นไม้ได้

นี่คือการใช้งานทรีทั่วไปอื่น ๆ :


5
"... ไม่มีทางที่ดีที่จะทำให้ทุกคนพอใจ ... " ยกเว้นว่าตั้งแต่ stl :: map, stl :: multimap และ stl :: set ขึ้นอยู่กับ stb ของ rb_tree มันควรจะตอบสนองได้หลาย ๆ กรณีเช่นเดียวกับประเภทพื้นฐาน .
Catskul

44
เมื่อพิจารณาถึงวิธีการดึงลูกของโหนด a std::mapฉันจะไม่เรียกภาชนะต้นไม้เหล่านั้น ภาชนะเหล่านี้เป็นที่เชื่อมโยงที่ใช้กันทั่วไปเป็นต้นไม้ แตกต่างใหญ่
Mooing Duck

2
ฉันเห็นด้วยกับ Mooing Duck คุณจะใช้การค้นหาแบบกว้างเป็นครั้งแรกในแผนที่ std :: ได้อย่างไร มันจะมีราคาแพงมาก
มาร์โก A.

1
ฉันเริ่มใช้ tree.hh ของ Kasper Peeters แต่หลังจากตรวจสอบใบอนุญาตสำหรับ GPLv3 หรือรุ่น GPL อื่น ๆ มันจะปนเปื้อนซอฟต์แวร์เชิงพาณิชย์ของเรา ฉันอยากจะแนะนำให้ดูที่ treetree ที่ให้ไว้ในความคิดเห็นโดย @hplbsh หากคุณต้องการโครงสร้างเพื่อวัตถุประสงค์ทางการค้า
Jake88

3
ข้อกำหนดเฉพาะที่หลากหลายเกี่ยวกับต้นไม้เป็นข้อโต้แย้งว่ามีต้นไม้ประเภทต่าง ๆ และไม่มีเลย
André

50

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


12
ฉันไม่คิดว่าเขากำลังพูดถึงการใช้งานคอนเทนเนอร์เขาพูดถึงต้นไม้จริงในคอนเทนเนอร์
Mooing Duck

3
@MooingDuck ฉันคิดว่า wilhelmtell แปลว่าไลบรารีมาตรฐาน C ++ ไม่ได้กำหนดคอนเทนเนอร์ตามโครงสร้างข้อมูลพื้นฐาน มันกำหนดเฉพาะคอนเทนเนอร์โดยส่วนต่อประสานและคุณลักษณะที่สังเกตได้เช่นประสิทธิภาพของซีมโทติค เมื่อคุณคิดเกี่ยวกับมันต้นไม้ไม่ได้เป็นภาชนะ (อย่างที่เรารู้) จริง ๆ พวกเขาไม่ได้มี AA ตรงไปข้างหน้าend()และbegin()ที่คุณสามารถทำซ้ำผ่านองค์ประกอบทั้งหมดและอื่น ๆ
Jordan Melo

7
@JordanMelo: ไร้สาระในทุกจุด มันเป็นสิ่งที่มีวัตถุ มันค่อนข้างง่ายที่จะออกแบบให้มีตัววนซ้ำเริ่มต้น () และสิ้นสุด () และแบบสองทิศทางเพื่อทำซ้ำ แต่ละภาชนะมีลักษณะแตกต่างกัน มันจะมีประโยชน์ถ้าใครสามารถมีลักษณะต้นไม้ ควรสวยง่าย
Mooing Duck

ดังนั้นหนึ่งต้องการมีคอนเทนเนอร์ที่ให้การค้นหาที่รวดเร็วสำหรับโหนดลูกและพาเรนต์และข้อกำหนดหน่วยความจำที่สมเหตุสมผล
doc

@JordanMelo: จากมุมมองนั้นเช่นอะแดปเตอร์เช่นคิวสแต็คหรือลำดับความสำคัญจะไม่ได้อยู่ใน STL (พวกเขายังไม่มีbegin()และend()) และจำไว้ว่าคิวลำดับความสำคัญมักจะเป็นกองซึ่งอย่างน้อยก็ในทางทฤษฎีคือต้นไม้ (แม้ว่าการใช้งานจริง) ดังนั้นแม้ว่าคุณจะนำต้นไม้มาใช้เป็นอะแดปเตอร์โดยใช้โครงสร้างข้อมูลพื้นฐานที่แตกต่างกันบางอย่างก็จะมีสิทธิ์ที่จะรวมอยู่ใน STL
andreee

48

"ฉันต้องการเก็บลำดับชั้นของวัตถุเป็นต้นไม้"

C ++ 11 มาถึงแล้วและพวกเขาก็ยังไม่เห็นความต้องการที่จะให้std::treeแม้ว่าความคิดจะเกิดขึ้นก็ตาม (ดูที่นี่ ) บางทีเหตุผลที่พวกเขาไม่ได้เพิ่มสิ่งนี้อาจเป็นเรื่องง่ายที่จะสร้างของคุณเองบนบรรจุภัณฑ์ที่มีอยู่แล้ว ตัวอย่างเช่น...

template< typename T >
struct tree_node
   {
   T t;
   std::vector<tree_node> children;
   };

การสำรวจเส้นทางอย่างง่ายจะใช้การเรียกซ้ำ ...

template< typename T >
void tree_node<T>::walk_depth_first() const
   {
   cout<<t;
   for ( auto & n: children ) n.walk_depth_first();
   }

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


2
หากโครงการสามารถอนุญาตให้เด็ก ๆ ของ tree_node ที่จะเรียงลำดับจากนั้นใช้ std :: set <> แทน std :: vector <> แล้วเพิ่มตัวดำเนินการ <() ไปยังวัตถุ tree_node จะดีขึ้นอย่างมาก ประสิทธิภาพ 'ค้นหา' ของวัตถุที่เหมือน 'T'
J Jorgenson

4
ปรากฎว่าพวกเขาขี้เกียจและทำให้ตัวอย่างแรกของคุณไม่ได้กำหนดพฤติกรรม
user541686

2
@Mehrdad: ในที่สุดผมก็ตัดสินใจที่จะขอดูรายละเอียดที่อยู่เบื้องหลังความคิดเห็นของคุณที่นี่
โนเบิล

many of the algorithms simply don't make any sense for a hierarchy. เรื่องของการตีความ ลองนึกภาพโครงสร้างของผู้ใช้งานสแต็คโอเวอร์โฟลว์และในแต่ละปีคุณต้องการให้ผู้ที่มีคะแนนชื่อเสียงสูงขึ้นเพื่อเป็นเจ้านายให้กับผู้ที่มีคะแนนชื่อเสียงต่ำกว่า จึงให้ BFS iterator std::sort(tree.begin(), tree.end())และการเปรียบเทียบความเหมาะสมทุกปีคุณเรียกเพียง
doc

ด้วยโทเค็นเดียวกันคุณสามารถสร้างแผนผังการเชื่อมโยง (เพื่อจำลองเร็กคอร์ดคีย์ - ค่าที่ไม่มีโครงสร้างเช่น JSON เป็นต้น) โดยการแทนที่vectorด้วยmapในตัวอย่างด้านบน สำหรับการสนับสนุนโครงสร้างแบบ JSON อย่างสมบูรณ์คุณสามารถใช้variantเพื่อกำหนดโหนด
สูงศักดิ์

43

หากคุณกำลังมองหาการนำ RB-tree มาใช้stl_tree.hก็อาจเหมาะสมสำหรับคุณเช่นกัน


14
น่าแปลกที่นี่เป็นคำตอบเดียวที่จริง ๆ แล้วตอบคำถามเดิม
Catskul

12
เมื่อพิจารณาว่าเขาต้องการ "Heiarchy" ดูเหมือนว่าจะถือว่าทุกอย่างที่มี "การปรับสมดุล" เป็นคำตอบที่ผิด
Mooing Duck

11
"นี่เป็นไฟล์ส่วนหัวภายในซึ่งรวมอยู่ในส่วนหัวของห้องสมุดอื่น ๆ คุณไม่ควรใช้งานโดยตรง"
ด่าน

3
@Dan: การคัดลอกไม่ได้เป็นการใช้โดยตรง
einpoklum

12

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


13
มันมักจะใช้ต้นไม้สีแดงดำ (ไม่จำเป็นต้องทำ)
Martin York

1
GCC ใช้แผนผังเพื่อสร้างแผนที่ ทุกคนต้องการดูไดเรกทอรี VC ของพวกเขาเพื่อดูว่าไมโครซอฟท์ใช้อะไร?
JJ

// คลาสต้นไม้สีแดงดำออกแบบมาเพื่อใช้ในการติดตั้ง STL // คอนเทนเนอร์ที่เชื่อมโยง (ชุดมัลติเซ็ตแผนที่และ Multimap) คว้าสิ่งนั้นจากไฟล์ stl_tree.h ของฉัน
JJ

@JJ อย่างน้อยก็ใน Studio 2010 จะใช้ภายในระดับที่กำหนดไว้ในordered red-black tree of {key, mapped} values, unique keys <xtree>ไม่สามารถเข้าถึงเวอร์ชันที่ทันสมัยกว่าได้ในขณะนี้
Justin Time - Reinstate Monica

8

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

โดยทั่วไปถ้ามีการทำงานห้องสมุดพื้นฐานที่คุณต้องการที่ไม่ได้อยู่ใน STL การแก้ไขคือการดูที่BOOST

มิฉะนั้นมีพวงของห้องสมุด ออก มีขึ้นอยู่กับความต้องการของต้นไม้ของคุณ


6

คอนเทนเนอร์ STL ทั้งหมดถูกแสดงภายนอกเป็น "ลำดับ" พร้อมกับกลไกการวนซ้ำหนึ่งรายการ ต้นไม้ไม่ทำตามสำนวนนี้


7
โครงสร้างข้อมูลแบบต้นไม้สามารถให้การสั่งซื้อล่วงหน้า, inorder หรือ Traversal ผ่านทางตัววนซ้ำ อันที่จริงนี่คือสิ่งที่ std :: map ทำ
Andrew Tomazos

3
ใช่และไม่ใช่ ... ขึ้นอยู่กับความหมายของ "ต้นไม้" std::mapมีการใช้งานภายในเป็น btree แต่ภายนอกจะปรากฏเป็นลำดับที่เรียงลำดับของ PAIRS เมื่อพิจารณาถึงองค์ประกอบใดก็ตามที่คุณสามารถถามได้ว่าใครคือใครมาก่อน โครงสร้างต้นไม้ทั่วไปที่มีองค์ประกอบซึ่งแต่ละอย่างมีอื่น ๆ ไม่ได้กำหนดการเรียงลำดับหรือทิศทางใด ๆ คุณสามารถกำหนดตัววนซ้ำที่เดินโครงสร้างต้นไม้ได้หลายวิธี (sallow | deep first | last ... ) แต่เมื่อคุณทำแล้วstd::treeคอนเทนเนอร์ต้องส่งคืนหนึ่งในนั้นจากbeginฟังก์ชัน และไม่มีเหตุผลที่ชัดเจนว่าจะส่งคืนอย่างใดอย่างหนึ่ง
Emilio Garavaglia

4
แผนที่ std :: โดยทั่วไปจะแสดงด้วยแผนภูมิการค้นหาแบบไบนารีที่สมดุลไม่ใช่แบบต้นไม้ B อาร์กิวเมนต์เดียวกับที่คุณทำสามารถนำไปใช้กับ std :: unordered_set แต่ก็ไม่มีความเป็นธรรมชาติ แต่ยังแสดงการเริ่มต้นและสิ้นสุดตัววนซ้ำ ความต้องการของการเริ่มต้นและการสิ้นสุดคือการที่มันวนซ้ำองค์ประกอบทั้งหมดตามลำดับที่กำหนดไว้บางอย่างไม่ใช่ว่าจะต้องเป็นไปตามธรรมชาติ การสั่งซื้อล่วงหน้าเป็นคำสั่งวนซ้ำที่ถูกต้องสมบูรณ์แบบสำหรับต้นไม้
Andrew Tomazos

4
ความหมายของคำตอบของคุณคือไม่มีโครงสร้างข้อมูล stl n-tree เนื่องจากไม่มีอินเทอร์เฟซ "ลำดับ" สิ่งนี้ไม่ถูกต้อง
Andrew Tomazos

3
@EmiloGaravaglia: ตามหลักฐานstd::unordered_setซึ่งไม่มี "วิธีที่ไม่ซ้ำ" ในการวนสมาชิก (ในความเป็นจริงคำสั่งการทำซ้ำนั้นเป็นการหลอกแบบสุ่มและการใช้งานที่กำหนดไว้) แต่ก็ยังคงเป็นคอนเทนเนอร์ stl - นี่ทำให้จุดของคุณไม่ดี การวนซ้ำองค์ประกอบแต่ละรายการในคอนเทนเนอร์ยังคงเป็นการดำเนินการที่มีประโยชน์แม้ว่าจะไม่มีการกำหนดลำดับ
Andrew Tomazos

4

เนื่องจาก STL ไม่ใช่ไลบรารี "ทุกอย่าง" มันมีโครงสร้างขั้นต่ำที่จำเป็นในการสร้างสิ่งต่าง ๆ


13
ต้นไม้ไบนารีเป็นฟังก์ชั่นพื้นฐานอย่างยิ่งและที่จริงแล้วพื้นฐานมากกว่าตู้คอนเทนเนอร์อื่น ๆ ตั้งแต่ประเภทเช่น std :: map, std :: multimap และ stl :: set เนื่องจากประเภทเหล่านั้นยึดตามประเภทนั้นคุณจึงคาดว่าจะได้รับการเปิดเผยประเภทที่ซ่อนอยู่
Catskul

2
ฉันไม่คิดว่า OP ขอต้นไม้ไบนารีเขาขอต้นไม้เพื่อจัดลำดับชั้น
Mooing Duck

ไม่เพียงแค่นั้นการเพิ่มทรี "container" ลงใน STL จะมีความหมายที่จะเพิ่มแนวคิดใหม่ ๆ มากมายเช่น tree navigator (generalizing Iterator)
alfC

5
"โครงสร้างขั้นต่ำในการสร้างสิ่งต่าง ๆ " เป็นคำให้การอัตนัย คุณสามารถสร้างสิ่งต่าง ๆ ด้วยคอนเซ็ปต์ C ++ แบบดิบ ๆ ได้ดังนั้นฉันจึงเดาได้ว่าค่าต่ำสุดที่แท้จริงคือไม่มี STL เลย
doc


3

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

ตัวอย่างเช่น:

template <typename T>
struct TreeNode
{
  T* DATA ; // data of type T to be stored at this TreeNode

  vector< TreeNode<T>* > children ;

  // insertion logic for if an insert is asked of me.
  // may append to children, or may pass off to one of the child nodes
  void insert( T* newData ) ;

} ;

template <typename T>
struct Tree
{
  TreeNode<T>* root;

  // TREE LEVEL functions
  void clear() { delete root ; root=0; }

  void insert( T* data ) { if(root)root->insert(data); } 
} ;

7
นั่นเป็นจำนวนมากของการเป็นเจ้าของพอยน์เตอร์ดิบที่คุณมีซึ่งหลายคนไม่จำเป็นต้องเป็นพอยน์เตอร์เลย
Mooing Duck

แนะนำให้คุณถอนคำตอบนี้ คลาส TreeNode เป็นส่วนหนึ่งของการใช้งานต้นไม้
einpoklum

3

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

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

template<class A>
struct unordered_tree : std::set<unordered_tree>, A
{};

template<class A>
struct b_tree : std::vector<b_tree>, A
{};

template<class A>
struct planar_tree : std::list<planar_tree>, A
{};

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

ต้นไม้มีบทบาทสำคัญในโครงสร้างทางคณิตศาสตร์จำนวนมาก (ดูเอกสารคลาสสิกของ Butcher, Grossman และ Larsen; นอกจากนี้เอกสารของ Connes และ Kriemer สำหรับตัวอย่างของพวกเขาสามารถเข้าร่วมและวิธีที่พวกเขาจะใช้ในการแจกแจง) มันไม่ถูกต้องที่จะคิดว่าบทบาทของพวกเขาเป็นเพียงเพื่ออำนวยความสะดวกในการดำเนินงานอื่น ๆ ค่อนข้างพวกเขาอำนวยความสะดวกในงานเหล่านั้นเพราะบทบาทพื้นฐานของพวกเขาเป็นโครงสร้างข้อมูล

อย่างไรก็ตามนอกเหนือจากต้นไม้แล้วยังมี "ต้นไม้ร่วม" ด้วย; ต้นไม้ด้านบนทั้งหมดมีคุณสมบัติที่ถ้าคุณลบรูทคุณจะลบทุกอย่าง

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

template<class TREE>
struct node_iterator : std::stack<TREE::iterator>{
operator*() {return *back();}
...};

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

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

ฉันสำหรับหนึ่งจะยินดีถ้าสิ่งนี้ในรูปแบบที่ดีหาทางลงในมาตรฐาน


0

การอ่านคำตอบในที่นี้เหตุผลที่มีชื่อทั่วไปคือไม่มีใครสามารถย้ำผ่านทรีหรือทรีไม่ถือว่าอินเตอร์เฟสคล้ายกับคอนเทนเนอร์ STL อื่นและไม่สามารถใช้อัลกอริธึม STL กับโครงสร้างทรีเช่นนั้นได้

ในใจฉันพยายามออกแบบโครงสร้างข้อมูลแบบต้นไม้ของตัวเองซึ่งจะให้อินเทอร์เฟซแบบ STL และสามารถใช้งานได้กับ algorthims STL ที่มีอยู่ให้มากที่สุด

ความคิดของฉันคือต้นไม้จะต้องขึ้นอยู่กับภาชนะ STL ที่มีอยู่และต้องไม่ซ่อนภาชนะเพื่อที่จะสามารถใช้กับอัลกอริทึม STL ได้

คุณลักษณะที่สำคัญอื่น ๆ ที่ทรีต้องมีคือตัววนซ้ำแบบสำรวจภายใน

นี่คือสิ่งที่ฉันสามารถมากับ: https://github.com/igagis/utki/blob/master/src/utki/tree.hpp

และนี่คือการทดสอบ: https://github.com/igagis/utki/blob/master/tests/tree/tests.cpp


-9

คอนเทนเนอร์ STL ทั้งหมดสามารถใช้กับตัววนซ้ำได้ คุณไม่สามารถมีตัววนซ้ำต้นไม้เนื่องจากคุณไม่มีวิธี '' ถูกต้อง '' ผ่านต้นไม้


3
แต่คุณสามารถพูดได้ว่า BFS หรือ DFS เป็นวิธีที่ถูกต้อง หรือสนับสนุนทั้งคู่ หรืออื่น ๆ ที่คุณสามารถจินตนาการ Jut บอกผู้ใช้ว่ามันคืออะไร
tomas789

2
ใน std :: map มี tree iterator
อึ๊ง

1
ต้นไม้สามารถกำหนดชนิดตัววนซ้ำแบบกำหนดเองของมันเองที่จะข้ามโหนดทั้งหมดตามลำดับจาก "สุดขั้ว" ไปยังอีกโหนดหนึ่ง (เช่นสำหรับต้นไม้ไบนารีใด ๆ ที่มีเส้นทาง 0 & 1 มันสามารถเสนอตัววนรอบจาก "all 0s" เป็น "all 1s "และ iterator กลับที่ไม่ตรงข้ามสำหรับต้นไม้ที่มีความลึกของ 3 และโหนดเริ่มต้นที่sยกตัวอย่างเช่นมันจะย้ำกว่าโหนดเป็นs000, s00, s001, s0, s010, s01, s011, s, s100, s10, s101, s1, s110, s11, s111(" ซ้ายสุด" กับ 'ขวาสุด'); มันยังสามารถใช้รูปแบบเชิงลึกสำรวจเส้นทาง ( s, s0, s1, s00, s01, s10, s11,
เวลาจัสติน - Reinstate โมนิกา

เป็นต้น) หรือรูปแบบอื่น ๆ ตราบใดที่มันวนซ้ำทุกโหนดในลักษณะที่แต่ละอันจะผ่านเพียงครั้งเดียว
Justin Time - Reinstate Monica

1
@doc เป็นจุดที่ดีมาก ฉันคิดว่าstd::unordered_setเป็น "ทำ" ลำดับเนื่องจากเราไม่รู้วิธีที่ดีกว่าในการวนซ้ำองค์ประกอบอื่น ๆ นอกเหนือจากวิธีการตามอำเภอใจบางอย่าง ฉันคิดว่ามันเป็นกรณีตรงข้ามของต้นไม้: การทำซ้ำซ้ำไปซ้ำมาunordered_setนั้นไม่ได้ระบุไว้ในทางทฤษฎีว่า "ไม่มีทาง" ในการกำหนดการทำซ้ำอื่นนอกเหนือจาก "สุ่ม" ในกรณีของต้นไม้มีวิธี "ดี" (ไม่ใช่แบบสุ่ม) มากมาย แต่จุดของคุณถูกต้องอีกครั้ง
alfC
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.