Wariant z order statistic tree pozwoliłby na dodanie i pobranie według indeksu w O (log n).
Podstawowa idea jest następująca:
- mieć każdy sklep węzła wielkości poddrzewa zakorzenione w tym węźle.
Indeks węzła będzie odpowiadał jego pozycji w drzewie in-order traversal.
Oznacza to, że porządkowanie węzłów jest określane na podstawie miejsca w drzewie, w którym się pojawiają - nie jest tak, jak zwykle działa binary search tree, gdzie elementy węzłów mają pewne uporządkowanie, które nie jest zależne od miejsca w drzewie. pojawia się (np f
jest większa niż a
w regularnych BST nakazał leksykograficznie, ale w naszym przypadku f
może być mniejsza lub większa niż a
, ponieważ zamówione na podstawie indeksu od f
i a
).
Aby dodać lub uzyskać, zaczynamy u nasady i rekursywnie przejść przez drzewa, ustalenie, czy nasza pozycja wkładka lub wyszukiwanie jest oparte na indeksie docelowej i wielkości poddrzewa w lewo lub w prawo.
Dokładniej, mamy następujące definicje rekurencyjne:
(z niektórymi dodaje złożoności dla zerowych węzłów i faktycznie wstawienie węzła)
node.add(index, element):
if index <= left.subtreeSize
left.add(index, element)
else
// anything to the right is after left subtree and current node, so those must be excluded
right.add(index - left.subtreeSize - 1, element)
node.get(index, element):
if index == left.subtreeSize
return node
if index < left.subtreeSize
return left.get(index)
else
return right.get(index - left.subtreeSize - 1)
Aby to lepiej zrozumieć, następujący przykład drzewo może Bądź pomocny:
Values: Indices (in-order pos): Subtree sizes:
a 5 8
/\ /\ /\
b g 1 6 5 2
/\ \ /\ \ /\ \
f c h 0 3 7 1 3 1
/\ /\ /\
e d 2 4 1 1
Jeśli chcemy wstawić nowy węzeł w pozycji 5, na przykład zostanie wstawiony na prawo od d
.
Poniżej znajduje się mały program testowy do zademonstrowania tego (tworzenie drzewa pokazanego powyżej).
Należy pamiętać, że nadal trzeba będzie wykonać balancing, aby uzyskać czas działania O (log n) na operację.
class Test
{
static class Node<T>
{
Node<T> left, right;
T data;
int subtreeCount;
Node(T data) { this.data = data; subtreeCount = 1; }
public String toString(int spaces, char leftRight)
{
return String.format("%" + spaces + "s%c: %s\n", "", leftRight, data.toString())
+ (left != null ? left.toString(spaces+3, 'L') : "")
+ (right != null ? right.toString(spaces+3, 'R') : "");
}
int subtreeSize(Node<T> node)
{
if (node == null)
return 0;
return node.subtreeCount;
}
// combined add and get into 1 function for simplicity
// if data is null, it is an get, otherwise it's an add
private T addGet(int index, T data)
{
if (data != null)
subtreeCount++;
if (index == subtreeSize(left) && data == null)
return this.data;
if (index <= subtreeSize(left))
{
if (left == null && data != null)
return (left = new Node<>(data)).data;
else
return left.addGet(index, data);
}
else if (right == null && data != null)
return (right = new Node<>(data)).data;
else
return right.addGet(index-subtreeSize(left)-1, data);
}
}
static class TreeArray<T>
{
private Node<T> root;
public int size() { return (root == null ? 0 : root.subtreeCount); }
void add(int index, T data)
{
if (index < 0 || index > size())
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size());
if (root == null)
root = new Node<>(data);
else
root.addGet(index, data);
}
T get(int index)
{
if (index < 0 || index >= size())
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size());
return root.addGet(index, null);
}
@Override
public String toString() { return root == null ? "Empty" : root.toString(1, 'X'); }
}
public static void main(String[] args)
{
TreeArray<String> tree = new TreeArray<>();
tree.add(0, "a");
tree.add(0, "b");
tree.add(1, "c");
tree.add(2, "d");
tree.add(1, "e");
tree.add(0, "f");
tree.add(6, "g");
tree.add(7, "h");
System.out.println("Tree view:");
System.out.print(tree);
System.out.println("Elements in order:");
for (int i = 0; i < tree.size(); i++)
System.out.println(i + ": " + tree.get(i));
}
}
ten wyjścia:
Tree view:
X: a
L: b
L: f
R: c
L: e
R: d
R: g
R: h
Elements in order:
0: f
1: b
2: e
3: c
4: d
5: a
6: g
7: h
Live demo.
'get (indeks)' jest bardziej prawdopodobne, że jest O (n log n), ponieważ wiąże się z sortowaniem. – DwB