Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/370.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 ArrayList获取操作O(1)。怎么用?_Java_Big O - Fatal编程技术网

Java ArrayList获取操作O(1)。怎么用?

Java ArrayList获取操作O(1)。怎么用?,java,big-o,Java,Big O,在其中一个as中,为什么ArrayList.get是O(1)而不是O(n) 响应者说ArrayList由一个数组和一个 RangeCheck(index); 是什么决定了恒定的时间复杂度而不是线性的!我试着把我的脑袋绕到这一点上,难道任何数组都不需要至少对数组中n个字段的%年龄进行部分搜索,从而以某种方式构成O(n)搜索(如果要搜索的元素位于数组的n-1位置-这不是O(n)搜索吗?它仍然是一个一级for循环,我认为是O(n)复杂性?作为答案发布,建议如下: 不搜索。它直接返回由提

在其中一个as中,为什么ArrayList.get是O(1)而不是O(n)

响应者说ArrayList由一个数组和一个

      RangeCheck(index); 

是什么决定了恒定的时间复杂度而不是线性的!我试着把我的脑袋绕到这一点上,难道任何数组都不需要至少对数组中n个字段的%年龄进行部分搜索,从而以某种方式构成O(n)搜索(如果要搜索的元素位于数组的n-1位置-这不是O(n)搜索吗?它仍然是一个一级for循环,我认为是O(n)复杂性?

作为答案发布,建议如下:

不搜索。它直接返回由提供的索引寻址的元素…与数组完全相同-因此得名

ArrayList.get(int)源:

其中,rangeCheck(int)为:

elementData()是:

然而,链表将有一个
O(n)
get:它必须跳转到下一个元素,直到达到所需的索引

public E get(int index) {
    return entry(index).element;
}
其中条目(int)是(这就是为什么它是O(n)):

private Entry更多…条目(int索引){
如果(索引<0 | |索引>=大小)
抛出新的IndexOutOfBoundsException(“索引:+Index+”,大小:+Size);
条目e=标题;
如果(索引<(大小>>1)){
对于(int i=0;i索引;i--)
e=e.先前;
}
返回e;
}

(注意:它是双链接列表,因此通过选择最接近所需结果的端点可以节省一些时间,但这仍然是O(n))

访问数组中的特定索引是一个常数时间操作,因为它涉及从数组对象获取基内存地址,并在基地址+索引乘以元素类型大小时访问内存。由于跳过了其间的所有元素,因此访问时间受一个常数的限制


ArrayList.get(int)
方法是直接数组访问上的一个薄包装,因此它也由一个常数限定。

数组在内存中按顺序排列。这意味着,如果它是一个整数数组,每个整数使用4个字节,从内存地址1000开始,下一个元素将在1004,下一个元素将在1008,依此类推。因此,如果我想要元素在位置20在我的数组中,
get()
中的代码必须计算:

1000 + 20 * 4 = 1080
要获得元素的确切内存地址,RAM内存的名称为随机访问内存,因为它们的构建方式是,它们有一个硬件多路复用器的层次结构,允许它们在给定地址的情况下,以恒定时间访问任何存储的内存单元(字节?)


因此,两个简单的算术运算和一个对RAM的访问被称为O(1)。

ArrayList.get(int)
不进行搜索。它直接返回由提供的索引寻址的元素…与数组完全相同-因此得名。(另外,我假设这是关于Java的)。对于LinkedList,这将保持不变!该链接应该转到提问页面吗?您在这里谈论的是什么语言?是的,这是关于Java的!@ppeterka66您应该将其添加为答案。Wooble:Java。答案很简单,ArrayList的内部表示形式是一个数组。因此,您可以通过索引直接访问!+1,真的是地址这是为什么这是O(1)的根源,而不仅仅是假设数组是O(1)。我想补充一点,“数组在内存中按顺序排列”这就是为什么数组必须具有固定大小的原因。你永远无法确定数组之后是什么内存。除此之外,我一直在想:内存访问不是O(内存地址中的位)?也就是说,32位系统上的内存访问速度应该比64位系统快?当然,电路必须为每个位做出至少一个决定,对吗?此外,内存实际上是字节可寻址的。只要(内存地址中的位)保持不变,O(内存地址中的位)根据大o的数学定义,仍然是o(1)…但硬件确实更复杂,所有这一切都是一种简化,涉及到更多的层和算法,包括一级缓存、二级缓存、MMU和虚拟地址表。但是内存地址中的位不是恒定的。我的系统可能比你的系统有更多。对于同一个系统,它总是恒定的,但不是一般的我知道虚拟寻址、寄存器和缓存等,但我说的是,在64位系统上(所有其他变量都相等)何时必须进行内存访问,会花费更长的时间吗?如果内存是一个大链表,我必须遍历整个内存空间才能访问我的内存,你会说:它是O(n)其中n是内存量。你不会说:它是O(1),因为系统总是有相同的内存量。谢谢!内存关联和代码分解给出了一个360度的画面!
E elementData(int index) {
    return (E) elementData[index];
}
public E get(int index) {
    return entry(index).element;
}
private Entry<E> More ...entry(int index) {
    if (index < 0 || index >= size)
        throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);

    Entry<E> e = header;

    if (index < (size >> 1)) {
        for (int i = 0; i <= index; i++)
            e = e.next;
    } else {
        for (int i = size; i > index; i--)
            e = e.previous;
    }
    return e;
}
1000 + 20 * 4 = 1080