lua源码--对数组首尾进行指定的n个元素的反转以及删除和插入操作


这个基于数组的操作方法,在某些应用中可以用于简单地替换队列或链表等数据结构。

//Lua.h
//往索引值为idx的位置进行插入操作,记住在这个动作之前应将要插入的元素放置于数组当前有效值的最后位置(即相当于栈顶的push操作)
#define lua_insert(L,idx)    lua_rotate(L, (idx), 1)
//删除索引值为idx的位置处的元素,其后的元素都会向前移位
#define lua_remove(L,idx)    (lua_rotate(L, (idx), -1), lua_pop(L, 1))

//将栈顶的元素和位置索引值为idx的元素进行替换
#define lua_replace(L,idx)    (lua_copy(L, -1, (idx)), lua_pop(L, 1))

//Lapi.h
/*
** Reverse the stack segment from 'from' to 'to'
** (auxiliary to 'lua_rotate')
*/
//反转操作
static void reverse (lua_State *L, StkId from, StkId to) {
  for (; from < to; from++, to--) {
    TValue temp;
    setobj(L, &temp, from);
    setobjs2s(L, from, to);
    setobj2s(L, to, &temp);
  }
}

/*
** Let x = AB, where A is a prefix of length 'n'. Then,
** rotate xn == BA. But BA == (A^r . B^r)^r.
*/
//|n|为要反转的个数
LUA_API void lua_rotate (lua_State *L, int idx, int n) {
  StkId p, t, m;
  lua_lock(L);
  t = L->top - 1;          /* end of stack segment being rotated *///将被反转的段的末端
  p = index2addr(L, idx);  /* start of segment */                   //将被反转的段的起始端
  api_checkstackindex(L, idx, p);
  api_check(L, (n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'"); //
  m = (n >= 0 ? t - n : p - n - 1);  /* end of prefix */  //将要反转的段的前部的末尾索引值:例如0-10的数值序列中,反转3个数,那么m=2,
  reverse(L, p, m);  /* reverse the prefix with length 'n' */ //这个反转技巧很妙避免了移位操作
  reverse(L, m + 1, t);  /* reverse the suffix */
  reverse(L, p, t);  /* reverse the entire segment */
  lua_unlock(L);
}

LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) {
  TValue *fr, *to;
  lua_lock(L);            //
  fr = index2addr(L, fromidx);
  to = index2addr(L, toidx);
  api_checkvalidindex(L, to);
  setobj(L, to, fr);
  if (isupvalue(toidx))  /* function upvalue? */
    luaC_barrier(L, clCvalue(L->ci->func), fr);
  /* LUA_REGISTRYINDEX does not need gc barrier
     (collector revisits it before finishing collection) */
  lua_unlock(L);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值