Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby-on-rails-4/2.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 StringBuffer上插入(0,c)操作的复杂性:是O(1)吗?_Java - Fatal编程技术网

Java StringBuffer上插入(0,c)操作的复杂性:是O(1)吗?

Java StringBuffer上插入(0,c)操作的复杂性:是O(1)吗?,java,Java,我知道StringBuffer的append()操作需要O(1)个时间,与字符串连接相比,它避免了创建字符串对象多个副本的开销 insert(整数偏移量,字符c)怎么样 我需要反复调用此操作,以便以相反的顺序逐个向StringBuffer对象添加新字符。比如说, StringBuffer sb = new StringBuffer(); sb.insert(0, 'c'); sb.insert(0, 'b'); sb.insert(0, 'a'); System.out.println(sb.t

我知道StringBuffer的append()操作需要O(1)个时间,与字符串连接相比,它避免了创建字符串对象多个副本的开销

insert(整数偏移量,字符c)怎么样

我需要反复调用此操作,以便以相反的顺序逐个向StringBuffer对象添加新字符。比如说,

StringBuffer sb = new StringBuffer();
sb.insert(0, 'c');
sb.insert(0, 'b');
sb.insert(0, 'a');
System.out.println(sb.toString()); //prints out "abc";

在理想情况下,如果StringBuffer对象内部看起来像一个字符链表,则每个插入(0,c)都应该是O(1)。我想确认是否真的是这样。

好吧,这是一个实现细节——但我不希望它是一个字符的链接列表。我希望它是一个长度为的
char[]
,基本上类似于
ArrayList
,但用于字符。因此,在缓冲区的开头插入一个字符意味着复制所有剩余的数据


这是我见过的每一个实现的基础——与更常见的实现相比,字符链表将有巨大的内存(和分配时间)成本。包含对字符串部分的引用的列表或树结构(请参阅)不会有相同的成本,但我个人没有见过使用rope的
Java.lang.StringBuilder
Java.lang.StringBuffer
的Java实现。因此,是的,它是
O(n)
至少几乎总是这样。

StringBuffer
上的
insert
操作是O(n)。这是因为它必须向上移动到
n
个字符,以便为要插入的元素腾出空间

"bc"
insert(0, 'a') => "_bc" => "abc"
您可以通过不使用
insert
来解决此问题。您可以按相反的顺序迭代这些字母,然后可以调用O(1)
append
方法


StringBuffer
类是
AbstractStringBuilder
的一个子类,它定义了一个
char[]
来保存字符。它使用
System.arraycopy
在调用
insert
时移动现有字符,我在文档中找不到它,但它很可能不是O(1),因为
StringBuffer
在内部维护一个
char[]
缓冲区。因此,对于
n
字符序列,这些操作所需的总时间是O(n^2),因为每个
insert(0,c)
都需要将所有当前内容移位1

更有效的方法是使用
append
追加所有字符,最后使用
sb.reverse()
。其总体复杂度为O(n)-对于每个
追加
,摊销O(1),对于反向追加,摊销O(n)


另外,除非您有多个线程访问您的代码> StringBuffer < /代码>,否则您可能需要考虑用.< /P>< P>替换它。StringBuilder的内部数据结构是一个数组,而不是连接到其他节点(链表)的节点,所以答案是否定的——它不会是0(1)

您可以查看代码,它使用System.arrayCopy,因此复杂性为0(n)。您为什么关心这个问题?如果你在巨大的StringBuffers中进行大量插入,那么你可能是做错了。@HotLicks为什么一定是做错了?有时我们需要重复地追加一个字符串,但要反向追加;这意味着您只能先知道最后一个字符,然后才能知道前面的字符。@KubaSpatny有趣。这是
AbstractStringBuffer
;虽然我们使用的不是标准java.lang包中的StringBuffer,但我猜StringBuffer的实现大致类似。如果需要以相反的顺序执行,那么方法是将单个字符串累积到数组或列表中,然后在列表中向后旋转,最后添加到StringBuilder中。这会更有效率。请问您如何知道
StringBuffer
AbstractStringBuilder
的一个子类?我从这个链接中进行了检查,但没有找到它是否扩展了
AbstractStringBuilder
。好的,我想您可以从提供实现细节的开放jdk中找到它。它使用的是
System.arraycopy(value,offset,value,offset+1,count-offset)来进行元素转换。“rope”的数据结构很有趣,但我想这会使append()操作(StringBuffer最常用的操作)的成本超过O(1),因为在追加时可能需要保持树结构的平衡。@Erencie:我不太了解rope的详细信息,但这肯定是一种权衡。即使使用
StringBuilder
,append实际上也不是O(1)-充其量,它是您要追加的数据大小的O(N),充其量它需要在扩展缓冲区时创建一个副本。我不明白您的意思。这就是为什么我在句子的开头加上“除非”这个词的原因...如何将字符串移位为a
O(n^2)
操作?那不是
O(n)
?谢谢