从中到外访问数组(非向量)元素的最简单方法是什么?

时间:2015-06-26 06:34:41

标签: arrays language-agnostic

我想创建一个游戏,怪物从左到右水平对齐,怪物的顺序具有其他逻辑意义(例如:出现的序列),但我想发挥一些从中间怪物开始的效果< / p>

数组,例如,对于奇数大小的数组:

int[] a=new int[]{1,2,3,4,5};

访问顺序为3,2,4,1,5(或3,4,2,5,1

用于偶数数字大小的数组:

int[] a=new int[]{1,2,3,4,5,6};

访问顺序为3,4,2,5,1,6或(4,3,5,2,6,1

如果它与c ++中的vector类似,那么它将是:

std::vector<int> a;
a.push_back(1);
a.push_back(2);
a.push_back(3);
a.push_back(4);
a.push_back(5);

while(a.size()>0){
    printf("%d\n",a[a.size()/2]);
    a.erase(a.begin()+a.size()/2);
}

输出

3
4
2
5
1

但是我想要一个适合在数组中使用的算法,它不能改变元素的位置,

我尝试过类似的事情:

int a[]={1,2,3,4,5};
for(int i=a.size()/2;i>=0 && i<a.size();i=XXXX){
    printf("%d\n",a[i]);
}

哪个XXXX是更新语句,我仍然不知道它应该是什么。

实际上,我不知道for循环中的init值和条件语句是否正确。我甚至不知道它是否可以通过一个循环来完成。

好的,我知道我可以有一个临时向量,然后复制索引来做到这一点,但我也想知道它是否可以在没有任何临时向量或数组的单个for循环中完成。

任何人都可以提供帮助(或者还有其他简单的算法吗?)?

2 个答案:

答案 0 :(得分:4)

这是编辑问题的答案,该问题与语言无关,并且希望单个函数以所述顺序显示元素。

首先,选择一个“中间”指数。

var i = Math.floor((a.length-1)/2);

然后交替向右和向左逐渐向外移动,直到遇到阵列的任一边缘。

为方便起见,请从变量d = 0开始,该变量将是距中间元素的距离。这个d将在每次迭代时更新如此

d += -(2*d) + (d > 0 ? 0 : 1);

使用以下更新模式:

  

0,1,-1,2,-2,......

如果数组[1,2,3,4,5]中的中间索引为2,则应用a[i + d]将导致

  

3,4,2,5,1

我希望这就是你要找的东西。

这是一个JavaScript实现:

var a = [1,2,3,4,5,7,8];

var i = Math.floor((a.length-1)/2);
for (var d = 0; i+d >= 0 && i+d < a.length;) {

  // Print out the value
  console.log(a[i + d]);

  // Outward-moving logic
  d += -(2*d) + (d > 0 ? 0 : 1);
}

或者如果你想在for循环中想要这一切,就像你在问题中尝试过的那样,你可以这样做:

var a = [1,2,3,4,5,7,8];

var i = Math.floor((a.length-1)/2);
for (var d = 0; i+d >= 0 && i+d < a.length; d += -(2*d) + (d > 0 ? 0 : 1)) {
  console.log( a[i + d] ); // print the value
}

结果[1,2,3,4,5](奇数长度数组):

  

3 4 2 5 1

[1,2,3,4,5,6,7,8](偶数长度数组)的结果:

  

4 5 3 6 2 7 1 8

演示: JSBin

答案 1 :(得分:2)

列出从最里面到最外面的元素的算法是交替拉出数组中的最后一个和第一个条目(弹出和移位),直到没有剩下任何元素,然后反转你已经拉出的内容的列表。这自然适用于奇数和偶数长度数组。

例如,

1,2,3,4,5,6
1,2,3,4,5       6
2,3,4,5         6,1
2,3,4           6,1,5
3,4             6,1,5,2
3               6,1,5,2,4
                6,1,5,2,4,3
                3,4,2,5,1,6  // Reversed list from above

1,2,3,4,5
1,2,3,4         5
2,3,4           5,1
2,3             5,1,4
3               5,1,4,2
                5,1,4,2,3
                3,2,4,1,5  // Reversed list from above

您可以使用以上算法创建索引映射数组,您可以使用该数组按请求的顺序访问主数组。例如:

// Start with an array of indices 
// from 0..arr.length-1
0,1,2,3,4
0,1,2,3         4
1,2,3           4,0
1,2             4,0,3
2               4,0,3,1
                4,0,3,1,2
                2,1,3,0,4  // Reversed list from above

然后你有一个映射数组

int[] arr = new int[]{1,2,3,4,5};
int[] map = new int[]{2,1,3,0,4};

可用于访问主阵列,例如

arr[map[0]]; // returns 3

编辑:添加了Java实施和demo

public static int[] creatIndexMap(int length) {

    // Create a deque so elements can be removed from both ends
    Deque<Integer> tmp = new LinkedList<Integer>();
    for(int i = 0; i < length; i++) {
        tmp.add(i);
    }

    // In alternation remove the last and first entries of tmp
    // and add them in reverse order to the map array
    int[] map = new int[length];
    int index = length-1;
    while (!tmp.isEmpty()) {
        // Remove last element
        map[index--] = (int) tmp.removeLast();

        // Remove first element
        if(!tmp.isEmpty()) {
            map[index--] = (int) tmp.removeFirst();
        }
    }
    return map;
}

演示: IDEOne