Arrays 按Ruby数组复杂度顺序插入方法
在Ruby中,当n是数组大小时,插入数组的预期数量级是多少?Arrays 按Ruby数组复杂度顺序插入方法,arrays,ruby,complexity-theory,Arrays,Ruby,Complexity Theory,在Ruby中,当n是数组大小时,插入数组的预期数量级是多少? 感谢复杂性为O(N),因为此方法使用了Memmove()在rb_ary_splice()方法下,该方法本身就是O(N),请查看源代码: rb_ary_insert(int argc, VALUE *argv, VALUE ary) { long pos; rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS); rb_ary_modify_check(ary); if
感谢复杂性为O(N),因为此方法使用了
Memmove()
在rb_ary_splice()
方法下,该方法本身就是O(N),请查看源代码:
rb_ary_insert(int argc, VALUE *argv, VALUE ary)
{
long pos;
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
rb_ary_modify_check(ary);
if (argc == 1) return ary;
pos = NUM2LONG(argv[0]);
if (pos == -1) {
pos = RARRAY_LEN(ary);
}
if (pos < 0) {
pos++;
}
rb_ary_splice(ary, pos, 0, rb_ary_new4(argc - 1, argv + 1));
return ary;
}
rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl)
{
long rlen;
long olen;
if (len < 0) rb_raise(rb_eIndexError, "negative length (%ld)", len);
olen = RARRAY_LEN(ary);
if (beg < 0) {
beg += olen;
if (beg < 0) {
rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
beg - olen, -olen);
}
}
if (olen < len || olen < beg + len) {
len = olen - beg;
}
if (rpl == Qundef) {
rlen = 0;
}
else {
rpl = rb_ary_to_ary(rpl);
rlen = RARRAY_LEN(rpl);
olen = RARRAY_LEN(ary); /* ary may be resized in rpl.to_ary too */
}
if (beg >= olen) {
VALUE target_ary;
if (beg > ARY_MAX_SIZE - rlen) {
rb_raise(rb_eIndexError, "index %ld too big", beg);
}
target_ary = ary_ensure_room_for_push(ary, rlen-len); /* len is 0 or negative */
len = beg + rlen;
ary_mem_clear(ary, olen, beg - olen);
if (rlen > 0) {
ary_memcpy0(ary, beg, rlen, RARRAY_CONST_PTR(rpl), target_ary);
}
ARY_SET_LEN(ary, len);
}
else {
long alen;
if (olen - len > ARY_MAX_SIZE - rlen) {
rb_raise(rb_eIndexError, "index %ld too big", olen + rlen - len);
}
rb_ary_modify(ary);
alen = olen + rlen - len;
if (alen >= ARY_CAPA(ary)) {
ary_double_capa(ary, alen);
}
if (len != rlen) {
RARRAY_PTR_USE(ary, ptr,
MEMMOVE(ptr + beg + rlen, ptr + beg + len,
VALUE, olen - (beg + len)));
ARY_SET_LEN(ary, alen);
}
if (rlen > 0) {
MEMMOVE(RARRAY_PTR(ary) + beg, RARRAY_CONST_PTR(rpl), VALUE, rlen);
}
}
RB_GC_GUARD(rpl);
}
rb_ary_插入(int-argc,VALUE*argv,VALUE-ary)
{
长pos;
rb_校验(argc,1,无限参数);
rb\U ary\U修改检查(ary);
如果(argc==1)返回ary;
pos=NUM2LONG(argv[0]);
如果(位置==-1){
pos=RARRAY_LEN(ary);
}
如果(位置<0){
pos++;
}
rb_ary_拼接(ary,pos,0,rb_ary_new4(argc-1,argv+1));
回归分析;
}
rb_ary_拼接(值ary、长beg、长len、值rpl)
{
龙乐伦;
长橄榄油;
如果(len<0)rb_升高(rb_eIndexError,“负长度(%ld)”,len);
olen=RARRAY_LEN(ary);
if(beg<0){
beg+=olen;
if(beg<0){
rb_raise(rb_eIndexError,“索引%ld对于数组太小;最小值:%ld”,
beg-olen,-olen);
}
}
if(olen=olen){
价值目标;
如果(beg>ARY_最大尺寸-rlen){
rb_升高(rb_eIndexError,“索引%ld太大”,beg);
}
target_ari=ari_确保_push(ari,rlen len)的空间;/*len为0或负*/
len=beg+rlen;
ary_mem_clear(ary、olen、beg-olen);
如果(rlen>0){
ary_memcpy0(ary、beg、rlen、RARRAY_CONST_PTR(rpl)、target_ary);
}
ARY_SET_LEN(ARY,LEN);
}
否则{
龙阿伦;
如果(olen-len>ARY_MAX_SIZE-rlen){
rb_raise(rb_EINDEXERR,“索引%ld太大”,olen+rlen-len);
}
rb_ary_modify(ary);
alen=olen+rlen-len;
如果(alen>=ARY_CAPA(ARY)){
ary_double_capa(ary,alen);
}
如果(len!=rlen){
RARRAY_PTR_使用(ary,PTR,
MEMMOVE(ptr+beg+rlen,ptr+beg+len,
值,olen-(beg+len));
ARY_SET_LEN(ARY,alen);
}
如果(rlen>0){
MEMMOVE(RARRAY_PTR(ari)+beg、RARRAY_CONST_PTR(rpl)、VALUE、rlen);
}
}
RB_GC_防护装置(rpl);
}
以下是MEMMOVE函数的参考:
复杂度为O(N),因为此方法使用Memmove()
在rb\u ary\u splice()
方法(其本身为O(N))下,请查看源代码:
rb_ary_insert(int argc, VALUE *argv, VALUE ary)
{
long pos;
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
rb_ary_modify_check(ary);
if (argc == 1) return ary;
pos = NUM2LONG(argv[0]);
if (pos == -1) {
pos = RARRAY_LEN(ary);
}
if (pos < 0) {
pos++;
}
rb_ary_splice(ary, pos, 0, rb_ary_new4(argc - 1, argv + 1));
return ary;
}
rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl)
{
long rlen;
long olen;
if (len < 0) rb_raise(rb_eIndexError, "negative length (%ld)", len);
olen = RARRAY_LEN(ary);
if (beg < 0) {
beg += olen;
if (beg < 0) {
rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
beg - olen, -olen);
}
}
if (olen < len || olen < beg + len) {
len = olen - beg;
}
if (rpl == Qundef) {
rlen = 0;
}
else {
rpl = rb_ary_to_ary(rpl);
rlen = RARRAY_LEN(rpl);
olen = RARRAY_LEN(ary); /* ary may be resized in rpl.to_ary too */
}
if (beg >= olen) {
VALUE target_ary;
if (beg > ARY_MAX_SIZE - rlen) {
rb_raise(rb_eIndexError, "index %ld too big", beg);
}
target_ary = ary_ensure_room_for_push(ary, rlen-len); /* len is 0 or negative */
len = beg + rlen;
ary_mem_clear(ary, olen, beg - olen);
if (rlen > 0) {
ary_memcpy0(ary, beg, rlen, RARRAY_CONST_PTR(rpl), target_ary);
}
ARY_SET_LEN(ary, len);
}
else {
long alen;
if (olen - len > ARY_MAX_SIZE - rlen) {
rb_raise(rb_eIndexError, "index %ld too big", olen + rlen - len);
}
rb_ary_modify(ary);
alen = olen + rlen - len;
if (alen >= ARY_CAPA(ary)) {
ary_double_capa(ary, alen);
}
if (len != rlen) {
RARRAY_PTR_USE(ary, ptr,
MEMMOVE(ptr + beg + rlen, ptr + beg + len,
VALUE, olen - (beg + len)));
ARY_SET_LEN(ary, alen);
}
if (rlen > 0) {
MEMMOVE(RARRAY_PTR(ary) + beg, RARRAY_CONST_PTR(rpl), VALUE, rlen);
}
}
RB_GC_GUARD(rpl);
}
rb_ary_插入(int-argc,VALUE*argv,VALUE-ary)
{
长pos;
rb_校验(argc,1,无限参数);
rb\U ary\U修改检查(ary);
如果(argc==1)返回ary;
pos=NUM2LONG(argv[0]);
如果(位置==-1){
pos=RARRAY_LEN(ary);
}
如果(位置<0){
pos++;
}
rb_ary_拼接(ary,pos,0,rb_ary_new4(argc-1,argv+1));
回归分析;
}
rb_ary_拼接(值ary、长beg、长len、值rpl)
{
龙乐伦;
长橄榄油;
如果(len<0)rb_升高(rb_eIndexError,“负长度(%ld)”,len);
olen=RARRAY_LEN(ary);
if(beg<0){
beg+=olen;
if(beg<0){
rb_raise(rb_eIndexError,“索引%ld对于数组太小;最小值:%ld”,
beg-olen,-olen);
}
}
if(olen=olen){
价值目标;
如果(beg>ARY_最大尺寸-rlen){
rb_升高(rb_eIndexError,“索引%ld太大”,beg);
}
target_ari=ari_确保_push(ari,rlen len)的空间;/*len为0或负*/
len=beg+rlen;
ary_mem_clear(ary、olen、beg-olen);
如果(rlen>0){
ary_memcpy0(ary、beg、rlen、RARRAY_CONST_PTR(rpl)、target_ary);
}
ARY_SET_LEN(ARY,LEN);
}
否则{
龙阿伦;
如果(olen-len>ARY_MAX_SIZE-rlen){
rb_raise(rb_EINDEXERR,“索引%ld太大”,olen+rlen-len);
}
rb_ary_modify(ary);
alen=olen+rlen-len;
如果(alen>=ARY_CAPA(ARY)){
ary_double_capa(ary,alen);
}
如果(len!=rlen){
RARRAY_PTR_使用(ary,PTR,
MEMMOVE(ptr+beg+rlen,ptr+beg+len,
值,olen-(beg+len));
ARY_SET_LEN(ARY,alen);
}
如果(rlen>0){
MEMMOVE(RARRAY_PTR(ari)+beg、RARRAY_CONST_PTR(rpl)、VALUE、rlen);
}
}
RB_GC_防护装置(rpl);
}
以下是MEMMOVE函数的参考:
TL;DR将项目追加(插入的一种特殊形式)到数组末尾通常在O(1)个时间内完成。
让我们浏览一下(MRI)ruby源代码,看看为什么会出现这种情况。我们从这行ruby代码开始:
a = [1,2]
Ruby准备一个数组对象,然后在中初始化它。
检查参数的有效性,然后使用以下命令检查数组的有效性:
ary_resize_capa(ary, len);
数组的容量是数组在从操作系统分配的内存块中可能容纳的元素数。
数组的长度(数组实际包含的元素数)始终小于或等于容量。
通过设置数组的容量,ruby确保分配足够的内存来容纳len
数组中的项数
现在,让我们在数组的末尾添加一个元素:
a << 3
这个代码看起来不太吓人。它发现新元素的索引(idx
)是数组的长度,确保数组有足够的内存容纳新元素(),将新元素写入数组,并增加数组长度
当阵列的容量大于其长度时,无需在ari\u确保\u空间中为\u p分配更多内存
static VALUE
ary_ensure_room_for_push(VALUE ary, long add_len)
{
long old_len = RARRAY_LEN(ary);
long new_len = old_len + add_len;
long capa;
// ...
rb_ary_modify(ary);
capa = ARY_CAPA(ary);
if (new_len > capa) {
ary_double_capa(ary, new_len);
}
return ary;
}