2013-06-07 8 views
5

Possiedo un ad es. {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}Metodo di spostamento matrice ottimizzato

Mi piacerebbe essere in grado di spostare gli elementi con l'avvolgimento.

Così ad es. muovi 1 al centro, spostando tutti gli elementi, avvolgendo di nuovo quelli rimanenti (che superano i limiti) all'inizio, e viceversa, ad es. 10 al centro.

{7, 8, 9, 10, 1, 2, 3, 4, 5, 6} e {6, 7, 8, 9, 10, 1, 2, 3, 4, 5}

Esiste un ottimizzato sort metodo come questo già esistente?

+1

penso che possiamo farlo in tempo lineare con uno 'ciclo for', uno per il primo' k' elementi dicono 1-6 e il prossimo per rimanere 'elementi M' cioè 7-10. e 'k + m = n' che è la dimensione della matrice. Ma non sono a conoscenza di alcun algoritmo standard in quanto tale. –

+0

@PraveenS - 'trueIndex = (offset + indice)% array.count'. Penso che sia meglio del tempo lineare. –

risposta

2

L'approccio più efficiente sarebbe quello di creare un oggetto wrapper che mantenga l'attuale "origine" dell'array e reinterpreta gli indici aggiungendo quell'origine, modulo la lunghezza. In effetti, se l'array è accessibile solo in una manciata di posti, questo è fatto facilmente con 1-2 linee di codice in linea.

-(id)objectForIndex:(NSInteger) index { 
    NSInteger realIndex = (origin + index) % array.count; 
    return [array objectAtIndex:realIndex]; 
} 

(Se si estende NS (Mutevole) Array poi "matrice" è "super". Se solo un involucro poi "matrice" è una var esempio. "Origine" è un'istanza var/struttura in entrambi i casi .)

+0

Intelligente, non c'è bisogno di mutare. – jarryd

+0

Modulo! Genio! –

0

sicuramente se si sta spostando da N elementi che devono avvolgere tutto ciò che si farebbe prendere gli ultimi elementi dell'array N e incollarli nella parte anteriore?

e se stai spostando dall'altra parte, prendi la parte anteriore e mettila dietro.

2

Sono a conoscenza di metodi su NSArray per questo, ma:

static NSArray *shiftArray(NSArray *array, NSInteger pos) 
{ 
    NSInteger length = [array count]; 
    NSArray *post = [array subarrayWithRange:(NSRange){ .location = length - pos, .length = pos }]; 
    NSArray *pre = [array subarrayWithRange:(NSRange){ .location = 0, .length = length - pos}]; 
    return [post arrayByAddingObjectsFromArray:pre]; 
} 

es .:

NSArray *array = @[@"A", @"B", @"C", @"D", @"E", @"F", @"G", @"H", @"I"]; 
NSLog(@"array = %@",shiftArray(array, 4)); 

dovrebbe fare ciò che si descrive.

registri per la console:

array = (
    F, 
    G, 
    H, 
    I, 
    A, 
    B, 
    C, 
    D, 
    E 
) 

probabilmente non performante.

0

La rotazione è essenzialmente eseguita prendendo gli elementi N da un'estremità dell'array e posizionandoli invece sull'altra estremità. Potresti farlo con array immutabili se lo desideri, ma gli array mutabili offrono un'implementazione leggermente più pulita.

Per Ruota a sinistra, il modo più semplice è probabilmente solo:

// Make sure we don't overrun the array if the rotation is larger. 
numberOfObjectsToRotateLeft %= array.count; 

NSRange range = NSMakeRange(0, numberOfObjectsToRotateLeft); 
NSMutableArray * rotatedArray = [array mutableCopy]; 

[rotatedArray addObjectsFromArray:[rotatedArray subarrayWithRange:range]]; 
[rotatedArray removeObjectsInRange:range]; 

// now return or use rotatedArray 

Ruota a destra sarebbe simile, ma la gamma sarebbe alla fine dell'array, e si sarebbe inserire gli oggetti a partire dall'indice 0 con -insertObjects:atIndexes::

// Make sure we don't overrun the array if the rotation is larger. 
numberOfObjectsToRotateRight %= array.count; 

NSRange range = NSMakeRange(array.count - numberOfObjectsToRotateRight, numberOfObjectsToRotateRight); 
NSMutableArray * rotatedArray = [array mutableCopy]; 

NSArray * movedObjects = [rotatedArray subarrayWithRange:range]; 
[rotatedArray removeObjectsInRange:range]; 
[rotatedArray insertObjects:movedObjects atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, numberOfObjectsToRotateRight)]]; 

// now return or use rotatedArray 
1
-(NSArray*)shiftForward:(BOOL)forward withbits:(int)bit 
{ 
    NSInteger length = [array count]; 
    NSArray *right; 
    NSArray *left; 

    if (forward) { 
     //code for right shift 
     right = [array subarrayWithRange:(NSRange){ .location = length - bit, .length = bit }]; 
     left = [array subarrayWithRange:(NSRange){ .location = 0, .length = length - bit}]; 
     return [right arrayByAddingObjectsFromArray:left]; 
    }else{ 
     //code for left shift 
     left = [array subarrayWithRange:(NSRange){ .location =0, .length = bit }]; 
     right= [array subarrayWithRange:(NSRange){ .location = bit, .length = length - bit}]; 
     return [right arrayByAddingObjectsFromArray:left]; 
    } 
} 

- (void)viewDidLoad 
{ 
    array = @[@"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9"]; 
    NSLog(@"array is %@",[self shiftForward:YES withbits:3]); 
}