Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 在钱包中最佳地重新排列卡片?_Algorithm_Data Structures_Hash_Language Agnostic_Linked List - Fatal编程技术网

Algorithm 在钱包中最佳地重新排列卡片?

Algorithm 在钱包中最佳地重新排列卡片?,algorithm,data-structures,hash,language-agnostic,linked-list,Algorithm,Data Structures,Hash,Language Agnostic,Linked List,前几天我出去买杂货,需要在钱包里搜索我的信用卡、客户奖励(忠诚)卡和照片ID。我的钱包里有几十张其他卡(工作ID、其他信用卡等),所以我花了一段时间才找到所有东西 我的钱包里有六个插槽,我可以把卡放在里面,每个插槽里的第一张卡在任何时候都是可见的。如果我想找到一张特定的卡,我必须记住它在哪个插槽中,然后逐个查看插槽中的所有卡来找到它。它越靠近插槽的前端,就越容易找到它 我突然想到,这几乎是一个数据结构问题。假设您有一个由k个链表组成的数据结构,每个链表可以存储任意数量的元素。您希望以最小化查找的

前几天我出去买杂货,需要在钱包里搜索我的信用卡、客户奖励(忠诚)卡和照片ID。我的钱包里有几十张其他卡(工作ID、其他信用卡等),所以我花了一段时间才找到所有东西

我的钱包里有六个插槽,我可以把卡放在里面,每个插槽里的第一张卡在任何时候都是可见的。如果我想找到一张特定的卡,我必须记住它在哪个插槽中,然后逐个查看插槽中的所有卡来找到它。它越靠近插槽的前端,就越容易找到它

我突然想到,这几乎是一个数据结构问题。假设您有一个由k个链表组成的数据结构,每个链表可以存储任意数量的元素。您希望以最小化查找的方式将元素分布到链接列表中。您可以使用您想要的任何系统将元素分布到不同的列表中,并且可以随时对列表重新排序。鉴于这种设置,在以下任何假设条件下,是否有一种最佳方式来排列列表:

  • 您可以预先访问每个元素,并且访问是独立的,或者
  • 您事先不知道何时访问哪些元素
  • 我在钱包中使用的非正式系统是根据用例(ID、信用卡、忠诚卡等)将卡“散列”到不同的插槽中,然后将每个插槽中的元素按访问频率大致排序。然而,也许有更好的方法来做到这一点(例如,将k个最常用的元素存储在每个插槽的前面,而不管它们的用例如何)

    有解决这个问题的已知系统吗?这是数据结构中众所周知的问题吗?如果是,最佳解决方案是什么


    (如果这看起来与编程无关:我可以想象一个应用程序,其中用户有几个常用项的下拉列表,并希望以一种最小化查找特定项所需时间的方式对这些项进行排序。)

    您需要查看跳过列表。在有特快列车和普通列车的列车系统中,也存在类似的问题。特快列车只在特快站停车,而普通列车在普通站和特快站停车。应在何处设置快速停车点,以便在从起点站到任何车站的行驶过程中尽量减少平均停车次数

    解决方案是使用三元数的站(即,在1、3、6、10等处,T_n=n*(n+1)/2)


    这是假设所有站点(或卡)访问的可能性相同。

    虽然不是一般k的完整答案,但对k=1情况下几种动态列表更新算法的摊销复杂性进行了有益的分析。事实证明,向前移动非常好:假设每个项目的访问概率固定,它所需的步数(移动和交换)不会超过最优(静态)算法所需步数的两倍,在该算法中,所有元素都以非递增的概率顺序列出


    有趣的是,其他两种看似合理的启发式方法——即在找到所需元素后与前一个元素交换,并根据显式频率计数维持顺序——并不具有这种令人满意的特性。奥托,在p。2他们提到Rivest之前的一篇论文表明,与previous交换的任何访问的预期摊销成本如果您事先知道n张卡的访问概率,并且您有k个钱包插槽,并且访问是独立的,那么贪婪的解决方案是否是最优的,这不是很清楚吗?也就是说,最频繁访问的k卡放在口袋的前面,其次是最频繁访问的k卡放在口袋的后面,依此类推?(你永远不希望低概率卡排在高概率卡之前。)

    如果你不知道访问概率,但你知道它们的存在,并且卡片访问是独立的,我可以想象对卡片进行类似的排序,但是按照目前为止看到的访问次数是渐进最优的。(移到前面也很酷,但我看不出有明显的理由在这里使用它。)


    如果你同时惩罚牌的移动,也许你会得到一些有趣的东西;如果我对卡片访问有任何已知的概率分布,不管是独立的还是非独立的,每次访问时我都会贪婪地对卡片重新排序。

    在列表中搜索以查找特定项是一个O(n)操作,这是一个最佳操作。将其划分为k个列表(提供您可以知道要查看哪个列表)使其成为O(n)/k,这对于n>>k来说是无关紧要的。将更频繁访问的项目放在列表的前面可以有效地减少n.@Dale-虽然这是真的,但您可以想象某种类似于splay树的算法,即使单个查找速度很慢,也能提供良好的摊销性能。您还可以设计一种数据结构,通过确保高优先级元素在链表中的位置不太深,使其能够非常快速地访问。在最坏的情况下,你不能比O(n/k)做得更好,这并不一定意味着你对所有访问模式都能做到最好。@templatetypedef-当然,但是,你必须弄清楚维护列表的开销是否小于保存的开销。@Dale M-哦,绝对是这样。这个问题的关键是看是否有一个合法的方案比简单的平均分配系统更有效。我希望有@templatetypedef—一种低开销的算法是将刚访问的项目移动到前端—频繁访问的项目将停留在前端附近,而访问较少的项目将后退。开销基本上为零-您已经找到了该项目,因此将其移动到前面很简单,您不需要这样做