Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.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
Java 具有快速搜索和慢速插入/删除功能的内存有效整数列表_Java_Algorithm_Design Patterns_Data Structures - Fatal编程技术网

Java 具有快速搜索和慢速插入/删除功能的内存有效整数列表

Java 具有快速搜索和慢速插入/删除功能的内存有效整数列表,java,algorithm,design-patterns,data-structures,Java,Algorithm,Design Patterns,Data Structures,我试图为正整数(数百万个元素)的排序列表找到最佳值。要求(按重要性排序): 内存占用小 快速O(日志n)search 插入/删除速度快于memcpy() 我正在考虑保留两个数组:一个用于搜索,一个用于插入。每隔几次操作,我就会重新组织主要的一次,并清理第二次。有什么想法吗?我走对了吗 注:没有重复的。它不需要是线程安全的。读会经常发生,而写会很少发生。整数在结构中的分布是不均匀的,这意味着一些结构只包含几个元素,而其他结构可能包含数百万个元素,它们的位置从零到0xffffff我想您应该使用 它具

我试图为正整数(数百万个元素)的排序列表找到最佳值。要求(按重要性排序):

  • 内存占用小

  • 快速
    O(日志n)
    search

  • 插入/删除速度快于
    memcpy()

  • 我正在考虑保留两个数组:一个用于搜索,一个用于插入。每隔几次操作,我就会重新组织主要的一次,并清理第二次。有什么想法吗?我走对了吗


    注:没有重复的。它不需要是线程安全的。读会经常发生,而写会很少发生。整数在结构中的分布是不均匀的,这意味着一些结构只包含几个元素,而其他结构可能包含数百万个元素,它们的位置从零到
    0xffffff

    我想您应该使用

    它具有以下特点:

    Space   O(M)
    Search  O(log log M)
    Insert  O(log log M)
    Delete  O(log log M)
    

    我想你想用一个

    它具有以下特点:

    Space   O(M)
    Search  O(log log M)
    Insert  O(log log M)
    Delete  O(log log M)
    

    那链表呢?momory约束是int的大小+上一个和下一个指针的一点开销。至于插入和删除,所需的时间只需沿着列表往下看,直到找到一个比正在插入的小的,并将其放在记录之前。删除只需要更改“上一个”和“下一个”的指针,搜索和插入一样简单。

    链表呢?momory约束是int的大小+上一个和下一个指针的一点开销。至于插入和删除,所需的时间只需沿着列表往下看,直到找到一个比正在插入的小的,并将其放在记录之前。删除只需要更改“上一个”和“下一个”的指针,搜索和插入一样简单。

    您能使用
    char[65536][]
    吗?其中,顶部或底部16位是其他16位数组的索引。这可能会使用少于4*X的每个条目

    查找

     private final char[][] bitsArray = new char[65536][];
    
     public int countFor(int num) {
         int topBits = num >>> 16;
         int lowerBits = num & 0xFFFF;
         char[] lowerBitsArray = bitsArray[topBits];
         int count = 0;
         for(char l : lowerBitsArray)
            if(l == lowerBits)
               count++;
         return count;
     }
    
    如果计数不能超过1,则位集可能是更好的选择。(可能是一个位集数组,具体取决于数据的模式)例如,如果要记录看到的IP地址,可能不需要担心0、10、127.*或224-255.*


    无论是
    int[]
    还是
    char[]
    都可以更快地访问,包括对int的强制转换

    public static void main(String... args) {
        char[] chars = new char[1000000];
        for (int i = 0; i < 5; i++)
            timeSum(chars);
        int[] ints = new int[1000000];
        for (int i = 0; i < 5; i++)
            timeSum(ints);
    }
    
    private static int timeSum(char[] chars) {
        long start = System.nanoTime();
        int sum = 0;
        for (char ch : chars) {
            sum += ch;
        }
        long time = System.nanoTime() - start;
        System.out.printf("Took %,d us to sum %,d chars%n", time / 1000, chars.length);
        return sum;
    }
    
    private static int timeSum(int[] ints) {
        long start = System.nanoTime();
        int sum = 0;
        for (int i : ints) {
            sum += i;
        }
        long time = System.nanoTime() - start;
        System.out.printf("Took %,d us to sum %,d ints%n", time / 1000, ints.length);
        return sum;
    }
    

    我的结论是缓存效率比强制转换成本更重要。

    您可以使用
    char[65536][]
    ?其中,顶部或底部16位是其他16位数组的索引。这可能会使用少于4*X的每个条目

    查找

     private final char[][] bitsArray = new char[65536][];
    
     public int countFor(int num) {
         int topBits = num >>> 16;
         int lowerBits = num & 0xFFFF;
         char[] lowerBitsArray = bitsArray[topBits];
         int count = 0;
         for(char l : lowerBitsArray)
            if(l == lowerBits)
               count++;
         return count;
     }
    
    如果计数不能超过1,则位集可能是更好的选择。(可能是一个位集数组,具体取决于数据的模式)例如,如果要记录看到的IP地址,可能不需要担心0、10、127.*或224-255.*


    无论是
    int[]
    还是
    char[]
    都可以更快地访问,包括对int的强制转换

    public static void main(String... args) {
        char[] chars = new char[1000000];
        for (int i = 0; i < 5; i++)
            timeSum(chars);
        int[] ints = new int[1000000];
        for (int i = 0; i < 5; i++)
            timeSum(ints);
    }
    
    private static int timeSum(char[] chars) {
        long start = System.nanoTime();
        int sum = 0;
        for (char ch : chars) {
            sum += ch;
        }
        long time = System.nanoTime() - start;
        System.out.printf("Took %,d us to sum %,d chars%n", time / 1000, chars.length);
        return sum;
    }
    
    private static int timeSum(int[] ints) {
        long start = System.nanoTime();
        int sum = 0;
        for (int i : ints) {
            sum += i;
        }
        long time = System.nanoTime() - start;
        System.out.printf("Took %,d us to sum %,d ints%n", time / 1000, ints.length);
        return sum;
    }
    

    我的结论是缓存效率比cast成本更重要。

    这实际上是一个有趣且不平凡的问题。最佳答案将取决于您的具体要求以及您执行的操作的精确组合

    如果数据密集且不允许重复,则大位图可能是最佳选择。只需设置一个位来显示每个可能整数值的存在/不存在。这种方法的读写速度都非常快,而且都是O(1),但是内存使用率显然是由您拥有的范围有多大/数据的稀疏程度决定的

    如果数据密集且允许重复/common,则存储每个可能值的出现次数的数组可能工作良好。在性能上与位图方法类似,但假设发生计数为int,则可能需要32倍的内存

    如果您是重读且数据稀疏,则基于排序数组的方法(使用二进制搜索进行查找)可能是最好的方法。如果您了解值的粗略分布,那么您可以通过使用启发式来猜测目标值在数组中的可能位置,从而更快地完成任务(例如,如果您利用分布大致均匀的知识,您可以大大超过log2(N))


    如果有大量写操作且数据稀疏,则可能需要基于树的结构,该结构基于整数中位的子集进行拆分(例如,每个节点上下一个最重要的5位上的32路trie拆分)。Clojure的持久化数据结构使用了这项技术,效果非常好。

    这实际上是一个有趣且不平凡的问题。最佳答案将取决于您的具体要求以及您执行的操作的精确组合

    如果数据密集且不允许重复,则大位图可能是最佳选择。只需设置一个位来显示每个可能整数值的存在/不存在。这种方法的读写速度都非常快,而且都是O(1),但是内存使用率显然是由您拥有的范围有多大/数据的稀疏程度决定的

    如果数据密集且允许重复/common,则存储每个可能值的出现次数的数组可能工作良好。在性能上与位图方法类似,但假设发生计数为int,则可能需要32倍的内存

    如果您是重读且数据稀疏,则基于排序数组的方法(使用二进制搜索进行查找)可能是最好的方法。如果您了解值的粗略分布,则可以通过使用启发式来猜测目标值在数组中的可能位置(例如,您可以