Персистентный массив — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
м (rollbackEdits.php mass rollback)
 
(не показано 20 промежуточных версий 5 участников)
Строка 1: Строка 1:
  
 
{{Определение
 
{{Определение
def=Мы называем ADT '''полностью персистентными'''(англ. fully persistent), если, помимо интерфейса, все операции сохраняют операнды неизменными, таким образом, что операнды и результаты таких операций могут быть свободно используемы повторно во время дальнейшего хода вычислений.
+
|definition=Мы называем ADT '''полностью персистентными'''(англ. fully persistent), если, помимо интерфейса, все операции сохраняют операнды неизменными, таким образом, что операнды и результаты таких операций могут быть свободно используемы повторно во время дальнейшего хода вычислений.
 
Мы называем структуру данных (как реализацию абстрактного типа данных англ.ATD) полностью персистентной, если она эффективно реализует все операции предполагаемого, полностью персистентного ADT.}}
 
Мы называем структуру данных (как реализацию абстрактного типа данных англ.ATD) полностью персистентной, если она эффективно реализует все операции предполагаемого, полностью персистентного ADT.}}
===Интерфейс===
+
==Интерфейс==
* [X] статический конструктор, который принимает элемент X и возвращает массив, который содержит X в качестве его единственного элемента.
+
 
* '''LENGTH''' [A] возвращает длину массива A.
+
* <tex> [ X ]</tex>  статический конструктор, который принимает элемент <tex>  X </tex> и возвращает массив, который содержит <tex>  X </tex> в качестве его единственного элемента.
* ε является пустым массивом, иногда также обозначается []
+
* <tex> LENGTH [A] </tex>  возвращает длину массива <tex>  A </tex>.
* '''A''' [i] принимает массив A = [''a''<sub>0</sub>, ..., an-1] и индекс ''i'' = 0..''n''-1, затем возвращает ''a''<sub>i</sub>.
+
* <tex> \varepsilon </tex> является пустым массивом, иногда также обозначается <tex> [ ]</tex>
* '''CONCATENATE'''(A,B) конкатентирует два массива: if ''A'' = [''a''<sub>0</sub>,...,''a''<sub>n-1</sub>] and ''B'' = [''b''<sub>0</sub>,...,''b''<sub>m-1</sub>], ''n'',''m'' ≥ 0, результат будет [''a''<sub>0</sub>,...,''a''<sub>n−1</sub>,"b"<sub>0</sub>,...,''b''<sub>m-1</sub>]. Часто записывается как ''A'' · ''B'' вместо '''CONCATENATE'''(''A'',''B'').
+
* <tex> A [i] </tex>  принимает массив <tex>  A = [a_0, ..., a_{n-1} ] </tex>  и индекс <tex>  i = 0..n - 1 </tex> , затем возвращает <tex>   a_i </tex>.
* '''HEAD'''(A,''i'') принимает на вход массив ''A'' = [''a''<sub>0</sub>,...,''a''n−1] и производный ''int'', возвращает массив [''a''0,...,''amin(i−1,n−1)'' ].  Если ''i'' < 0 результатом будет [].
+
* <tex> CONCATENATE(A,B) </tex>  конкатентирует два массива: если <tex>  A = [a_0,..., a_{n-1} ] </tex> и  <tex>  B = [b_0,..., b_{m-1} ]; n, m \geq 0</tex> , результат будет <tex> [a_0 ,..., a_{n−1}, b_0,..., b_{m-1}] </tex> . Часто записывается как <tex>  A B</tex>  вместо <tex> CONCATENATE (A,B) </tex> .
* '''TAIL'''(''A'',''i'') принимает на вход массив  ''A'' = ["a"<sub>0</sub>,...,an−1] и производный int, возвращает массив [''amax(''i'',0)'' ,...,''a''n−1]. Если ''i'' ≥ ''n'', результатом будет [].
+
* <tex> HEAD (A,i) </tex>  принимает на вход массив <tex>  A = [a_0,...,a_{n−1}] </tex>  и производный   <tex>  int</tex> , возвращает массив <tex>  [a_0,...,a_{min(i−1,n−1)} ] </tex> .  Если <tex>  i < 0</tex>  результатом будет <tex>  [ ]</tex> .
* '''B''' - структура, то ''seq (''B'')'' обозначает строку, которая представлена ''B''.  
+
* <tex> TAIL (A,i) </tex>  принимает на вход массив   <tex> A = [a_0,...,a_n−1] </tex>  и производный <tex>  int</tex> , возвращает массив <tex>  [a_{max(i,0)} ,...,a_{n−1}]</tex> . Если <tex>  i \geq n</tex> , результатом будет <tex>  [ ]</tex> .
 +
* Если <tex> B</tex>  - структура, то <tex>  seq (B) </tex>  обозначает строку, которая представлена <tex>  B</tex> .  
 +
 
 
Основываясь на вышеприведенных операциях, ADT может быть расширен следующими операциями:
 
Основываясь на вышеприведенных операциях, ADT может быть расширен следующими операциями:
* [''x''0,..., ''x''n−1] является сокращением для '''CONCATENATE'''([x0],'''CONCATENATE'''([x1],'''CONCATENATE'''(...,'''CONCATENATE'''([''x''n−2],[''x''n−1])))) . Обратите внимание, что в программе оценка этого выражения всегда включает ''n-2'' конкатенации.
+
 
* '''REVERSE'''[''A''] принимает на вход массив A = [''a''0,...,''a''<sub>n-1</sub>] и возвращает [''a''<sub>n-1</sub>,...,a0].  
+
* <tex> [x0,..., x_{n−1}]</tex>  является сокращением для <tex> CONCATENATE ([x_0], CONCATENATE ([x_1],CONCATENATE(...,CONCATENATE([x_{n−2}],[x_{n−1}])))) </tex>  . Обратите внимание, что в программе оценка этого выражения всегда включает <tex>  n-2</tex>  конкатенации.
* '''REPLACE'''[A,i, x] принимает на вход массив A = [''a''0,...,''a''<sub>n-1</sub>], индекс ''i'' = 0..''n'' − 1, и новый элемент ''x'', выводит [''a''<sub>0</sub>,...,''a''<sub>i-1</sub>, ''x'',''a''<sub>i+1</sub>,...,''a''<sub>n-1</sub>].  
+
* <tex> REVERSE[A] </tex>  принимает на вход массив <tex>  A = [a_0,...,a_{n-1}] </tex> и возвращает <tex> [a_{n-1},...,a_0] </tex> .  
* '''A'''[i] ← ''x ''является сокращенным обозначением A REPLACE(A,''i'', ''x'').   
+
* <tex> REPLACE [A,i, x] </tex>  принимает на вход массив <tex>  A = [a_0,...,a_{n-1}]</tex>   , индекс <tex>  i = 0.. n - 1 </tex> , и новый элемент <tex> x</tex> , выводит <tex> [a_0,...,a_{i-1}, x,a_{i+1},...,a_{n-1}]</tex> .  
* '''INSERT'''[A,i, x] получает массив A = [''a''0,...,''a''<sub>n-1</sub>], индекс ''i'' = 0..n−1, и новый элемент x и возвращает массив [''a''0,...,''a''<sub>i-1</sub>, x,''a''i ,...,''a''n−1] = '''HEAD'''(A,''i'') · [''x''] · '''TAIL'''(A,''i)'', длина которого ''n''-1.
+
* <tex> A[i] \leftarrow x </tex> является сокращенным обозначением <tex> A \leftarrow REPLACE(A,i, x)</tex> .   
* '''LEFTPART'''(A): возвращает (non-deterministically) массив, представляющий последовательность префикса A.
+
* <tex> INSERT[A,i, x]</tex>  получает массив <tex>  A = [a_0,...,a_{n-1}]</tex>   , индекс <tex>  i = 0..n - 1 </tex>  , и новый элемент <tex>  x </tex>  и возвращает массив <tex>  [a_0,...,a_{i-1}, x,a_i ,...,a_{n−1}] = HEAD(A,i) [x] TAIL(A,i) </tex>  , длина которого <tex>  n-1</tex>  .
* ''' RIGHTPART'''(A): возвращает (non-deterministically) массив, представляющий последовательность суффикса A.  
+
* <tex> LEFTPART (A) </tex> возвращает массив, представляющий последовательность префикса <tex>    A</tex>  .
===Реализация персистентных массивом в виде сбалансированных деревьев===
+
* <tex>  RIGHTPART(A) </tex>  возвращает массив, представляющий последовательность суффикса <tex>    A</tex>  .
 +
 
 +
==Реализация персистентных массивов в виде сбалансированных деревьев==
 
Будем использовать сбалансированные деревья в качестве нашей стандартной реализации постоянных массивов. (Реализации сбалансированных деревьев, таких как AVL-деревья и B-деревья, можно найти в соответствующих разделах сайта)
 
Будем использовать сбалансированные деревья в качестве нашей стандартной реализации постоянных массивов. (Реализации сбалансированных деревьев, таких как AVL-деревья и B-деревья, можно найти в соответствующих разделах сайта)
 
Решающим моментом является то, что мы допускаем множественные ссылки на одно и то же поддерево: хотя концептуальное представление постоянных массивов - ориентированные деревья, их представление в памяти различно. Мы допускаем, что узел может быть преемником многих разных узлов.  
 
Решающим моментом является то, что мы допускаем множественные ссылки на одно и то же поддерево: хотя концептуальное представление постоянных массивов - ориентированные деревья, их представление в памяти различно. Мы допускаем, что узел может быть преемником многих разных узлов.  
  
Def Пусть X - некоторое множество. Бинарное дерево с несколькими ссылками по X является кортежем B = (N, L, R) с L∩R = 0 /, L, R N × N, такой, что (N, L∪R) является корневым ациклическим ориентированным графом с узлами N и ребра L∪R и в каждом из двух подграфов (N, L) и (N, R) каждый узел имеет не более одного прямого преемника. Кроме того, узлы без каких-либо преемников (листья B) должны быть все элементами X.
+
{{Определение
Дано двоичное дерево с несколькими ссылками B = (N,L,R) и узел ''p'' ∈ N. Пишут LEFT(''p'') = ''q'', если ''q'' является единственным приемником  ''p'' в(N,L) и, если  такого ''q''  не существует, пишем LEFT(''p'')= ,  предполагая, что не содержит N. Аналогично, пишут RIGHT(p) = ''q'', если q является единственным приемником p в(N,R) и, если  такого q  не существует, пишем RIGHT(''p'')= . Мы будем называть LEFT (''p'') левым дочерним элементом p и RIGHT (''p'') правым дочерним элементом.
+
|definition= Пусть <tex> X</tex>  - некоторое множество. Бинарное дерево с несколькими ссылками на  <tex> X</tex>  является кортежем <tex> B = (N, L, R) с L \cap  R = 0 /, L, R \subseteq  N × N</tex> , таким, что
В B = (N, L∪R) узел ''p'' ∈ N может иметь много прямых предшественников ''q''. Тогда ребра (''q'', ''p'') E называют ссылками от q до p.
+
*  <tex> (N, L \cup R)</tex>  является корневым ациклическим ориентированным графом с узлами <tex> N</tex> , ребрами  <tex> L \cup R</tex> .
 +
* В каждом из двух подграфов <tex> (N, L) и (N, R)</tex>  каждый узел имеет не более одного прямого преемника .  
 +
*Узлы без каких-либо преемников (листья B) должны быть все элементами <tex> X</tex> .
 +
}}
 +
Дано двоичное дерево с несколькими ссылками <tex> B = (N,L,R)</tex>  и узел   <tex> p \in N</tex> . Пишут <tex> LEFT(p) = q</tex> , если <tex> q</tex>  является единственным приемником   <tex> p в (N,L)</tex>  и, если  такого <tex> q</tex>  не существует, пишем <tex> LEFT(p)= \perp</tex> ,  предполагая, что <tex> \perp </tex>  не содержит <tex> N</tex> . Аналогично, пишут <tex> RIGHT(p) = q</tex> , если <tex> q</tex>  является единственным приемником   <tex> p в(N,R)</tex>  и, если  такого <tex> q</tex> не существует, пишем <tex> RIGHT(p)= \perp</tex> . Мы будем называть <tex> LEFT (p)</tex>  левым дочерним элементом <tex> p</tex>  и <tex> RIGHT (p) </tex>  правым дочерним элементом.
 +
В <tex>  B = (N, L \cup R)</tex>  узел <tex> p \in N</tex>  может иметь много прямых предшественников <tex> q</tex> . Тогда ребра <tex> (q, p) \in E</tex>  называют ссылками от <tex> q</tex>  до <tex>  p</tex> .
  
С каждым узлом ''p'' ∈ N мы можем идентифицировать строку seq (''p'') X *: Если ''p'' - лист, то согласно определению выше, ''p'' ∈ X. Мы можем установить seq (p) = x (строка, содержащая только'' x''). Поскольку (N, L∪R ) ациклично, для всех внутренних узлов мы можем рекурсивно определить p N  seq (''p'') = seq (LEFT (''p'')) seq (RIGHT (''p'')), задав seq () = ε. Наконец, пусть r - корень B. Тогда определим''seq ''(B): = ''seq ''(''r''). В качестве примера, см. рисунок 1.2.
+
С каждым узлом <tex> p \in N</tex>  мы можем идентифицировать строку <tex> seq (p) \in X </tex>  :
В нашей реализации мы поддерживаем с каждым узлом p N длину seq (LEFT (''p'')). Это позволяет получить ''i''-й символ строки seq (B), пройдя путь от корня до соответствующего листа. Мы также поддерживаем значение HEIGHT (''p'') для каждого p N, которое определяется как максимальная
+
Если p - лист, то согласно определению выше, <tex>  p \in X</tex> . Мы можем установить <tex> seq (p) = x</tex>  (строка, содержащая только x). Поскольку <tex> (N, L \cup R )</tex>  ациклично, для всех внутренних узлов мы можем рекурсивно определить <tex> p \in N  seq (p) = seq (LEFT (p)) seq (RIGHT (p))</tex> , задав <tex> seq (\perp) = ε <tex> . Наконец, пусть r - корень B. Тогда определимseq (B): = seq (r). В качестве примера, см. рисунок 1.2.
длина пути от p до листа в ''q'' ∈ N. Согласно этому определению все листья имеют высоту 0 и если мы устанавливаем HEIGHT () = -1, то HEIGHT(''p'') = max(HEIGHT(LEFT(''p'')), HEIGHT(RIGHT(''p'')))+1  для всех ''p'' ∈ N.
+
В нашей реализации мы поддерживаем с каждым узлом <tex> p \in N</tex>  длину <tex> seq (LEFT (p))</tex> . Это позволяет получить
 +
<tex> i-й</tex>  символ строки <tex> seq (B)</tex> , пройдя путь от корня до соответствующего листа. Мы также поддерживаем значение HEIGHT (p) для каждого <tex> p \in N</tex> , которое определяется как максимальная
 +
длина пути от p до листа в <tex> q \in N</tex> . Согласно этому определению все листья имеют высоту <tex> 0</tex>  и если мы устанавливаем <tex> HEIGHT (\perp) = -1</tex> , то <tex> HEIGHT(p) = max(HEIGHT(LEFT(p)), HEIGHT(RIGHT(p)))+1</tex> . для всех <tex> .p \in N</tex> ..
 
Чтобы сбалансировать структуру, мы используем AVL-условие для двоичных деревьев.  
 
Чтобы сбалансировать структуру, мы используем AVL-условие для двоичных деревьев.  
Def3 Бинарное дерево B = (N, L, R) является AVL-деревом, если оно удовлетворяет условию AVL, то есть для каждого p N  |HEIGHT(LEFT(''p''))− HEIGHT(RIGHT(''p''))| 1.
+
Def3 Бинарное дерево <tex> B = (N, L, R) </tex>  является AVL-деревом, если оно удовлетворяет условию AVL, то есть для каждого <tex> p \in N  |HEIGHT(LEFT(p))− HEIGHT(RIGHT(p))| \le 1</tex> .
 
1.2 конкатенация постоянных массивов, представленных в виде двоичных деревьев
 
1.2 конкатенация постоянных массивов, представленных в виде двоичных деревьев
Для полноты мы покажем операции для конкатенации · и расщепления (HEAD и TAIL), которые особенно просты в реализации, запускаются во времени O (HEIGHT (''r'')) и позволяют нам реализовать полный интерфейс персистентного массива ADT. Для конкатенации см. Алгоритм 1.2.
+
Для полноты мы покажем операции для конкатенации и расщепления <tex>  (HEAD и TAIL) </tex> , которые особенно просты в реализации, запускаются во времени <tex> O (HEIGHT (r)) </tex>  и позволяют нам реализовать полный интерфейс персистентного массива ADT. Для конкатенации см. Алгоритм 1.2.
NODE (''l'', ''r'') является конструктором, который выдает созданный узел ''p'' с LEFT (''p'') = l и RIGHT (''p'') = ''r''. Конструктор также определяет правильные значения p для HEIGHT (''p'') и LENGTH (''p'').
+
  <tex> NODE (l, r) </tex>  является конструктором, который выдает созданный узел <tex> p с LEFT (p) = l и RIGHT (p) = r</tex> . Конструктор также определяет правильные значения <tex> p</tex>  для <tex> HEIGHT (p) и LENGTH (p) </tex> .
Обратите внимание, что время его работы равно O (| HEIGHT (''r'') -HEIGHT (''l'') |). Далее мы покажем алгоритм HEAD, алгоритм для TAIL является симметричным.  
+
Обратите внимание, что время его работы равно <tex> O (| HEIGHT (r) -HEIGHT (l) |)</tex> . Далее мы покажем алгоритм <tex> HEAD</tex> , алгоритм для <tex> TAIL</tex>  является симметричным.  
 
1.3  Разделение персистентного массива, представленного как двоичное дерево.
 
1.3  Разделение персистентного массива, представленного как двоичное дерево.
Учитывая корневой узел r высоты ''h'' и целое число ''i'', алгоритм 1.3 свяжет не более чем ''h + 1'' двоичных дерева. Стоимость одной конкатенации пропорциональна разнице высот.
+
Учитывая корневой узел r высоты h и целое число i, алгоритм 1.3 свяжет не более чем <tex> h + 1</tex>  двоичных дерева. Стоимость одной конкатенации пропорциональна разнице высот.
 +
 
 +
 
  
 
При использовании RAW с ограниченным размером арифметических операций, ADT для персистентных массивов могут быть реализованы таким образом, чтобы каждая из его операций выполнялась во времени O (logn).Если длины массивов представляются внутри границ слова. В противном случае временная граница O (min ((log n)2, k2)). Здесь n - максимальная длина задействованных массивов, а k – число, которые были использованы для создания массивов операндов.
 
При использовании RAW с ограниченным размером арифметических операций, ADT для персистентных массивов могут быть реализованы таким образом, чтобы каждая из его операций выполнялась во времени O (logn).Если длины массивов представляются внутри границ слова. В противном случае временная граница O (min ((log n)2, k2)). Здесь n - максимальная длина задействованных массивов, а k – число, которые были использованы для создания массивов операндов.

Текущая версия на 19:34, 4 сентября 2022


Определение:
Мы называем ADT полностью персистентными(англ. fully persistent), если, помимо интерфейса, все операции сохраняют операнды неизменными, таким образом, что операнды и результаты таких операций могут быть свободно используемы повторно во время дальнейшего хода вычислений. Мы называем структуру данных (как реализацию абстрактного типа данных англ.ATD) полностью персистентной, если она эффективно реализует все операции предполагаемого, полностью персистентного ADT.

Интерфейс

  • [math] [ X ][/math] статический конструктор, который принимает элемент [math] X [/math] и возвращает массив, который содержит [math] X [/math] в качестве его единственного элемента.
  • [math] LENGTH [A] [/math] возвращает длину массива [math] A [/math].
  • [math] \varepsilon [/math] является пустым массивом, иногда также обозначается [math] [ ][/math]
  • [math] A [i] [/math] принимает массив [math] A = [a_0, ..., a_{n-1} ] [/math] и индекс [math] i = 0..n - 1 [/math] , затем возвращает [math] a_i [/math].
  • [math] CONCATENATE(A,B) [/math] конкатентирует два массива: если [math] A = [a_0,..., a_{n-1} ] [/math] и [math] B = [b_0,..., b_{m-1} ]; n, m \geq 0[/math] , результат будет [math] [a_0 ,..., a_{n−1}, b_0,..., b_{m-1}] [/math] . Часто записывается как [math] A • B[/math] вместо [math] CONCATENATE (A,B) [/math] .
  • [math] HEAD (A,i) [/math] принимает на вход массив [math] A = [a_0,...,a_{n−1}] [/math] и производный [math] int[/math] , возвращает массив [math] [a_0,...,a_{min(i−1,n−1)} ] [/math] . Если [math] i \lt 0[/math] результатом будет [math] [ ][/math] .
  • [math] TAIL (A,i) [/math] принимает на вход массив [math] A = [a_0,...,a_n−1] [/math] и производный [math] int[/math] , возвращает массив [math] [a_{max(i,0)} ,...,a_{n−1}][/math] . Если [math] i \geq n[/math] , результатом будет [math] [ ][/math] .
  • Если [math] B[/math] - структура, то [math] seq (B) [/math] обозначает строку, которая представлена [math] B[/math] .

Основываясь на вышеприведенных операциях, ADT может быть расширен следующими операциями:

  • [math] [x0,..., x_{n−1}][/math] является сокращением для [math] CONCATENATE ([x_0], CONCATENATE ([x_1],CONCATENATE(...,CONCATENATE([x_{n−2}],[x_{n−1}])))) [/math] . Обратите внимание, что в программе оценка этого выражения всегда включает [math] n-2[/math] конкатенации.
  • [math] REVERSE[A] [/math] принимает на вход массив [math] A = [a_0,...,a_{n-1}] [/math] и возвращает [math] [a_{n-1},...,a_0] [/math] .
  • [math] REPLACE [A,i, x] [/math] принимает на вход массив [math] A = [a_0,...,a_{n-1}][/math] , индекс [math] i = 0.. n - 1 [/math] , и новый элемент [math] x[/math] , выводит [math] [a_0,...,a_{i-1}, x,a_{i+1},...,a_{n-1}][/math] .
  • [math] A[i] \leftarrow x [/math] является сокращенным обозначением [math] A \leftarrow REPLACE(A,i, x)[/math] .
  • [math] INSERT[A,i, x][/math] получает массив [math] A = [a_0,...,a_{n-1}][/math] , индекс [math] i = 0..n - 1 [/math] , и новый элемент [math] x [/math] и возвращает массив [math] [a_0,...,a_{i-1}, x,a_i ,...,a_{n−1}] = HEAD(A,i) [x] • TAIL(A,i) [/math] , длина которого [math] n-1[/math] .
  • [math] LEFTPART (A) [/math] возвращает массив, представляющий последовательность префикса [math] A[/math] .
  • [math] RIGHTPART(A) [/math] возвращает массив, представляющий последовательность суффикса [math] A[/math] .

Реализация персистентных массивов в виде сбалансированных деревьев

Будем использовать сбалансированные деревья в качестве нашей стандартной реализации постоянных массивов. (Реализации сбалансированных деревьев, таких как AVL-деревья и B-деревья, можно найти в соответствующих разделах сайта) Решающим моментом является то, что мы допускаем множественные ссылки на одно и то же поддерево: хотя концептуальное представление постоянных массивов - ориентированные деревья, их представление в памяти различно. Мы допускаем, что узел может быть преемником многих разных узлов.


Определение:
Пусть [math] X[/math] - некоторое множество. Бинарное дерево с несколькими ссылками на [math] X[/math] является кортежем [math] B = (N, L, R) с L \cap R = 0 /, L, R \subseteq N × N[/math] , таким, что
  • [math] (N, L \cup R)[/math] является корневым ациклическим ориентированным графом с узлами [math] N[/math] , ребрами [math] L \cup R[/math] .
  • В каждом из двух подграфов [math] (N, L) и (N, R)[/math] каждый узел имеет не более одного прямого преемника .
  • Узлы без каких-либо преемников (листья B) должны быть все элементами [math] X[/math] .

Дано двоичное дерево с несколькими ссылками [math] B = (N,L,R)[/math] и узел [math] p \in N[/math] . Пишут [math] LEFT(p) = q[/math] , если [math] q[/math] является единственным приемником [math] p в (N,L)[/math] и, если такого [math] q[/math] не существует, пишем [math] LEFT(p)= \perp[/math] , предполагая, что [math] \perp [/math] не содержит [math] N[/math] . Аналогично, пишут [math] RIGHT(p) = q[/math] , если [math] q[/math] является единственным приемником [math] p в(N,R)[/math] и, если такого [math] q[/math] не существует, пишем [math] RIGHT(p)= \perp[/math] . Мы будем называть [math] LEFT (p)[/math] левым дочерним элементом [math] p[/math] и [math] RIGHT (p) [/math] правым дочерним элементом. В [math] B = (N, L \cup R)[/math] узел [math] p \in N[/math] может иметь много прямых предшественников [math] q[/math] . Тогда ребра [math] (q, p) \in E[/math] называют ссылками от [math] q[/math] до [math] p[/math] .

С каждым узлом [math] p \in N[/math] мы можем идентифицировать строку [math] seq (p) \in X [/math]  :

Если p - лист, то согласно определению выше, [math]  p \in X[/math] . Мы можем установить  [math] seq (p) = x[/math]  (строка, содержащая только x). Поскольку  [math] (N, L \cup R )[/math]  ациклично, для всех внутренних узлов мы можем рекурсивно определить  [math] p \in N  seq (p) = seq (LEFT (p)) seq (RIGHT (p))[/math] , задав  [math] seq (\perp) = ε \lt tex\gt  . Наконец, пусть r - корень B. Тогда определимseq (B): = seq (r). В качестве примера, см. рисунок 1.2.
В нашей реализации мы поддерживаем с каждым узлом  \lt tex\gt  p \in N[/math]  длину  [math] seq (LEFT (p))[/math] . Это позволяет получить
[math] i-й[/math]  символ строки  [math] seq (B)[/math] , пройдя путь от корня до соответствующего листа. Мы также поддерживаем значение HEIGHT (p) для каждого  [math] p \in N[/math] , которое определяется как максимальная

длина пути от p до листа в [math] q \in N[/math] . Согласно этому определению все листья имеют высоту [math] 0[/math] и если мы устанавливаем [math] HEIGHT (\perp) = -1[/math] , то [math] HEIGHT(p) = max(HEIGHT(LEFT(p)), HEIGHT(RIGHT(p)))+1[/math] . для всех [math] .p \in N[/math] .. Чтобы сбалансировать структуру, мы используем AVL-условие для двоичных деревьев. Def3 Бинарное дерево [math] B = (N, L, R) [/math] является AVL-деревом, если оно удовлетворяет условию AVL, то есть для каждого [math] p \in N |HEIGHT(LEFT(p))− HEIGHT(RIGHT(p))| \le 1[/math] . 1.2 конкатенация постоянных массивов, представленных в виде двоичных деревьев Для полноты мы покажем операции для конкатенации • и расщепления [math] (HEAD и TAIL) [/math] , которые особенно просты в реализации, запускаются во времени [math] O (HEIGHT (r)) [/math] и позволяют нам реализовать полный интерфейс персистентного массива ADT. Для конкатенации см. Алгоритм 1.2.

 [math] NODE (l, r) [/math]  является конструктором, который выдает созданный узел  [math] p с LEFT (p) = l и RIGHT (p) = r[/math] . Конструктор также определяет правильные значения  [math] p[/math]  для  [math] HEIGHT (p) и LENGTH (p) [/math] .

Обратите внимание, что время его работы равно [math] O (| HEIGHT (r) -HEIGHT (l) |)[/math] . Далее мы покажем алгоритм [math] HEAD[/math] , алгоритм для [math] TAIL[/math] является симметричным. 1.3 Разделение персистентного массива, представленного как двоичное дерево. Учитывая корневой узел r высоты h и целое число i, алгоритм 1.3 свяжет не более чем [math] h + 1[/math] двоичных дерева. Стоимость одной конкатенации пропорциональна разнице высот.


При использовании RAW с ограниченным размером арифметических операций, ADT для персистентных массивов могут быть реализованы таким образом, чтобы каждая из его операций выполнялась во времени O (logn).Если длины массивов представляются внутри границ слова. В противном случае временная граница O (min ((log n)2, k2)). Здесь n - максимальная длина задействованных массивов, а k – число, которые были использованы для создания массивов операндов.

Литература

  • [Nobuhiro Izumi Hui-Hsiung "Acta Applicandae Texematicae",79–87.Bell numbers, log-concavity, and log-convexity 2000]
  • [Aitken A. C. Edinburgh Texematical Notes,18–23 A problem in combinations 1933]
  • [H. W.BeckerJohn Riordan "The arithmetic of Bell and Stirling numbers" American Journal of Texematics,1948,385–394]
  • [E. T.Bell Exponential polynomials,Annals of Texematics,1934, 258–277]
  • [E. T.Bell The iterated exponential integers,Annals of Texematics,1938,539–557]
  • Bender Edward A.Williamson, S. Gill, Set Partitions, 319–320, 2006
  • Bell numbers

Примeчания

--MikeTerentyev 16:07, 8 октября 2017 (MSK)MikeTerentyev