2 * Treap container for internal usage.
4 * Copyright: Copyright Digital Mars 2014 - 2014.
5 * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
7 module core
.internal
.container
.treap
;
9 static import common
= core
.internal
.container
.common
;
10 import core
.internal
.qsort
;
29 void initialize(ulong randSeed
)
31 Rand _rand
= { randSeed
};
35 void insert(E element
) @nogc
37 root
= insert(root
, element
);
40 void remove(E element
)
42 remove(&root
, element
);
45 int opApply(scope int delegate(ref E
) nothrow dg
)
47 return (cast(const)&this).opApply((ref const E e
) => dg(*cast(E
*)&e
));
50 int opApply(scope int delegate(ref const E
) nothrow dg
) const
52 return opApplyHelper(root
, dg
);
55 version (CoreUnittest
)
56 bool opEquals(E
[] elements
)
61 if (i
>= elements
.length
)
63 if (e
!= elements
[i
++])
66 return i
== elements
.length
;
75 version (CoreUnittest
)
85 static uint height(Node
* node
)
89 auto left
= height(node
.left
);
90 auto right
= height(node
.right
);
91 return 1 + (left
> right ? left
: right
);
99 static size_t
count(Node
* node
)
103 return count(node
.left
) + count(node
.right
) + 1;
113 Node
* allocNode(E element
) @nogc
115 Node
* node
= cast(Node
*)common
.xmalloc(Node
.sizeof
);
116 node
.left
= node
.right
= null;
117 node
.priority
= rand();
118 node
.element
= element
;
122 Node
* insert(Node
* node
, E element
) @nogc
125 return allocNode(element
);
126 else if (element
< node
.element
)
128 node
.left
= insert(node
.left
, element
);
129 if (node
.left
.priority
< node
.priority
)
130 node
= rotateR(node
);
132 else if (element
> node
.element
)
134 node
.right
= insert(node
.right
, element
);
135 if (node
.right
.priority
< node
.priority
)
136 node
= rotateL(node
);
139 {} // ignore duplicate
146 void freeNode(Node
* node
)
151 Node
* rotateL(Node
* root
)
153 auto pivot
= root
.right
;
154 root
.right
= pivot
.left
;
159 Node
* rotateR(Node
* root
)
161 auto pivot
= root
.left
;
162 root
.left
= pivot
.right
;
167 void remove(Node
** ppnode
, E element
)
169 Node
* node
= *ppnode
;
171 return; // element not in treap
173 if (element
< node
.element
)
175 remove(&node
.left
, element
);
177 else if (element
> node
.element
)
179 remove(&node
.right
, element
);
183 while (node
.left
&& node
.right
)
185 if (node
.left
.priority
< node
.right
.priority
)
187 *ppnode
= rotateR(node
);
188 ppnode
= &(*ppnode
).right
;
192 *ppnode
= rotateL(node
);
193 ppnode
= &(*ppnode
).left
;
197 *ppnode
= node
.right
;
204 void removeAll(Node
* node
)
208 removeAll(node
.left
);
209 removeAll(node
.right
);
213 int opApplyHelper(const Node
* node
, scope int delegate(ref const E
) nothrow dg
)
218 int result
= opApplyHelper(node
.left
, dg
);
221 result
= dg(node
.element
);
224 return opApplyHelper(node
.right
, dg
);
227 version (CoreUnittest
)
228 bool valid(Node
* node
)
235 if (node
.left
.priority
< node
.priority
)
237 if (node
.left
.element
> node
.element
)
242 if (node
.right
.priority
< node
.priority
)
244 if (node
.right
.element
< node
.element
)
247 return valid(node
.left
) && valid(node
.right
);
253 // randomized unittest for randomized data structure
254 import /*cstdlib = */core
.stdc
.stdlib
: rand
, srand
;
255 import /*ctime = */core
.stdc
.time
: time
;
257 enum OP
{ add, remove
}
258 enum initialSize
= 1000;
265 srand(cast(uint)time(null));
266 treap
.initialize(rand());
270 foreach (i
; 0 .. initialSize
)
273 treap
.insert(data
[$-1]);
274 foreach (e
; data
[0..$-1])
278 continue initialLoop
;
281 _adSort(*cast(void[]*)&data
, typeid(data
[0]));
282 assert(treap
== data
);
283 assert(treap
.valid());
285 for (int i
= randOps
; i
> 0; --i
)
287 ops
~= cast(OP
)(rand() < uint.max
/ 2 ? OP
.add: OP
.remove
);
295 treap
.insert(opdata
[0]);
298 for (i
= 0; i
< data
.length
; ++i
)
299 if (data
[i
] >= opdata
[0])
302 if (i
== data
.length || data
[i
] != opdata
[0])
305 uint tmp
= opdata
[0];
306 for (; i
< data
.length
; ++i
)
314 else if (!data
.length
) // nothing to remove
316 opdata
= opdata
[1..$];
321 uint tmp
= data
[opdata
[0]%data
.length
];
324 for (i
= 0; data
[i
] < tmp
; ++i
)
326 for (; i
< data
.length
-1; ++i
)
330 assert(treap
.valid());
331 assert(treap
== data
);
332 opdata
= opdata
[1..$];
337 assert(treap
== data
);
340 /// Random number generators for internal usage.
343 private ulong rng_state
;
355 @property uint front()
357 return cast(uint)(rng_state
>> 32);
362 immutable ulong a
= 2862933555777941757;
363 immutable ulong c
= 1;
364 rng_state
= a
* rng_state
+ c
;