How to perform binary search on NSArray?

前端 未结 5 670
失恋的感觉
失恋的感觉 2020-12-09 11:06

What is the simplest way to do a binary search on an (already) sorted NSArray?

Some potential ways I have spotted so far include:

  1. The use

相关标签:
5条回答
  • 2020-12-09 11:12

    I'm surprised that nobody mentioned the use of NSSet, which [when it contains objects with a decent hash, such as most Foundation data types] performs constant time lookups. Instead of adding your objects to an array, add then to a set instead (or add them to both if you need to retain a sorted order for other purposes [or alternatively on iOS 5.0 or Mac OS X 10.7 there is NSOrderedSet]).

    To determine whether an object exists in a set:

    NSSet *mySet = [NSSet setWithArray:myArray]; // try to do this step only once
    
    if ([mySet containsObject:someObject])
    {
        // do something
    }
    

    Alternatively:

    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).
    

    It is important to know that you will lose any performance benefit if you convert the array to a set each time you do a lookup, ideally you will be using a preconstructed set containing the objects you want to test.

    0 讨论(0)
  • 2020-12-09 11:20

    The second option is definitely the simplest. Ole Begemann has a blog entry on how to use the NSArray's indexOfObject:inSortedRange:options:usingComparator: method:

    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];
                                  }];
    

    See NSArray Binary Search

    0 讨论(0)
  • 2020-12-09 11:22
    //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.
    }
    
    0 讨论(0)
  • 2020-12-09 11:25

    CFArrayBSearchValues should work—NSArray * is toll-free bridged with CFArrayRef.

    0 讨论(0)
  • 2020-12-09 11:31

    1 and 2 will both work. #2 is probably easier; it certainly doesn't make sense for that method to do anything other than a binary search (if the range is above a certain size, say). You could verify on a large array that it only does a small number of comparisons.

    0 讨论(0)
提交回复
热议问题