赞 | 2 |
VIP | 143 |
好人卡 | 1 |
积分 | 1 |
经验 | 216792 |
最后登录 | 2019-10-10 |
在线时间 | 24 小时 |
Lv1.梦旅人
- 梦石
- 0
- 星屑
- 61
- 在线时间
- 24 小时
- 注册时间
- 2008-8-5
- 帖子
- 1924
|
嗯,但指针是连续内存...
shift 确实只是增加指针:- 00480 /*
- 00481 * call-seq:
- 00482 * array.shift -> obj or nil
- 00483 *
- 00484 * Returns the first element of <i>self</i> and removes it (shifting all
- 00485 * other elements down by one). Returns <code>nil</code> if the array
- 00486 * is empty.
- 00487 *
- 00488 * args = [ "-m", "-q", "filename" ]
- 00489 * args.shift #=> "-m"
- 00490 * args #=> ["-q", "filename"]
- 00491 */
- 00492
- 00493 VALUE
- 00494 rb_ary_shift(ary)
- 00495 VALUE ary;
- 00496 {
- 00497 VALUE top;
- 00498
- 00499 rb_ary_modify_check(ary);
- 00500 if (RARRAY(ary)->len == 0) return Qnil;
- 00501 top = RARRAY(ary)->ptr[0];
- 00502 ary_make_shared(ary);
- 00503 RARRAY(ary)->ptr++; /* shift ptr */
- 00504 RARRAY(ary)->len--;
- 00505
- 00506 return top;
- 00507 }
复制代码 不过就像我说的,unshift 和 pop 则会在缓冲区容量不够的时候重新分配内存:- 00509 VALUE
- 00510 rb_ary_unshift(ary, item)
- 00511 VALUE ary, item;
- 00512 {
- 00513 rb_ary_modify(ary);
- 00514 if (RARRAY(ary)->len == RARRAY(ary)->aux.capa) {
- 00515 long capa_inc = RARRAY(ary)->aux.capa / 2;
- 00516 if (capa_inc < ARY_DEFAULT_SIZE) {
- 00517 capa_inc = ARY_DEFAULT_SIZE;
- 00518 }
- 00519 RARRAY(ary)->aux.capa += capa_inc;
- 00520 REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->aux.capa);
- 00521 }
- 00522
- 00523 /* sliding items */
- 00524 MEMMOVE(RARRAY(ary)->ptr + 1, RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len);
- 00525
- 00526 RARRAY(ary)->len++;
- 00527 RARRAY(ary)->ptr[0] = item;
- 00528
- 00529 return ary;
- 00530 }
复制代码 这里的 REALLOC_N 就是包装了 xrealloc 的一个宏;下面还有一个的 MEMMOVE 用来把数组整体右移一位,之后空出来的第一位被设为 unshift 的参数。一般类似这种插入删除的运算,都需要 O(n),只不过由于按块转移内存,所以效率损失微乎其微
pop 的:- 00444 VALUE
- 00445 rb_ary_pop(ary)
- 00446 VALUE ary;
- 00447 {
- 00448 rb_ary_modify_check(ary);
- 00449 if (RARRAY(ary)->len == 0) return Qnil;
- 00450 if (!FL_TEST(ary, ELTS_SHARED) &&
- 00451 RARRAY(ary)->len * 2 < RARRAY(ary)->aux.capa &&
- 00452 RARRAY(ary)->aux.capa > ARY_DEFAULT_SIZE) {
- 00453 RARRAY(ary)->aux.capa = RARRAY(ary)->len * 2;
- 00454 REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->aux.capa);
- 00455 }
- 00456 return RARRAY(ary)->ptr[--RARRAY(ary)->len];
- 00457 }
复制代码 也需要在适当时候重新分配内存,只不过这次是缩减容量
to_s 那个是写过无数次的二叉树 ASCII 化 + -90度旋转... |
|