เป็นTrieและRadix Trieโครงสร้างข้อมูลสิ่งเดียวกัน
ถ้าไม่เหมือนกันความหมายของ radix trie (AKA Patricia trie) คืออะไร?
เป็นTrieและRadix Trieโครงสร้างข้อมูลสิ่งเดียวกัน
ถ้าไม่เหมือนกันความหมายของ radix trie (AKA Patricia trie) คืออะไร?
radix trie
Radix tree
ยิ่งไปกว่านั้นคำว่า "Radix tree" ยังใช้กันอย่างแพร่หลายในวรรณคดี หากมีสิ่งใดที่การโทรพยายาม "ต้นไม้นำหน้า" จะทำให้เข้าใจได้มากกว่านี้ ท้ายที่สุดพวกเขาทั้งหมดเป็นโครงสร้างข้อมูลแบบต้นไม้
radix = 2
ซึ่งหมายความว่าคุณสำรวจต้นไม้โดยการค้นหาlog2(radix)=1
บิตของสตริงอินพุตในแต่ละครั้ง
คำตอบ:
ต้นไม้รัศมีเป็นเวอร์ชันบีบอัดของ Trie ใน Trie แต่ละขอบคุณเขียนตัวอักษรตัวเดียวในขณะที่อยู่ในต้นไม้ PATRICIA (หรือต้นรัศมี) คุณเก็บทั้งคำ
ตอนนี้ถือว่าคุณมีคำhello
, และhat
have
หากต้องการเก็บไว้ในTrieจะมีลักษณะดังนี้:
e - l - l - o
/
h - a - t
\
v - e
และคุณต้องมีเก้าโหนด ฉันวางตัวอักษรไว้ในโหนด แต่จริงๆแล้วมันติดป้ายกำกับที่ขอบ
ในต้นรัศมีคุณจะมี:
*
/
(ello)
/
* - h - * -(a) - * - (t) - *
\
(ve)
\
*
และคุณต้องการเพียงห้าโหนด ในภาพโหนดด้านบนคือเครื่องหมายดอกจัน
ดังนั้นโดยรวมแล้วต้นไม้ radix ใช้หน่วยความจำน้อยลงแต่ใช้งานได้ยากกว่า มิฉะนั้นกรณีการใช้งานของทั้งสองจะเหมือนกันมาก
คำถามของฉันคือโครงสร้างข้อมูลTrieและRadix Trieเป็นสิ่งเดียวกันหรือไม่?
ในระยะสั้นไม่ หมวดหมู่Radix Trieอธิบายถึงหมวดหมู่เฉพาะของTrieแต่นั่นไม่ได้หมายความว่าการพยายามทั้งหมดจะเป็นการพยายามด้วย radix
ถ้า [ไม่] เหมือนกัน Radix trie (aka Patricia Trie) มีความหมายว่าอย่างไร?
ฉันคิดว่าคุณตั้งใจจะเขียนไม่ได้อยู่ในคำถามของคุณดังนั้นการแก้ไขของฉัน
ในทำนองเดียวกัน PATRICIA หมายถึงประเภทของ radix trie ที่เฉพาะเจาะจง แต่ไม่ใช่การพยายามใช้ radix ทั้งหมดที่ PATRICIA พยายาม
"Trie" อธิบายโครงสร้างข้อมูลแบบทรีที่เหมาะสำหรับใช้เป็นอาร์เรย์เชื่อมโยงโดยที่กิ่งก้านหรือขอบสอดคล้องกับส่วนต่างๆของคีย์ คำจำกัดความของชิ้นส่วนค่อนข้างคลุมเครือที่นี่เนื่องจากการใช้งานที่แตกต่างกันจะใช้ความยาวบิตที่แตกต่างกันเพื่อให้สอดคล้องกับขอบ ตัวอย่างเช่นสามเหลี่ยมไบนารีมีสองขอบต่อโหนดที่สอดคล้องกับ 0 หรือ 1 ในขณะที่สามเหลี่ยม 16 ทางมีสิบหกขอบต่อโหนดที่สอดคล้องกับสี่บิต (หรือเลขฐานสิบหก: 0x0 ถึง 0xf)
แผนภาพนี้ดึงมาจาก Wikipedia ดูเหมือนว่าจะแสดงให้เห็นถึงสามคนที่มีการแทรก (อย่างน้อย) ปุ่ม 'A', 'to', 'tea', 'ted', 'ten' และ 'inn':
หาก trie นี้ใช้เก็บรายการสำหรับคีย์ 't', 'te', 'i' หรือ 'in' จะต้องมีข้อมูลเพิ่มเติมที่แต่ละโหนดเพื่อแยกความแตกต่างระหว่างโหนดว่างและโหนดที่มีค่าจริง
"Radix trie" ดูเหมือนจะอธิบายรูปแบบของ trie ที่ควบแน่นส่วนของคำนำหน้าทั่วไปตามที่ Ivaylo Strandjev อธิบายไว้ในคำตอบของเขา พิจารณาว่ารูปสามเหลี่ยม 256 ทิศทางซึ่งทำดัชนีคีย์ "ยิ้ม" "ยิ้ม" "ยิ้ม" และ "ยิ้ม" โดยใช้การกำหนดแบบคงที่ต่อไปนี้:
root['s']['m']['i']['l']['e']['\0'] = smile_item;
root['s']['m']['i']['l']['e']['d']['\0'] = smiled_item;
root['s']['m']['i']['l']['e']['s']['\0'] = smiles_item;
root['s']['m']['i']['l']['i']['n']['g']['\0'] = smiling_item;
ตัวห้อยแต่ละตัวเข้าถึงโหนดภายใน นั่นหมายถึงการดึงข้อมูลsmile_item
คุณต้องเข้าถึงเจ็ดโหนด แปดโหนดเข้าถึงตรงตามลักษณะที่smiled_item
และและเก้าsmiles_item
smiling_item
สำหรับสี่รายการนี้มีทั้งหมดสิบสี่โหนด อย่างไรก็ตามพวกเขาทั้งหมดมีสี่ไบต์แรก (ตรงกับสี่โหนดแรก) เหมือนกันอย่างไรก็ตาม ด้วยการย่อขนาดสี่ไบต์เหล่านี้เพื่อสร้างroot
ที่สอดคล้องกันการ['s']['m']['i']['l']
เข้าถึงโหนดสี่โหนดได้รับการปรับให้เหมาะสม นั่นหมายถึงหน่วยความจำน้อยลงและเข้าถึงโหนดน้อยลงซึ่งเป็นข้อบ่งชี้ที่ดีมาก การเพิ่มประสิทธิภาพสามารถใช้ซ้ำได้เพื่อลดความจำเป็นในการเข้าถึงไบต์ส่วนต่อท้ายที่ไม่จำเป็น ในที่สุดคุณก็มาถึงจุดที่คุณเปรียบเทียบความแตกต่างระหว่างคีย์ค้นหาและคีย์ที่จัดทำดัชนีในตำแหน่งที่จัดทำดัชนีโดย Trie เท่านั้น. นี่คือ radix trie
root = smil_dummy;
root['e'] = smile_item;
root['e']['d'] = smiled_item;
root['e']['s'] = smiles_item;
root['i'] = smiling_item;
ในการดึงข้อมูลแต่ละโหนดจำเป็นต้องมีตำแหน่ง ด้วยคีย์การค้นหาของ "รอยยิ้ม" และroot.position
4 เราเข้าถึงซึ่งเกิดขึ้นเป็นroot["smiles"[4]]
เราเก็บนี้ในตัวแปรที่เรียกว่าroot['e']
คือ 5 ซึ่งเป็นที่ตั้งของความแตกต่างระหว่างและเพื่อให้เข้าถึงต่อไปจะเป็น สิ่งนี้นำเราไปสู่และจุดสิ้นสุดของสตริงของเรา การค้นหาของเราได้ยุติลงและมีการดึงข้อมูลโดยมีการเข้าถึงโหนดเพียงสามโหนดแทนที่จะเป็นแปดcurrent
current.position
"smiled"
"smiles"
root["smiles"[5]]
smiles_item
PATRICIA trie เป็นตัวแปรของ radix ที่พยายามซึ่งควรเป็นn
โหนดที่ใช้บรรจุn
รายการเท่านั้น ในสมุฎฐาน Trie pseudocode แสดงให้เห็นถึงหยาบข้างต้นของเรามีห้าโหนดทั้งหมด: root
(ซึ่งเป็นโหนด nullary มันไม่มีค่าจริง) root['e']
, root['e']['d']
, และroot['e']['s']
root['i']
ใน PATRICIA Trie ควรมีเพียงสี่ตัว มาดูกันว่าคำนำหน้าเหล่านี้อาจแตกต่างกันอย่างไรโดยดูจากไบนารีเนื่องจาก PATRICIA เป็นอัลกอริทึมไบนารี
smile: 0111 0011 0110 1101 0110 1001 0110 1100 0110 0101 0000 0000 0000 0000
smiled: 0111 0011 0110 1101 0110 1001 0110 1100 0110 0101 0110 0100 0000 0000
smiles: 0111 0011 0110 1101 0110 1001 0110 1100 0110 0101 0111 0011 0000 0000
smiling: 0111 0011 0110 1101 0110 1001 0110 1100 0110 1001 0110 1110 0110 0111 ...
ให้เราพิจารณาว่ามีการเพิ่มโหนดตามลำดับที่แสดงไว้ข้างต้น smile_item
เป็นรากของต้นไม้นี้ ความแตกต่างที่เป็นตัวหนาเพื่อให้มองเห็นได้ง่ายขึ้นเล็กน้อยอยู่ในไบต์สุดท้าย"smile"
ที่บิต 36 จนถึงจุดนี้โหนดทั้งหมดของเรามีคำนำหน้าเหมือนกัน smiled_node
อยู่ที่smile_node[0]
. ความแตกต่างระหว่าง"smiled"
และ"smiles"
เกิดขึ้นในบิต 43 ที่"smiles"
มี '1' บิตเพื่อให้เป็นsmiled_node[1]
smiles_node
แทนที่จะใช้NULL
เป็นสาขาและ / หรือข้อมูลภายในเพิ่มเติมเพื่อแสดงถึงเมื่อการค้นหาสิ้นสุดลงกิ่งก้านจะเชื่อมโยงข้อมูลต้นไม้กลับไปที่ใดที่หนึ่งดังนั้นการค้นหาจะสิ้นสุดลงเมื่อค่าชดเชยในการทดสอบลดลงแทนที่จะเพิ่มขึ้น นี่คือแผนภาพง่ายๆของต้นไม้ดังกล่าว(แม้ว่า PATRICIA จะเป็นกราฟวัฏจักรมากกว่าต้นไม้อย่างที่คุณเห็น) ซึ่งรวมอยู่ในหนังสือของ Sedgewick ที่กล่าวถึงด้านล่าง:
อัลกอริธึม PATRICIA ที่ซับซ้อนมากขึ้นซึ่งเกี่ยวข้องกับคีย์ของความยาวตัวแปรเป็นไปได้แม้ว่าคุณสมบัติทางเทคนิคบางอย่างของ PATRICIA จะสูญหายไปในกระบวนการ (กล่าวคือโหนดใด ๆ มีคำนำหน้าร่วมกับโหนดก่อนหน้านั้น):
การแตกกิ่งก้านเช่นนี้มีประโยชน์หลายประการ: ทุกโหนดมีค่า ซึ่งรวมถึงราก เป็นผลให้ความยาวและความซับซ้อนของโค้ดสั้นลงมากและอาจเร็วกว่าเล็กน้อยในความเป็นจริง อย่างน้อยหนึ่งสาขาและสาขาส่วนใหญ่k
( k
จำนวนบิตในคีย์การค้นหาอยู่ที่ใด) จะถูกติดตามเพื่อค้นหารายการ โหนดมีขนาดเล็กเนื่องจากเก็บเพียงสองสาขาแต่ละแห่งซึ่งทำให้ค่อนข้างเหมาะสมสำหรับการเพิ่มประสิทธิภาพตำแหน่งแคช คุณสมบัติเหล่านี้ทำให้ PATRICIA อัลกอริทึมที่ชื่นชอบจนถึงตอนนี้ ...
ฉันจะตัดคำอธิบายนี้ให้สั้นลงเพื่อลดความรุนแรงของโรคข้ออักเสบที่กำลังจะเกิดขึ้น แต่ถ้าคุณต้องการทราบข้อมูลเพิ่มเติมเกี่ยวกับ PATRICIA คุณสามารถอ่านหนังสือเช่น "The Art of Computer Programming, Volume 3" โดย Donald Knuth หรือ "อัลกอริทึมในภาษา {your-favorite-language} ส่วนที่ 1-4" โดย Sedgewick
TRIE:
เราสามารถมีรูปแบบการค้นหาที่แทนที่จะเปรียบเทียบคีย์การค้นหาทั้งหมดกับคีย์ที่มีอยู่ทั้งหมด (เช่นแฮชสกีม) เรายังสามารถเปรียบเทียบอักขระแต่ละตัวของคีย์ค้นหาได้ ตามแนวคิดนี้เราสามารถสร้างโครงสร้าง (ดังที่แสดงด้านล่าง) ซึ่งมีคีย์ที่มีอยู่สามปุ่มคือ " พ่อ " " ตบเบา ๆ " และ " รถแท็กซี่ "
[root]
...// | \\...
| \
c d
| \
[*] [*]
...//|\. ./|\\... Fig-I
a a
/ /
[*] [*]
...//|\.. ../|\\...
/ / \
B b d
/ / \
[] [] []
(cab) (dab) (dad)
โดยพื้นฐานแล้วนี่คือต้นไม้ M-ary ที่มีโหนดภายในแสดงเป็น [*] และโหนดใบไม้แทนด้วย [] โครงสร้างแบบนี้จะเรียกว่าเป็นTrie การตัดสินใจแยกย่อยในแต่ละโหนดสามารถคงไว้เท่ากับจำนวนสัญลักษณ์เฉพาะของตัวอักษรพูด R สำหรับตัวอักษรภาษาอังกฤษตัวพิมพ์เล็ก az, R = 26; สำหรับตัวอักษร ASCII แบบขยาย R = 256 และสำหรับเลขฐานสอง / สตริง R = 2
Compact TRIE:
โดยทั่วไปแล้วโหนดในTrieจะใช้อาร์เรย์ที่มีขนาด = R จึงทำให้เสียหน่วยความจำเมื่อแต่ละโหนดมีขอบน้อยลง เพื่อหลีกเลี่ยงความกังวลเรื่องความทรงจำจึงมีการเสนอข้อเสนอต่างๆ ขึ้นอยู่กับรูปแบบเหล่านั้นTrieนอกจากนี้ยังมีชื่อเป็น“ ขนาดกะทัดรัด Trie ” และ“ Trie บีบอัด ” ในขณะที่ระบบการตั้งชื่อที่สอดคล้องกันนั้นหาได้ยาก แต่รุ่นที่พบมากที่สุดของ Compact Trieนั้นถูกสร้างขึ้นโดยการจัดกลุ่มขอบทั้งหมดเมื่อโหนดมีขอบเดียว โดยใช้แนวคิดนี้ด้านบน (รูป-I) Trieด้วยปุ่ม“พ่อ”,“ตบเบา ๆ” และ“รถแท็กซี่” สามารถใช้แบบฟอร์มด้านล่าง
[root]
...// | \\...
| \
cab da
| \
[ ] [*] Fig-II
./|\\...
| \
b d
| \
[] []
โปรดทราบว่า 'c', 'a' และ 'b' แต่ละอันเป็นขอบ แต่เพียงผู้เดียวสำหรับโหนดแม่ที่เกี่ยวข้องดังนั้นจึงรวมกันเป็น "cab" แบบขอบเดียว ในทำนองเดียวกัน 'd' และ a 'จะถูกรวมเข้าด้วยกันเป็นขอบเดียวที่มีป้ายกำกับว่า "da"
Radix Trie:
คำว่าradixในทางคณิตศาสตร์หมายถึงฐานของระบบตัวเลขและโดยพื้นฐานแล้วจะระบุจำนวนสัญลักษณ์เฉพาะที่จำเป็นในการแสดงจำนวนใด ๆ ในระบบนั้น ตัวอย่างเช่นระบบฐานสิบคือเลขฐานสิบและระบบเลขฐานสองคือเลขสอง การใช้แนวคิดที่คล้ายกันนี้เมื่อเราสนใจในการกำหนดลักษณะโครงสร้างข้อมูลหรืออัลกอริทึมด้วยจำนวนสัญลักษณ์เฉพาะของระบบการแทนค่าที่อยู่เบื้องหลังเราจะติดแท็กแนวคิดด้วยคำว่า "radix" ตัวอย่างเช่น "radix sort" สำหรับอัลกอริทึมการจัดเรียงบางประเภท ในบรรทัดเดียวกันของตรรกะตัวแปรทั้งหมดของtrieซึ่งมีลักษณะเฉพาะ (เช่นความลึกความต้องการหน่วยความจำรันไทม์การค้นหาพลาด / การตี ฯลฯ ) ขึ้นอยู่กับรัศมีของตัวอักษรที่อยู่ข้างใต้เราอาจเรียกพวกมันว่า radix ยกตัวอย่างเช่นการยกเลิกการบดอัดเช่นเดียวกับการบดอัดTrieเมื่อใช้ตัวอักษร az, เราสามารถเรียกมันว่า Radix 26 Trie Trie ใด ๆ ที่ใช้เพียงสองสัญลักษณ์ (ตามธรรมเนียม '0' และ '1') สามารถเรียกได้ว่ากี่ 2 Trie อย่างไรก็ตามวรรณกรรมจำนวนมากได้ จำกัด การใช้คำว่า“ Radix Trie” เฉพาะกับTrie ที่ถูกบดอัดเท่านั้น
Prelude to PATRICIA Tree / Trie:
เป็นเรื่องน่าสนใจที่จะสังเกตว่าแม้แต่สตริงที่เป็นคีย์ก็สามารถแสดงได้โดยใช้ตัวอักษรไบนารี หากเราถือว่าการเข้ารหัส ASCII คีย์“ พ่อ” สามารถเขียนในรูปแบบไบนารีได้โดยการเขียนการแทนค่าไบนารีของแต่ละอักขระตามลำดับพูดว่า“ 01100100 01100001 01100100 ” โดยการเขียนรูปแบบไบนารีของ 'd', 'a' และ 'd' ตามลำดับ การใช้แนวคิดนี้สามารถสร้างTrie (กับ Radix Two) ได้ ด้านล่างนี้เราอธิบายแนวคิดนี้โดยใช้สมมติฐานที่เรียบง่ายว่าตัวอักษร 'a', 'b', 'c' และ 'มาจากตัวอักษรขนาดเล็กแทนที่จะเป็น ASCII
หมายเหตุสำหรับ Fig-III: ตามที่กล่าวไว้เพื่อให้การพรรณนาเป็นเรื่องง่ายสมมติว่าตัวอักษรมีเพียง 4 ตัวอักษร {a, b, c, d} และการแทนค่าไบนารีที่เกี่ยวข้องคือ "00", "01", "10" และ “ 11” ตามลำดับ ด้วยสิ่งนี้คีย์สตริงของเรา "พ่อ" "ตบเบา ๆ " และ "แท็กซี่" จึงกลายเป็น "110011", "110001" และ "100001" ตามลำดับ Trie สำหรับสิ่งนี้จะเป็นดังที่แสดงด้านล่างใน Fig-III (บิตอ่านจากซ้ายไปขวาเช่นเดียวกับการอ่านสตริงจากซ้ายไปขวา)
[root]
\1
\
[*]
0/ \1
/ \
[*] [*]
0/ /
/ /0
[*] [*]
0/ /
/ /0
[*] [*]
0/ 0/ \1 Fig-III
/ / \
[*] [*] [*]
\1 \1 \1
\ \ \
[] [] []
(cab) (dab) (dad)
Patricia Trie / Tree:
ถ้าเรากระชับ binary trieข้างต้น(Fig-III) โดยใช้การบดอัดแบบขอบเดียวมันจะมีโหนดน้อยกว่าที่แสดงด้านบนมาก แต่โหนดจะยังคงมากกว่า 3 จำนวนคีย์ที่มีอยู่ . โดนัลด์อาร์มอร์ริสันพบ (ในปี 1968) เป็นวิธีใหม่ที่จะใช้ไบนารีTrieจะพรรณนาปุ่ม N โดยใช้เพียง N โหนดและเขาตั้งชื่อนี้โครงสร้างข้อมูลPATRICIA. โครงสร้าง Trie ของเขากำจัดขอบด้านเดียวเป็นหลัก (การแตกกิ่งทางเดียว) และในการทำเช่นนั้นเขายังได้กำจัดความคิดของโหนดสองชนิด - โหนดภายใน (ที่ไม่แสดงถึงคีย์ใด ๆ ) และโหนดใบไม้ (ซึ่งแสดงถึงคีย์) ซึ่งแตกต่างจากตรรกะการบดอัดที่อธิบายไว้ข้างต้น trie ของเขาใช้แนวคิดที่แตกต่างกันโดยที่แต่ละโหนดมีการบ่งชี้จำนวนบิตของคีย์ที่จะต้องข้ามเพื่อทำการตัดสินใจแยกส่วน อีกลักษณะหนึ่งของ PATRICIA Trie ของเขาคือไม่เก็บคีย์ - ซึ่งหมายความว่าโครงสร้างข้อมูลดังกล่าวจะไม่เหมาะสำหรับการตอบคำถามเช่นแสดงรายการคีย์ทั้งหมดที่ตรงกับคำนำหน้าที่กำหนดแต่เหมาะสำหรับการค้นหาว่ามีคีย์อยู่หรือไม่ ไม่ได้อยู่ใน Trie. อย่างไรก็ตามคำว่า Patricia Tree หรือ Patricia Trie ได้ถูกนำมาใช้ในหลาย ๆ ความรู้สึกที่แตกต่างกัน แต่คล้ายคลึงกันเช่นเพื่อระบุ trie ขนาดกะทัดรัด [NIST] หรือเพื่อระบุ radix trie ด้วย radix 2 [ตามที่ระบุไว้ในคำอธิบาย ทางใน WIKI] และอื่น ๆ
Trie ว่าอาจจะไม่ Radix Trie:
Ternary ค้นหา Trie (aka Ternary ค้นหาต้นไม้) มักจะสั้นขณะที่ทีเอสทีเป็นโครงสร้างข้อมูล (เสนอโดยเจเบนท์ลีย์และอาร์เซดจ์วิก ) ซึ่งมีลักษณะคล้ายกันมากกับ Trie ที่มีสามทางแยกทาง สำหรับโครงสร้างดังกล่าวแต่ละโหนดจะมีลักษณะเป็นตัวอักษร 'x' ดังนั้นการตัดสินใจที่แตกแขนงจะถูกขับเคลื่อนโดยไม่ว่าอักขระของคีย์จะน้อยกว่าเท่ากับหรือมากกว่า 'x' เนื่องจากคุณสมบัติการแตกกิ่ง 3 ทางคงที่นี้จึงเป็นทางเลือกที่มีประสิทธิภาพของหน่วยความจำสำหรับ trie โดยเฉพาะอย่างยิ่งเมื่อ R (radix) มีขนาดใหญ่มากเช่นสำหรับ Unicode alphabets ที่น่าสนใจคือ TST ซึ่งแตกต่างจาก (R-way) trieไม่มีลักษณะที่ได้รับอิทธิพลจาก R ตัวอย่างเช่นการค้นหา TST ที่ไม่ถูกต้องคือln (N)ตรงข้ามกับบันทึกR (N)สำหรับ R-way Trie ต้องการหน่วยความจำของทีเอสทีซึ่งแตกต่างจาก R-วิธีTrieคือไม่ได้ฟังก์ชั่นการวิจัยเป็นอย่างดี ดังนั้นเราควรระมัดระวังในการเรียก TST ว่า radix-trie โดยส่วนตัวฉันไม่คิดว่าเราควรเรียกมันว่า radix-trie เนื่องจากลักษณะของมันไม่มี (เท่าที่ฉันรู้) ได้รับอิทธิพลจาก radix, R ของตัวอักษรพื้นฐาน
uintptr_t
เป็นจำนวนเต็มของคุณเนื่องจากโดยทั่วไปแล้วประเภทดังกล่าวคาดว่าจะมีอยู่ (แม้ว่าจะไม่จำเป็น)
radix-tree
มากกว่าradix-trie
มีคำถามไม่กี่คำถามที่ติดแท็กนอกจากนี้