Lano (datová struktura) - Rope (data structure)
V programování počítače , na laně , nebo kabelem , je datová struktura složená z menších řetězců , který se používá pro efektivní ukládání a manipulaci s velmi dlouhý řetězec. Například program pro úpravy textu může použít lano k reprezentaci upravovaného textu, takže lze efektivně provádět operace, jako je vkládání, mazání a náhodný přístup.
Popis
Lano je binární strom, kde každý list (koncový uzel) obsahuje řetězec a délku (také známou jako „váha“) a každý uzel dále na stromě drží součet délek všech listů v levém podstromu . Uzel se dvěma podřízenými tedy rozděluje celý řetězec na dvě části: levý podstrom ukládá první část řetězce, pravý podstrom ukládá druhou část řetězce a váha uzlu je délka první části.
U lanových operací se řetězce uložené v uzlech považují za konstantní neměnné objekty v typickém nedestruktivním případě, což umožňuje určité chování kopírování při zápisu . Uzly listu jsou obvykle implementovány jako základní řetězce pevné délky s připojeným počtem odkazů pro uvolnění, když už nejsou potřeba, i když lze použít i jiné metody uvolňování paměti .
Operace
V následujících definicích je N délka lana.
Vložit
-
Definice::
Insert(i, S’)
vložte řetězec S ' začínající na pozici i do řetězce s , aby se vytvořil nový řetězec C 1 ,…, C i , S' , C i + 1 ,…, C m . - Časová složitost: .
Tuto operaci lze provést operacemi a Split()
a dvěma Concat()
. Cena je součtem všech tří.
Index
-
Definice::
Index(i)
vrátit znak na pozici i - Časová složitost:
Chcete-li načíst i -tý znak, začneme rekurzivní vyhledávání z kořenového uzlu:
function index(RopeNode node, integer i)
if node.weight <= i and exists(node.right) then
return index(node.right, i - node.weight)
end
if exists(node.left) then
return index(node.left, i)
end
return node.string[i]
end
Chcete-li například najít znak na i=10
obrázku 2.1 zobrazeném vpravo, začněte v kořenovém uzlu (A), zjistěte, že 22 je větší než 10 a je zde levé dítě, takže přejděte na levé dítě (B). 9 je menší než 10, takže odečtěte 9 od 10 (opusťte i=1
) a jděte k pravému dítěti (D). Protože je 6 větší než 1 a je zde levé dítě, přejděte k levému dítěti (G). 2 je větší než 1 a je zde levé dítě, takže jděte znovu k levému dítěti (J). Nakonec 2 je větší než 1, ale nezůstane žádné podřízené dítě, takže odpovědí je znak v indexu 1 krátkého řetězce „na“ (tj. „A“).
Concat
-
Definice::
Concat(S1, S2)
zřetězit dvě lana, S 1 a S 2 , do jednoho lana. - Časová složitost: (nebo čas pro výpočet hmotnosti kořene)
Zřetězení lze provést jednoduše vytvořením nového kořenového uzlu s left = S1 a right = S2 , což je konstantní čas. Váha nadřazeného uzlu je nastavena na délku levého podřízeného S 1 , což by vyžadovalo čas, pokud je strom vyvážený.
Jelikož většina lanových operací vyžaduje vyvážené stromy, může být nutné strom po vyrovnání znovu vyvážit.
Rozdělit
-
Definice::
Split (i, S)
rozdělte řetězec S na dva nové řetězce S 1 a S 2 , S 1 = C 1 ,…, C i a S 2 = C i + 1 ,…, C m . - Časová složitost:
Je třeba řešit dva případy:
- Bod rozdělení je na konci řetězce (tj. Za posledním znakem uzlu listu)
- Bod rozdělení je uprostřed řetězce.
Druhý případ se redukuje na první rozdělením řetězce v bodě rozdělení za účelem vytvoření dvou nových uzlů listu a poté vytvořením nového uzlu, který je nadřazeným řetězcem dvou komponent.
Chcete-li například rozdělit lano o délce 22 znaků zobrazené na obrázku 2.3 na dvě lana se stejnou složkou o délce 11, zadejte dotaz na 12. znak a vyhledejte uzel K na spodní úrovni. Odstraňte spojení mezi K a G . Přejděte na nadřazené G a odečíst hmotnost K z hmotnosti D . Projděte strom a vyjměte všechny pravé odkazy na podstromy pokrývající znaky za pozicí 11, odečtěte váhu K od jejich nadřazených uzlů ( v tomto případě pouze uzel D a A ). A konečně, vybudovat nově osamocených uzly K a H jejich zřetězení dohromady a vytvoření nového mateřský P s hmotností, která se rovná délce levého uzlu K .
Protože většina lanových operací vyžaduje vyvážené stromy, může být nutné strom po rozdělení znovu vyrovnat.
Vymazat
-
Definice::
Delete(i, j)
odstranit podřetězec C i ,…, C i + j - 1 , ze s a vytvořit nový řetězec C 1 ,…, C i - 1 , C i + j ,…, C m . - Časová složitost: .
Tuto operaci lze provést dvěma Split()
a jednou Concat()
operací. Nejprve rozdělte lano na tři, vydělené i - tým a i + j -tým znakem, který extrahuje řetězec k odstranění v samostatném uzlu. Potom zřetězte další dva uzly.
Zpráva
-
Definice::
Report(i, j)
výstup řetězce C i ,…, C i + j - 1 . - Časová složitost:
Chcete-li nahlásit řetězec C i ,…, C i + j - 1 , najděte uzel u, který obsahuje C i a weight(u) >= j
, a poté projeďte T počínaje uzlem u . Výstup C i , ..., C i + j - 1 tím, že dělá přechodu přes in-pořadí z T začíná v uzlu u .
Srovnání s monolitickými poli
Úkon | Lano | Tětiva |
---|---|---|
Index | O (log n) | O (1) |
Rozdělit | O (log n) | O (1) |
Zřetězit (destruktivně) | O (log n) bez vyvážení / O (n) nejhorší případ | Na) |
Zřetězit (nedestruktivně) | Na) | Na) |
Iterujte každou postavu | Na) | Na) |
Vložit | O (log n) bez vyvážení / O (n) nejhorší případ | Na) |
Připojit | O (log n) bez vyvážení / O (n) nejhorší případ | O (1) amortizován, O (n) nejhorší případ |
Vymazat | O (log n) | Na) |
Zpráva | O (j + log n) | O (j) |
Stavět | Na) | Na) |
Výhody:
- Lana umožňují mnohem rychlejší vkládání a mazání textu než monolitická pole řetězců, u nichž mají operace časovou složitost O (n).
- Lana nevyžadují O (n) extra paměť, když jsou provozována (pole to potřebují pro operace kopírování).
- Lana nevyžadují velké souvislé paměťové prostory.
- Pokud se používají pouze nedestruktivní verze operací, je lanko trvalou datovou strukturou . U příkladu programu pro úpravy textu to vede k snadné podpoře více úrovní zpět .
Nevýhody:
- Větší celkové využití prostoru, když není provozováno, hlavně k ukládání nadřazených uzlů. Existuje kompromis mezi tím, kolik z celkové paměti je taková režie, a tím, jak dlouho se data zpracovávají jako řetězce. Řetězce na příkladech výše jsou pro moderní architektury nereálně krátké. Režie je vždy O (n), ale konstanta může být libovolně malá.
- Prodloužení času pro správu dalšího úložiště
- Zvýšená složitost zdrojového kódu; větší riziko chyb
Tato tabulka porovnává algoritmické vlastnosti implementací řetězců a lan, nikoli jejich surovou rychlost . Řetězce založené na poli mají menší režii, takže (například) operace zřetězení a rozdělení jsou u malých datových sad rychlejší. Pokud se však řetězce založené na poli používají pro delší řetězce, časová složitost a využití paměti pro vkládání a mazání znaků se stanou nepřijatelně velkými. Naproti tomu lanová datová struktura má stabilní výkon bez ohledu na velikost dat. Dále je prostorová složitost pro lana a pole O (n). Stručně řečeno, lana jsou vhodnější, když jsou data velká a často se mění.
Viz také
- Cedar programovací prostředí, které používají provazy „téměř od svého vzniku“
- Model T enfilade , podobnou datovou strukturu od začátku roku 1970.
- Mezera vyrovnávací paměti , datová struktura běžně používaná v textových editorech, která umožňuje efektivní operace vkládání a mazání seskupené poblíž stejného místa
- Kusová tabulka , další datová struktura běžně používaná v textových editorech
Reference
externí odkazy
- "C šňůry" implementace lan v knihovně Boehm Garbage Collector
- Specifikace SGI C ++ pro lana (podporovaná STLPort a libstdc ++ )
- Lana pro C #
- lana pro Common Lisp
- Lana pro Javu
- Lana pro JavaScript
- Lana pro limbu
- lana pro Nim
- Lana pro OCaml
- pyropes pro Python
- Lana pro Smalltalk
- SwiftRope pro Swift
- „Ropey“ pro Rusta