2012-06-25 14 views
14

Jaki jest najprostszy sposób wyszukiwania binarnego na (już) posortowanym NSArray?Jak przeprowadzić wyszukiwanie binarne w NSArray?

niektórych potencjalnych sposobów I zauważyli dotychczas to:

  1. Zastosowanie CFArrayBSearchValues (wspomniane here) - to będzie działać na NSArray?
  2. Sposób indexOfObject:inSortedRange:options:usingComparator: z NSArray zakłada tablica jest posortowana i bierze opts param typu NSBinarySearchingOptions - to znaczy, że wykonuje wyszukiwanie binarne? docs to znaczy:

    Zwraca wskaźnika w określonym zakresie, o przedmiotu w porównaniu z elementami w macierzy z wykorzystaniem danego bloku NSComparator.

  3. Napisz moją własną metodę wyszukiwania binarnego (coś podobnego do linii this).

Dodam, że jestem programowania dla iOS 4.3+

Dzięki z góry.

+0

Dlaczego zamiast tego nie używać NSDictionary? objectForKey: wyszuka ciebie. – progrmr

+0

Kilka pytań na ten temat - jaka jest korzyść ze słownika nad tablicą dla wyszukiwania obiektów? Ponadto, aby użyć sugerowanej metody, nie musiałbym znać klucza obiektu? Powodem, dla którego przeszukuję tablicę dla obiektu, jest to, że nie znam jego indeksu - jeśli zmienię na słownikową, oznacza to, że nie znam klucza. – Barjavel

Odpowiedz

7

1 i 2 będą działać. # 2 jest prawdopodobnie łatwiejsze; Z pewnością nie ma sensu, aby ta metoda robiła coś innego niż wyszukiwanie binarne (jeśli zakres jest powyżej pewnego rozmiaru, powiedzmy). Na dużej tablicy można zweryfikować, że wykonuje tylko niewielką liczbę porównań.

+0

To jest to, co myślałem - doktorzy wydają się trochę brakuje w tym, że tak naprawdę nie twierdzą, że wykonuje wyszukiwanie binarne (po prostu mocno sugerują). Jeśli przejdę do testu, który zasugerowałeś, na pewno opublikuję tutaj moje wyniki. – Barjavel

14

Druga opcja jest zdecydowanie najprostsza. Ole Begemann posiada wpis w blogu, w jaki sposób korzystać z NSArray „s indexOfObject:inSortedRange:options:usingComparator: metody:

NSArray *sortedArray = ... // must be sorted 
id searchObject = ... 
NSRange searchRange = NSMakeRange(0, [sortedArray count]); 
NSUInteger findIndex = [sortedArray indexOfObject:searchObject 
           inSortedRange:searchRange 
             options:NSBinarySearchingFirstEqual 
           usingComparator:^(id obj1, id obj2) 
           { 
            return [obj1 compare:obj2]; 
           }]; 

Zobacz NSArray Binary Search

+1

Należy pamiętać, że musisz sprawdzić, czy findIndex znajduje się poniżej [sortedArray count], jeśli później korzystasz z findIndex. Spowoduje to awarię, jeśli element nie istnieje i próbujesz go pobrać za pomocą sortedArray [findIndex]. – NatashaTheRobot

3

Dziwię się, że nikt nie wspomniał o wykorzystanie NSSet, która [gdy zawiera obiekty z przyzwoite hash, takie jak większość typów danych Foundation] wykonuje stałe wyszukiwanie czasu. Zamiast dodawać obiekty do tablicy, należy zamiast tego dodać do zestawu (lub dodać je do obu, jeśli zachowasz posortowaną kolejność do innych celów [lub alternatywnie na iOS 5.0 lub Mac OS X 10.7 jest NSOrderedSet]).

Aby ustalić, czy dany obiekt istnieje w zestawie:

NSSet *mySet = [NSSet setWithArray:myArray]; // try to do this step only once 

if ([mySet containsObject:someObject]) 
{ 
    // do something 
} 

Alternatywnie:

NSSet *mySet = [NSSet setWithArray:myArray]; // try and do this step only once 

id obj = [mySet member:someObject]; 

// obj is now set to nil if the object doesn't exist or it is 
// set to an object that "isEqual:" to someObject (which could be 
// someObject itself). 

Ważne jest, aby wiedzieć, że stracisz żadnych korzyści wydajności konwertowania tablicę do zestawu za każdym razem, gdy wykonujesz wyszukiwanie, najlepiej będziesz używał wstępnie skonstruowanego zestawu zawierającego obiekty, które chcesz przetestować.

2
//Method to pass array and number we are searching for. 
- (void)binarySearch:(NSArray *)array numberToEnter:(NSNumber *)key{ 


    NSUInteger minIndex = 0; 
    NSUInteger maxIndex = array.count-1; 
    NSUInteger midIndex = array.count/2; 


    NSNumber *minIndexValue = array[minIndex]; 
    NSNumber *midIndexValue = array[midIndex]; 
    NSNumber *maxIndexValue = array[maxIndex]; 

    //Check to make sure array is within bounds 
    if (key > maxIndexValue || key < minIndexValue) { 
     NSLog(@"Key is not within Range"); 
     return; 
    } 

    NSLog(@"Mid indexValue is %@", midIndexValue); 

    //If key is less than the middleIndexValue then sliceUpArray and recursively call method again 
    if (key < midIndexValue){ 
     NSArray *slicedArray = [array subarrayWithRange:NSMakeRange(minIndex, array.count/2)]; 
     NSLog(@"Sliced array is %@", slicedArray); 
     [self binarySearch:slicedArray numberToEnter:key]; 

    //If key is greater than the middleIndexValue then sliceUpArray and recursively call method again 
    } else if (key > midIndexValue) { 
     NSArray *slicedArray = [array subarrayWithRange:NSMakeRange(midIndex+1, array.count/2)]; 
     NSLog(@"Sliced array is %@", slicedArray); 
     [self binarySearch:slicedArray numberToEnter:key]; 

    } else { 
     //Else number was found 
     NSLog(@"Number found"); 
    } 

} 


//Call Method 

@interface ViewController() 
@property(nonatomic)NSArray *searchArray; 
@end 


- (void)viewDidLoad { 
    [super viewDidLoad]; 
//Initialize the array with 10 values 
    self.searchArray = @[@1,@2,@3,@4,@5,@6,@7,@8,@9,@10]; 

//Call Method and search for any number 
    [self binarySearch:self.searchArray numberToEnter:@5]; 
    // Do any additional setup after loading the view, typically from a nib. 
} 
Powiązane problemy