You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
description = "A linked list implementation with unique features and an extended list of constant time methods providing high performance traversals and mutations."
Copy file name to clipboardExpand all lines: README.md
+10-10Lines changed: 10 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -71,7 +71,7 @@ Linked lists are all about traversal. And hence, the linked list, specifically t
71
71
*[`iter_backward_from(idx: &DoublyIdx<T>)`](https://docs.rs/orx-linked-list/latest/orx_linked_list/trait.DoublyIterable.html#method.iter_backward_from) iterates forward starting from the node with the given index to the front
72
72
*[`ring_iter(pivot_idx: &DoublyIdx<T>)`](https://docs.rs/orx-linked-list/latest/orx_linked_list/trait.DoublyIterable.html#method.ring_iter) iterates forward starting from the pivot node with the given index until the node before the pivot node, linking back to the front and giving the list the **circular behavior**
73
73
*[`iter_links()`](https://docs.rs/orx-linked-list/latest/orx_linked_list/trait.DoublyIterable.html#method.iter_links) iterates over the links of the list
74
-
*[`iter_x()`](https://docs.rs/orx-linked-list/latest/orx_linked_list/trait.DoublyIterable.html#method.iter_x) iterates over elements in an arbitrary order, which is often faster when the order is not required
74
+
*[`iter_x()`](https://docs.rs/orx-linked-list/latest/orx_linked_list/type.DoublyList.html#method.iter_x) iterates over elements in an arbitrary order, which is often faster when the order is not required
75
75
76
76
As typical, above-mentioned methods have the "_mut" suffixed versions for iterating over mutable references.
Due to the feature of the [`Recursive`](https://docs.rs/orx-split-vec/3.8.0/orx_split_vec/struct.Recursive.html) growth strategy of the underlying SplitVec that allows merging vectors and the nature of linked lists, appending two lists is a constant time operation.
119
119
120
-
See [`append_front`](https://docs.rs/orx-linked-list/latest/orx_linked_list/type.DoublyList.html#method.append_front) and [`iter_back`](https://docs.rs/orx-linked-list/latest/orx_linked_list/type.DoublyList.html#method.append_back).
120
+
See [`append_front`](https://docs.rs/orx-linked-list/latest/orx_linked_list/type.DoublyList.html#method.append_front) and [`append_back`](https://docs.rs/orx-linked-list/latest/orx_linked_list/type.DoublyList.html#method.append_back).
@@ -326,7 +326,7 @@ This crate aims to overcome the concerns with the following approach:
326
326
327
327
▶ There is also <ins>no choice</ins> between a `VecDeque` and a linked list. VecDeque is very efficient when we need a double ended queue. However, we need a linked list when we need lots of mutations in the sequence and positions of elements. They solve different problems.
328
328
329
-
For instance, a `DoublyList` with indices is a better fit for a problem where we will continuously mutate positions of elements in a collection, moving them around. A very common use case is due to the classical traveling salesman problem where we keep changing positions of cities with the aim to find shorter and shorter tours.
329
+
For instance, a `DoublyList` with indices is a better fit for a problem where we will continuously mutate positions of elements in a collection, moving them around. A very common use case occurs due to the classical traveling salesman problem where we keep changing positions of cities with the aim to find shorter and shorter tours.
330
330
331
331
See the example in [tour_mutations.rs](https://github.com/orxfun/orx-linked-list/blob/main/examples/tour_mutations.rs).
332
332
@@ -364,7 +364,7 @@ impl TourLinkedList {
364
364
}
365
365
```
366
366
367
-
Although clear from the worst time complexity of the implementations, [doubly_shuffling_around.rs](https://github.com/orxfun/orx-linked-list/blob/main/benches/doubly_shuffling_around.rs) benchmark demonstrates the dramatic difference. At each setting, we perform 10k `insert_after` moves with tours of different lengths. The following table summarizes the required time in macro-seconds for each setting.
367
+
Although clear from the worst time complexity of the implementations, [doubly_shuffling_around.rs](https://github.com/orxfun/orx-linked-list/blob/main/benches/doubly_shuffling_around.rs) benchmark demonstrates the dramatic difference. At each setting, we perform 10k `insert_after` moves with tours of different lengths. The following table summarizes the required time in microseconds for each setting.
368
368
369
369
| num_cities | DoublyList | Vec |
370
370
|------------|------------|-----------|
@@ -379,26 +379,26 @@ Although clear from the worst time complexity of the implementations, [doubly_sh
379
379
380
380
As mentioned, node indices are associated with elements rather than positions.
381
381
* The linked list can provide safe access through node indices due to the fact that the underlying storage is a [`SplitVec`](https://crates.io/crates/orx-split-vec) which implements [`PinnedVec`](https://crates.io/crates/orx-pinned-vec), keeping the memory positions of its elements unchanged, unless they are explicitly changed.
382
-
* Therefore, the list is able to know if a node index is pointing to a valid memory position belonging to itself. Therefore, we are not allowed use a node index created from one list on another list:
382
+
* Therefore, the list is able to know if a node index is pointing to a valid memory position belonging to itself, and prevents to use a node index created from one list on another list:
383
383
*`get`, `is_valid`, `idx_err` returns None, false and `NodeIdxErr::OutOfBounds`, respectively.
384
384
* Further, when an element is removed from the list, its position is not immediately filled by other elements. Therefore, the index still points to the correct memory position and the list is able to know that the element is removed.
385
385
*`get`, `is_valid`, `idx_err` returns None, false and `NodeIdxErr::RemovedNode`, respectively.
386
386
387
-
Clearly, such a memory policy might leave gaps in the storage and lead to low utilization of memory. However, the lists are self-organizing as follows:
387
+
Clearly, such a memory policy leaves gaps in the storage and utilization of memory becomes important. Therefore, the linked lists are self-organizing as follows:
388
388
* Whenever an element is removed, the utilization of nodes is checked. Node utilization is the ratio of active nodes to occupied nodes.
389
389
* Whenever the utilization falls below a certain threshold (75% by default), positions of closed nodes are reclaimed and utilization is brought back to 100%.
390
390
391
391
When, a node reorganization is triggered, node indices collected beforehand become invalid. The linked lists, however, have a means to know that the node index is now invalid by comparing the so called memory states of the index and list. If we attempt to use a node index after the list is reorganized and the index is invalidated, we safely get an error:
392
392
*`get`, `is_valid`, `idx_err` returns None, false and `NodeIdxErr::ReorganizedCollection`, respectively.
393
393
394
-
**In summary, we can always make sure whether or not using a node index is safe and allowed. Further, we can never have an unchecked / unsafe access to elements that we are not supposed to.**
394
+
*In summary, we can make sure whether or not using a node index is safe. Further, we cannot have an unchecked / unsafe access to elements that we are not supposed to.*
395
395
396
-
On the other hand, it sounds inconvenient that the indices can implicitly be invalidated. However, the situation is actually not complicated or unpredictable.
396
+
It sounds inconvenient that the indices can implicitly be invalidated. The situation, however, is not complicated or unpredictable.
397
397
* First, we know that growth can never cause reorganization; only removals can trigger it.
398
398
* Second, we have the lazy versions of the lists which will never automatically reorganize nodes. Collected indices will always be valid unless we explicitly call `reclaim_closed_nodes`.
399
-
* Third, it is a free operation to switch between auto-reclaim and lazy-reclaim modes.
399
+
* Third, it is free to transform between auto-reclaim and lazy-reclaim modes.
400
400
401
-
**Therefore, we can have full control on the valid lifetime of our indices.**
401
+
*Therefore, we can have full control on the valid lifetime of our indices.*
402
402
403
403
<details>
404
404
<summarystyle="font-weight:bold;">Controlling Validity of Node Indices</summary>
0 commit comments