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

问题描述 投票:-19回答:2

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

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

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循环中完成。

任何人都可以帮忙(或者还有另一种简单的算法吗?)?

arrays language-agnostic
2个回答
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;
}

但是:ぁzxswい


4
投票

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

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

IDEOne

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

为了实现这一点,请从变量var i = Math.floor((a.length-1)/2); 开始,该变量将是距离中间元素的距离。这个d = 0将在每次迭代时更新

d

使用以下更新模式:

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

如果数组d += -(2*d) + (d > 0 ? 0 : 1); 中的中间索引为2,则应用[1,2,3,4,5]将导致

3, 4, 2, 5, 1

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


这是一个JavaScript实现:

a[i + d]

或者如果你想在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;) {

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

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

关于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 } (奇数长度数组)的结果:

3 4 2 5 1

关于[1,2,3,4,5](偶数长度数组)的结果:

4 5 3 6 2 7 1 8

但是:ぁzxswい

© www.soinside.com 2019 - 2024. All rights reserved.