Undo support for moving nodes of NSOutlineView/NSTreeController - cocoa

I have an NSOutlineView that is bound to an NSTreeController. Items (multiple selection) of the outline view can be reordered through drag & drop.
I would like to add support to undo/redo reordering the outline view. Could anybody point to some sample code showing how to do this?
I'm having a hard time reconstructing the index paths of the moved tree nodes, because as I undo changes, the structure of the tree controller changes, and thus, the index paths of the remaining nodes to put back into their original position.
I use this code to move the nodes initially:
[self.treeController moveNodes:draggedTreeNodes toIndexPath:insertIndexPath];
Note how moveNodes: only takes a single index path as argument. In case of a selection that contains multiple nodes, I can't move everything back in one go, but have to replay changes one by one (running into the above issue of invalidating index paths).

Related

Container of fixed size where items exist within it according to their demand

I'm trying to implement a container with the following characteristics:
The container has a fixed size n.
When an item is inserted into the container, if the item is in the data structure it will be moved to the front of it. If not it will be inserted to the front of the data structure, but the last item at the back of the container will be removed to respect the fixed size n.
Building on for 2, it will be required to check whether an item exists in this container in order to know whether to insert or move an item in the container.
The reasoning behind this container, is to keep frequently accessed items in the container. The cost of inserting a new item into the container is large thus it is in my interest to keep it in the container for as long as it is in demand.
Is there a container/data structure that exists that achieves something similar to what I've described? If not can you provide any advice on how to implement it? I'm using C++ but any examples or pseudocode will be equally appreciated.
Edit:
I suppose what I need is a kind of queue with no duplicate items. The queue needs to be searched to see if an item exists within it, and if so moves it to the front of the queue. A fixed size isn't that difficult to adhere to (just check the size before insertion and if it will go over remove the last item in the queue). Basically this post but not allowing any duplicates in the container, and also fast search capabilities to check if an item is within it.
I'm not following the requirements you gave but this seems like it can be implemented as as a double-ended queue (C++ deque or Java Deque). Each time an element is accessed implies a linear search (can't be avoided), then this element is moved to the front (constant time), and the last element removed (also constant time). This should result that the most frequently accessed elements move to the front of the queue over time, decreasing the real-time cost of a linear search.
A double-ended queue can be implemented as a ring-buffer or as a doubly-linked-list. Since you stated a fixed number of elements, the ring buffer seems like the better option.
However, I can't vouch for the implementations of C++ or Java deque.. you may look at the source code to see if its backed as an array or a linked node structure.
Maybe wrap a priority queue with elements having a last-accessed-time attribute?
You may check Splay Tree. If you do some operation on element X, that element move to root.

How to implement a collection that supports real-time filtering?

I want to implement a mutable sequential collection FilteredList that wraps another collection List and filters it based on a predicate.
Both the wrapped List and the exposed FilteredList are mutable and observable, and should be synchronized (so for example, if someone adds an element to List that element should appear in the correct position in FilteredList, and vice versa).
Elements that don't satisfy the predicate can still be added to FilteredList, but they will not be visible (they will still appear in the inner list).
The collections should support:
Insert(index,value) which inserts an element value at position index, pushing elements forward.
Remove(index) which removes the element at position index, moving all proceeding elements back.
Update(index, value), which updates the element at position index to be value.
I'm having trouble coming up with a good synchronization mechanism.
I don't have any strict complexity bounds, but real world efficiency is important.
The best way to avoid synchronization difficulties is to create a data structure that doesn't need them: use a single data structure to present the filtered and unfiltered data.
You should be able to do that with a modified skip list (actually, an indexable skip list), which will give you O(log n) access by index.
What you do is maintain two separate sets of forward pointers for each node, rather than just one set. The one set is for the unfiltered list, as in the normal skip list, and the other set is for the filtered list.
Adding to or removing from the list is the same for the filtered and unfiltered lists. That is, you find the node at index by following the appropriate filtered or unfiltered links, and then add or remove the node, updating both sets of link pointers.
This should be more efficient than a standard sequential list, because insertion and removal don't incur the cost of moving items up or down to make a hole or fill a gap; it's all done with references.
It takes a little more space per node, though. On average, skip list requires two extra references per node. Since you're building what is in effect two skip lists in one, expect your nodes to require, on average, four extra references per node.
Edit after comment
If, as you say, you don't control List, then you still maintain this dual skip list that I described. But the data stored in the skip list is just the index into List. You said that List is observable, so you get notification of all insert and delete operations, so you should be able to maintain an index by reacting to all notifications.
When somebody wants to operate on FilteredList, you use the filtered index links to find the List index of the FilteredList record the user wanted to affect. Then you pass the request onto List, using the translated index. And then you react to the observable notification from List.
Basically, you're just maintaining a secondary index into List, so that you can translate FilteredList indexes into List indexes.

What are labels and indices in Neo4j?

I am using neo4j-core gem (Neo4j::Node API). It is the only MRI-compatible Ruby binding of neo4j that I could find, and hence is valuable, but its documentation is a crap (it has missing links, lots of typographical errors, and is difficult to comprehend). In the Label and Index Support section of the first link, it says:
Create a node with an [sic] label person and one property
Neo4j::Node.create({name: 'kalle'}, :person)
Add index on a label
person = Label.create(:person)
person.create_index(:name)
drop index
person.drop_index(:name)
(whose second code line I believe is a typographical error of the following)
person = Node4j::Label.create(:person)
What is a label, is it the name of a database table, or is it an attribute peculiar to a node?
If it is the name of a node, I don't under the fact that (according to the API in the second link) the method Neo4j::Node.create and Neo4j::Node#add_label can take multiple arguments for the label. What does it mean to have multiple labels on a node?
Furthermore, If I repeat the create command with the same label argument, it creates a different node object each time. What does it mean to have multiple nodes with the same name? Isn't a label something to identify a node?
What is index? How are labels and indices different?
Labels are a way of grouping nodes. You can give the label to many nodes or just one node. Think of it as a collection of nodes that are grouped together. They allow you to assign indexes and other constraints.
An index allows quick lookup of nodes or edges without having to traverse the entire graph to find them. Think of it as a table of direct pointers to the particular nodes/edges indexed.
As I read what you pasted from the docs (and without, admittedly, knowing the slightest thing about neo4j):
It's a graph database, where every piece of data is a node with a certain amount of properties.
Each node can have a label (or more, presumably?). Think of it as a type -- or perhaps more appropriately, in Ruby parlance, a Module.
It's a database, so nodes can be part of an index for quicker access. So can subsets of nodes, and therefor nodes with a certain label.
Put another way: Think of the label as the table in a DB. Nodes as DB rows, which can belong to one or more labels/tables, or no label/table at all for that matter. And indexes as DB indexes on sets of rows.

Find isolated groups of blocks in a grid

I have a grid of "blocks" (in the form of a 2D array, could be 5*5, 17*17 or whatever) where I can add or remove blocks at will, except for the one at the center that should always remain there.
I can place blocks if they have a local neighbour : on their right/left/up/down (at least one of them).
By removing some blocks, it may leave other blocks isolated with no "connection" to the center-block, and I want to avoid this.
I'm looking for a quick solution to check if all my blocks have a connection to the center, the simplest possible (in terms of coding, I can accept to have a non optimal solution since this is supposed to be on executed on very small data and not so often). The first thing that came to my mind was to implement this as a path search but that seems overkill.
I'm using C++ but that should not make any difference.
You need to find the connected components using DFS/BFS.Construct the initial graph and as you add new blocks, you can add new edges, or when you remove blocks you can remove edges.When you remove a block, temporarily delete those edges in the graph and check if it causes two pieces of the graph to disconnect.This is simple, carry out DFS again.If it does not disconnect you can remove that block.
DFS is only about 8 lines to implement, and for small data sets this is elegant.

Efficient mass modification of persistent data structures

I understand how typically trees are used to modify persistent data structures (create a new node and replace all it's ancestors).
But what if I have a tree of 10,000's of nodes and I need to modify 1000's of them? I don't want to go through and create 1000's of new roots, I only need the one new root that results from modifying everything at once.
For example:
Let's take a persistent binary tree for example. In the single update node case, it does a search until it finds the node, creates a new one with the modifications and the old children, and creates new ancestors up to the root.
In the bulk update case could we do:
Instead of just updating a single node, you're going to update 1000 nodes on it in one pass.
At the root node, the current list is the full list. You then split that list between those that match the left node and those that match the right. If none match one of the children, don't descend to it. You then descend to the left node (assuming there were matches), split its search list between its children, and continue. When you have a single node and a match, you update it and go back up, replacing and updating ancestors and other branches as appropriate.
This would result in only one new root even though it modified any number of nodes.
These kind of "mass modification" operations are sometimes called bulk updates. Of course, the details will vary depending on exactly what kind of data structure you are working with and what kind of modifications you are trying to perform.
Typical kinds of operations might include "delete all values satisfying some condition" or "increment the values associated with all the keys in this list". Frequently, these operations can be performed in a single walk over the entire structure, taking O(n) time.
You seem to be concerned about the memory allocation involved in creating "1000's of new roots". Typical allocation for performing the operations one at a time would be O(k log n), where k is the number of nodes being modified. Typical allocation for performing the single walk over the entire structure would be O(n). Which is better depends on k and n.
In some cases, you can decrease the amount of allocation--at the cost of more complicated code--by paying special attention to when changes occur. For example, if you have a recursive algorithm that returns a tree, you might modify the algorithm to return a tree together with a boolean indicating whether anything has changed. The algorithm could then check those booleans before allocating a new node to see whether the old node can safely be reused. However, people don't usually bother with this extra check unless and until they have evidence that the extra memory allocation is actually a problem.
A particular implementation of what you're looking for can be found in Clojure's (and ClojureScript's) transients.
In short, given a fully-immutable, persistent data structure, a transient version of it will make changes using destructive (allocation-efficient) mutation, which you can flip back into a proper persistent data structure again when you're done with your performance-sensitive operations. It is only at the transition back to a persistent data structure that new roots are created (for example), thus amortizing the attendant cost over the number of logical operations you performed on the structure while it was in its transient form.

Resources