通过更改其起始索引(循环缓冲区)重新排序NSMutableArray

时间:2016-10-23 09:56:43

标签: objective-c

是否有一种通过更改其起始索引来重新排序NSMutableArray的有效方法?示例:如果我的数组是[A,B,C,D,E],我想将第3个元素设置为起始元素,从而创建数组[C,D,E,A,B]。 我通过将数组切成两个单独的数组,然后连接它们来做到这一点。有没有更有效或干净的方法来做到这一点?

编辑:以下是我当前的代码

NSArray myArray = [self getMyArray]; // [A,B,C,D]
int startingIndex = 2; 
NSArray *subArray1 = [myArray subarrayWithRange:NSMakeRange(_startingIndex, [myArray count] - _startingIndex + 1)]; // [C,D]
NSArray *subArray2 = [myArray subarrayWithRange:NSMakeRange(0, _startingIndex - 1)]; //[A,B]
NSMutableArray *reorderedArray = [NSMutableArray arrayWithArray:subArray1]; 
[reorderedArray addObjectsFromArray: subArray2]; //[C,D,A,B]

3 个答案:

答案 0 :(得分:1)

在额外内存方面旋转NSMutableArray的最经济的方法是此Q&A中描述的双重还原算法,因为它不需要任何额外的存储空间。想法是反转整个数组,然后分别反转两个范围。

在您的示例中,数组将被颠倒,就像这样

E D C B A

然后前三个元素将被颠倒

C D E B A

最后阵列的尾部将颠倒过来:

C D E A B

制作一个用于反转范围的辅助函数,并将其调用三次:

reverseInPlace(myArray, 0, myArray.count-1);
reverseInPlace(myArray, 0, _startingIndex);
reverseInPlace(myArray, _startingIndex+1, myArray.count-1);

实施reverseInPlace的一种方法如下:

static void reverseInPlace(NSMutableArray *a, int f, int b) {
    while (f < b) {
        [a exchangeObjectAtIndex:f++ withObjectAtIndex:b--];
    }
}

答案 1 :(得分:0)

不,NSMutableArray没有记录为circular buffer (ring buffer),也没有预期的操作。使用数据结构解决此问题的一些潜在有用资源,其中旋转具有O(1)成本:

  1. Answer to a related Objective-C question about ring buffers,如果您愿意,可以链接到CHDataStructures available also as a pod
  2. Boost.Circular:一个C ++循环缓冲区,您可以将其包装到某些Objective-C ++中。
  3. 如果您只需旋转固定的,可预测的长度缓冲区,则循环缓冲区is a simple data structure to implement yourself。 Apple的CoreAudio utility classes还包括一个通用的环形缓冲区(CARingBuffer),您可能会发现它可用作实施的参考。

    如果就地O(N)解决方案足以满足您的需求,the other answer比我上面提出的各种复杂的事情更好。

答案 2 :(得分:0)

更高效,更清洁:

NSRange range = NSMakeRange(0, startingIndex - 1);
NSArray *subArray = [array subarrayWithRange:range];
[array removeObjectsInRange:range];
[array addObjectsFromArray:subArray];
相关问题