Algorithm 排行榜的高效数据结构,即记录列表(名称、点数)-高效搜索(名称)、搜索(排名)和更新(点数)

Algorithm 排行榜的高效数据结构,即记录列表(名称、点数)-高效搜索(名称)、搜索(排名)和更新(点数),algorithm,list,data-structures,hashtable,record,Algorithm,List,Data Structures,Hashtable,Record,请建议一种数据结构,用于表示内存中的记录列表。每个记录由以下部分组成: 用户名 要点 排名(基于点)-可选字段-可以存储在记录中,也可以动态计算 数据结构应有效支持以下操作的实施: 插入(记录)-可能更改现有记录的列组 删除(记录)-可能更改现有记录的列组 GetRecord(名称)-可能一个哈希表就可以了 GetRecord(排名) 更新(点)-可能更改现有记录的列组 我的主要问题是GetRecord(rank)的高效实现,因为等级可以频繁更改 我想内存DBMS将是一个很好的解决方案,但请

请建议一种数据结构,用于表示
内存中的记录列表
。每个记录由以下部分组成:

  • 用户名
  • 要点
  • 排名(基于点)-可选字段-可以存储在记录中,也可以动态计算
数据结构应有效支持以下操作的实施:

  • 插入(记录)-可能更改现有记录的列组
  • 删除(记录)-可能更改现有记录的列组
  • GetRecord(名称)-可能一个哈希表就可以了
  • GetRecord(排名)
  • 更新(点)-可能更改现有记录的列组
  • 我的主要问题是GetRecord(rank)的高效实现,因为等级可以频繁更改


    我想内存
    DBMS
    将是一个很好的解决方案,但请不要建议它;请建议一种数据结构。

    查找包含按顺序记录编号选择记录功能的DBMS

    见:

    用UserName列和Points列构造一个表。将用户名作为主索引。在点上构造辅助非唯一维护索引

    要获得秩为R的记录,请选择点上的索引并移动到记录R


    这使得DBMS引擎可以完成大部分工作,并使您的部分保持简单。

    基本上,您只需要一对平衡的搜索树,它将允许O(lg n)插入、删除和getRecord操作。诀窍在于,不是将实际数据存储在树中,而是存储指向一组记录对象的指针,其中每个记录对象将包含5个字段:

  • 用户名
  • 点值
  • 等级
  • 指向名称树中引用对象的节点的指针
  • 指向点树中引用对象的节点的指针
  • 只有在添加新记录和删除记录时,才会修改名称树。修改点树以进行插入和删除,也可以进行更新,在找到相应记录的情况下,删除点树指针,更新点计数,然后向点树添加新指针

    正如您所提到的,如果您愿意,可以使用哈希表代替名称树。这里的关键是,您只需将单独的已排序索引维护到一组原本无序的记录中,这些记录本身包含指向其索引节点的指针



    点树将是上的一些变体,而不是特定的数据结构,是二元搜索树的总称,其操作被修改以保持不变,这使得请求的秩相关操作比遍历树更有效。如何维护不变量的细节取决于所使用的底层平衡搜索树(红黑树、avl树等)。

    skiplist+hashmap应该可以工作

    以下是Go中的一个实现:

    集合中的每个节点都与这些属性关联

    • 是节点的唯一标识,在您的案例中是“用户名”
    • value
      是与节点关联的任何值
    • score
      一个数字决定集合中的顺序(等级),在您的案例中是“分数”
    集合中的每个节点都与一个键相关联。虽然钥匙是独一无二的, 分数可以重复。节点按顺序排列(从低分到 高分)而不是事后订购。如果分数相同,则 节点按其键按字典顺序排序。中的每个节点 也可以通过等级访问集合,等级表示集合中的位置 排序集

    排序集的一个典型用例是大规模在线应用程序中的领导板 游戏中,每次提交新分数时,您都使用 AddOrUpdate()方法。您可以使用 方法,您还可以在给定用户名的情况下返回其 使用findawed()方法在列表中排名。使用find()和 GetByRankRange()一起,您可以向用户显示类似于 给定用户。一切都很快


    感谢您的回答,但我正在寻找一种数据结构方法使用名称树(O(lgn))查找记录;使用对象中存储的指针在点树中查找对应的节点;移除该节点(O(lgn));更新总分;在点树中插入一个新节点(O(lg n));并更新对象记录中的指针。但这与更新记录或其他记录的列组无关,对吗?排名基于点。点树中节点的排名基本上是该节点右子树中的节点数(加1)。您可以在平衡二叉搜索树的插入和删除操作期间保持此计数。那么,您的意思是,具有最大点数(秩=1)的记录将是点树中唯一的叶节点,而具有最小点数(秩=n)的记录将是没有剩余子节点的根节点吗?实际上,点树是一个右偏树,对吗?这是一个有效的实现吗?不,你需要一个平衡的树来实现一个有效的实现,但是在任何搜索树中,一个项目都比其左子树中的每个元素都大,比其右子树中的每个元素都小。秩1将是最右边的节点(在根的右子节点之后),秩n将是最左边的节点。根是(近似)中间元素。什么是键,什么是值?你能在答案中包含更多的算法吗?顺便说一句,这正是redis排序列表的实现方式@zuselegacy是的,但这个问题需要一个过程中的问题