Please suggest a data structure for representing a list of records in memory
. Each record is made up of:
The data structure should support implementation of the following operations efficiently:
My main problem is efficient implementation of GetRecord(rank), because ranks can change frequently.
I guess an in-memory DBMS
would be a good solution, but please don't suggest it; please suggest a data structure.
Basically, you'll just want a pair of balanced search trees, which will allow O(lg n) insertion, deletion, and getRecord operations. The trick is that instead of storing the actual data in the trees, you'll store pointers to a set of record objects, where each record object will contain 5 fields:
The name tree is only modified when new records are added and when records are deleted. The point tree is modified for insertions and deletions, but also for updates, where the appropriate record is found, has its point-tree pointer removed, its point count updated, then a new pointer added to the point-tree.
As you mention, you can use a hash table instead for the name tree if you like. The key here is that you simply maintain separate sorted indexes into a set of otherwise unordered records that themselves contain pointers to their index nodes.
The point tree will be some variation on an order statistic tree, which rather than being a specific data structure, is an umbrella term for a binary search tree whose operations are modified to maintain an invariant which makes the requested rank-related operations more efficient than walking the tree. The details of how the invariants are maintained depend on the underlying balanced search tree (red-black tree, avl tree, etc) used.
A skiplist + hashmap should work.
Here is an implementation in Go: https://github.com/wangjia184/sortedset
Every node in the set is associated with these properties.
key
is an unique identity of the node, which is "User name" in your case.value
is any value associated with the nodescore
a number decides the order(rank) in the set, which is "Points" in your caseEach node in the set is associated with a key. While keys are unique, scores may be repeated. Nodes are taken in order (from low score to high score) instead of ordered afterwards. If scores are the same, the node is ordered by its key in lexicographic order. Each node in the set also can be accessed by rank, which represents the position in the sorted set.
A typical use case of sorted set is a leader board in a massive online game, where every time a new score is submitted you update it using AddOrUpdate() method. You can easily take the top users using GetByRankRange() method, you can also, given an user name, return its rank in the listing using FindRank() method. Using FindRank() and GetByRankRange() together you can show users with a score similar to a given user. All very quickly.
Look for a DBMS that includes a function to select a record by sequential record number.
See: How to select the nth row in a SQL database table?
Construct a table with a UserName column and a Points column. Make UserName the primary index. Construct a secondary non-unique maintained index on Points.
To get the record with rank R, select the index on Points and move to record R.
This makes the DBMS engine do most of the work and keeps your part simple.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With