是否可以创建一个具有 ArrayList 属性且复杂度为 log(n) 的 Map?

2023-12-20

我正在尝试构建一个通用数据结构,它需要保存键和值,同时跟踪索引,其中键和值被放入其中,就像 arraylist 那样,复杂度为 O(log n) 或更少。

我尝试解决这个问题,并创建了各种具有整数索引和值的 TreeMap,反之亦然,键也相同。

为了更清楚地说明,索引象征着用户的插入顺序。所以如果我有 3 个元素,那么它们的索引是 0 1 2,如果元素 0 被删除,那么我需要将 1 推到 0,将 2 推到 1,然后将添加一个索引为 2 的新元素。

我的问题是,当我删除一个键及其值时,如果我想在正确的索引中插入下一个键和值,我必须确保所有旧的键和值都被设置回 1。我不知道该怎么做并且不会陷入 O(n) 复杂度。

我的目标是使用现有的数据结构并将它们混合以获得此结果,请查看我在需要时实现的方法。

我添加我的代码以供参考,任何帮助将不胜感激。

谢谢

Tom

import java.util.Collection;
import java.util.HashMap;
import java.util.TreeMap;
import java.util.Map;

public class SuperStruct<K,V> 
{
    private Map<K,V> mInternalKeyToValueMap;//all the keys and their values 
    private Map<Integer,V> mIndexToValueMap;//index's for values according to the entrance order to 
    private Map<V,Integer> mValueToIndexMap;//values and their index's
    private Map<Integer,K> mIndexToKeyMap;//index's and their keys according to entrance order
    private Map<K,Integer> mKeyToIndexMap;//keys and their index's
    private int mNextIndex;//index for the data structure according to the order data was received by user

    public SuperStruct(){
        mInternalKeyToValueMap = new TreeMap<K,V>();
        mIndexToValueMap = new TreeMap<Integer,V>();
        mValueToIndexMap = new TreeMap <V,Integer>();
        mIndexToKeyMap = new TreeMap <Integer, K>();
        mKeyToIndexMap = new TreeMap <K,Integer>();     
    }
    public boolean containsKey(Object key) {
        boolean containable = mInternalKeyToValueMap.containsKey(key);
        return containable;
    }

    public boolean containsValue(Object value) {
        boolean containable = mValueToIndexMap.containsKey(value);
        return containable;
    }

    public V get(Object key) {
        if(mInternalKeyToValueMap.containsKey(key)){
            V value = mInternalKeyToValueMap.get(key);
            return value;
        }
        return null;
    }



    public Collection<K> keySet() {

        return mInternalKeyToValueMap.keySet();
    }
    /**
     * This method is putting the key and the value in the main TreeMap "mInternalKeyToValueMap", while on the mean time updating 4 other TreeMaps
     * with data regarding to the index in which data was received from the user.
     * all in all this method runs in complexity of 6*(O(log n)) that sums down to O(log n) cause constants don't calculate over the whole 
     * Complexity calculation
     * In case that a key already had a mapping to it and we overwrite the value we will run in complexity of 11*(O(log n)) which still sums down to O(log n) 
     * cause constants don't calculate over the whole 
     */

    public V put(K key, V value) {
        if(mValueToIndexMap.containsKey(value))//preventing duplications of value
            return value;
            if(mInternalKeyToValueMap.containsKey(key)){//when a key already exist in system and we want to overwrite its value
                int indexToDelete = mKeyToIndexMap.get(key);//we get the index of the value we over-write
                V value1 = mIndexToValueMap.get(indexToDelete);//using this index we get the value
                mValueToIndexMap.remove(value1);//we remove the value and its index
                mIndexToValueMap.remove(indexToDelete);//we remove the index and its value
            }
            mInternalKeyToValueMap.put(key, value);//putting the new value for the key in the main TreeMap
            mValueToIndexMap.put(value, mNextIndex);//populating the TreeMap of values and their index's - the order we received them from the user
            mIndexToValueMap.put(mNextIndex, value);//This TreeMap holds the index's for each value according to the order of insertion by user
            mIndexToKeyMap.put(mNextIndex, key);//This TreeMap holds the index's for each key according to the order of insertion by user
            mKeyToIndexMap.put(key,mNextIndex);//populating the TreeMap of keys and their index's - the order we received them from the user
            ++mNextIndex;//advancing the index which mark the insertion order of arguments to structure
            return null;

    }


    public V remove(Object key) {   
        if(mInternalKeyToValueMap.containsKey(key)==true && (mInternalKeyToValueMap.get(key)!=null))
        {
            V value = mInternalKeyToValueMap.get(key);
            mInternalKeyToValueMap.remove(key);//removing map for the value 
            int mIndexToRemoveValue = mValueToIndexMap.get(value);//getting the right index to remove the value
            mIndexToValueMap.remove(mIndexToRemoveValue);//vacating the value for this index
            mIndexToKeyMap.remove(mIndexToRemoveValue);//vacating the key for this index
            mKeyToIndexMap.remove(key);//removing a key and index in the keyToIndex Map
            mValueToIndexMap.remove(value);//removing a key and index in the ValueToIndex Map
            return value;

        }
        return null;
    }


    public Collection<V> values() {     
        return mInternalKeyToValueMap.values();
    }

    public Collection<V> getStrcutureSorted(){
        return mValueToIndexMap.keySet();
    }

    public V getValueByIndex(int index){//return the index in which the value sits in, if not present null 
        V value = mIndexToValueMap.get(index);
            return value;
    }

    public Integer getIndexByKey(K key){
        Integer returnable = mKeyToIndexMap.get(key);
        if(returnable == null)
            return -1;
        return returnable;


    }
    public K getKeyByIndex(int index){
        return mIndexToKeyMap.get(index);
    }
    }

这是一个有趣的难题。感觉应该是可以的,但细节却难以捉摸。问题出在删除后的索引更新操作中。例如,如果索引存储在树节点中,则在删除操作后平均必须更改 n/2 个索引,这会破坏您所追求的 O(log n) 属性。

如果您同时将对象存储在树和 ArrayList 中,那么仍然存在在 ArrayList 中定位对象的问题,我无法在小于 O(n) 的时间内以简单的方式完成工作。 ArrayList 可能有一些变化,也许是自定义构造,但这似乎需要大量工作。

相反,我建议您考虑红黑树或类似的平衡树,并进行修改通过序数索引访问红黑树 https://stackoverflow.com/questions/9953557/red-black-tree-access-by-ordinal-index:对于树的每个节点,还存储以给定节点为根的子树中的节点数。在插入和删除操作期间,您必须更新受旋转操作影响的所有节点的计数。这仍然可以在 O(log n) 时间内完成,但很复杂。

然后,像往常一样,通过通常的递归算法,对第 k 个最小(或最大)元素的二分搜索也将在 O(log n) 时间内运行。

以下是该技术的更多参考:http://www.cs.usfca.edu/~galles/cs673/lecture/lecture8.pdf http://www.cs.usfca.edu/~galles/cs673/lecture/lecture8.pdf, http://fdatamining.blogspot.ca/2011/09/function-red-black-tree-with-dynamic.html http://fdatamining.blogspot.ca/2011/09/functional-red-black-tree-with-dynamic.html, http://en.wikipedia.org/wiki/Order_statistic_tree http://en.wikipedia.org/wiki/Order_statistic_tree。这应该可以帮助你开始。

更新:实施细节

您要做的就是创建两棵树。其中一个可以是普通的平衡树(如红黑树),用于保存对带有键/值对的对象的引用。您可以搜索键并在 O(log n) 中获取相应的值;插入和删除也将是 O(log n)。此外,第一棵树中的节点将保存对第二棵树(如下)中节点的引用。

第二棵树也将保存对第一棵树中节点的引用,但它将是一个顺序统计树,如上面讨论的那样。插入总是将新项目放置在树的右端。

对此数据结构的插入操作将是按键普通插入第一棵树,插入顺序统计树的右侧,并且每个插入节点中的引用将更新为指向另一个节点中的适当位置树。

可以在第一棵树上对给定键进行搜索操作,时间复杂度为 O(log n),这将返回适当的值,并且在对另一棵树的引用之后,可用于查找节点的“顺序统计量”通过向上遍历树到根并执行简单计算,在 O(log n) 时间内找到第二棵树。

可以在 O(log n) 时间内对第二棵树完成队列中第 k 个位置的搜索操作,返回对第二棵树的引用,可以取消引用该第二棵树以获得关联的键/值对。

在删除任一树中之前,都会先引用对另一棵树的引用,然后删除第一棵树中的节点,然后删除另一棵树中的相应节点,这两个操作都是 O(log n) 操作。

我想就是这样。一切都可以在 O(log n) 时间内完成。第二棵树的空间成本很小,但它只包含引用;空间仍然是 O(n)。

那样有用吗?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是否可以创建一个具有 ArrayList 属性且复杂度为 log(n) 的 Map? 的相关文章

  • Python OO程序结构规划

    我是 OOP 的初学者 我想创建一个包含三个类 A B 和 C 的程序 该类的每个实例都由一组特征 Achar1 Achar2 等定义 该程序应该创建uses由 A 元素 B 元素和 C 元素以及开始日期和结束日期组成 A 和 B 都有子类
  • 错误:找不到符号 ArrayList

    我正在尝试创建某种列表来存储数组 表 中的值 我在这里使用数组列表 但我应该使用列表吗 但是 每次我尝试编译时 它都会引发以下错误 找不到标志 符号 ArrayList类 位置 玩家类 TablePlayer 代码如下 public cla
  • 在Python中寻找坐标系中某些点之间的最短路径

    我编写了一个代码 可以在坐标系中的特定宽度和长度范围内生成所需数量的点 它计算并列出我使用欧几里德方法生成的这些点的距离矩阵 我的代码在这里 import pandas as pd from scipy spatial import dis
  • SQL 执行计划是基于架构还是数据,或者两者兼而有之?

    我希望这个问题不太明显 我已经找到了很多关于解释执行计划的好信息 但有一个问题我还没有找到答案 该计划 更具体地说是相对 CPU 成本 仅基于架构 还是数据库中当前的实际数据 我尝试对我的产品数据库中需要索引的位置进行一些分析 但正在使用我
  • python数据结构(类似设置)在添加重复项时抛出异常

    我正在寻找一种在添加重复元素时会引发异常的数据结构 我发现的最接近的是collections Counter gt gt gt from collections import Counter as counter gt gt gt c co
  • 如何为 pg_trgm `'term' % ANY (array_column)` 查询索引字符串数组列?

    我尝试过普通的Postgresgin索引以及 pg trgmgin trgm ops and gist trgm ops索引 使用此解决方法 https stackoverflow com a 33016333 283398 https s
  • 索引匹配不起作用

    对于下表 如果 A 列和 B 列都匹配 如何检索 C 列A 列 B 列 C 列城市 1 城市 10 本地城市 2 城市 21 远程城市 3 城市 1 远程城市 4 城市 2 本地 我尝试使用索引和匹配 但得到 N A Enter as an
  • 数据结构的优化存储以实现快速查找和持久化

    Scenario 我有以下方法 public void AddItemSecurity int itemId int userIds public int GetValidItemIds int userId 最初我正在考虑表单上的存储 i
  • 沿着长数据序列在固定大小的移动窗口中查找中值

    给定一个数据序列 可能有重复项 一个固定大小的移动 窗口 从数据开始处每次迭代时移动窗口 序列 使得 1 从窗口中删除最旧的数据元素并添加新数据 元素被推入窗口 2 求每次移动时窗口内数据的中位数 以下帖子没有帮助 有效地找到随机序列的中值
  • 如何在 MariaDB 10 中启用大索引?

    在 Debian Jessie 中 我安装了 MariaDB 服务器 10 0 30 并尝试增加最大密钥长度 AFAIU 这取决于配置参数innodb large prefix正在启用 根据docs https mariadb com kb
  • Pandas重置索引未生效[重复]

    这个问题在这里已经有答案了 我不确定我在哪里误入歧途 但我似乎无法重置数据帧上的索引 当我跑步时test head 我得到以下输出 正如您所看到的 数据帧是一个切片 因此索引超出范围 我想做的是重置该数据帧的索引 所以我跑test rese
  • 获取列表中倒数第二个元素[重复]

    这个问题在这里已经有答案了 我可以通过以下方式获取列表的倒数第二个元素 gt gt gt lst a b c d e f gt gt gt print lst len lst 2 e 有没有比使用更好的方法print lst len lst
  • DBMS 中的阻塞因素

    DBMS 中的阻塞因素是什么 我查看的位表示它是每个记录的块的下限值 因此 B R 下限 其中 B 是块大小 R 是记录 我只是想知道 有人可以告诉我它使用的主要原因 以及它是否真的是地板 我对 FLOORED 的理解是 1 5 降到 1
  • 使用自定义比较器在 Java 中创建 SortedMap

    我想创建一个TreeMap在 Java 中具有自定义排序顺序 排序后的键是字符串 需要根据第二个字符进行排序 这些值也是字符串 示例地图 Za FOO Ab Bar 您可以像这样使用自定义比较器 Comparator
  • MySQL:为什么 IN 子句中的第 5 个 ID 会极大地改变查询计划?

    给出以下两个查询 Query 1 SELECT log id FROM log WHERE user id IN 188858 188886 189854 203623 204072 and type in 14 15 17 ORDER B
  • CUDA 的嵌套循环

    我想将我的 C 代码移植到 CUDA 主要计算部分包含3个for嵌套循环 for int i 0 i lt Nx i for int j 0 j
  • 何时对 MongoDB 集合调用 EnsureIndex?

    我什么时候应该打电话ensureIndex 插入单条记录之前 插入单条记录之后 或者调用之前find 看来我的评论有点被误解了 所以我会澄清一下 当你调用它时并不重要只要在第一次调用 find 之前的某个时刻调用它即可 换句话说 什么时候创
  • 在大表上快速使用 LIMIT 和 OFFSET 进行 SELECT

    我的表中有超过 1000 万条记录 SELECT FROM tbl ORDER BY datecol DESC LIMIT 10 OFFSET 999990 输出EXPLAIN ANALYZE on 解释 depesz com http e
  • 为什么MongoDB不使用复合索引进行查询?

    以下是我对此集合的复合索引和单一索引 db Collection getIndexes 1 v 2 key id 1 name id ns service Collection 2 v 2 key FirstId 1 SecondId 1
  • 将更改(永久)保存在数组列表中?

    那可能吗 例如 用户将新的项目 元素添加到数组列表 缓冲读取器进程 中 并且肯定会发生更改 我的问题是 即使用户多次更改数组列表 它也可能会永久存在 即使他们关闭程序并再次打开它 它也会一直存在 注意 不使用 txt 很抱歉问这样的问题 但

随机推荐