问题
I am implementing queued flood fill algorithm and need to store and retrieve pairs of numbers in NSMutableArray
.
Basically, I am creating an array
m_queue = [NSMutableArray array];
then at some time I populate the array
[m_queue addObject:[NSValue valueWithCGPoint:CGPointMake(x + 1, y)]];
then I retrieve data for the next iteration and remove the value at the beginning of the array
NSValue* value = [m_queue objectAtIndex:0];
[m_queue removeObjectAtIndex:0];
CGPoint nextPoint = [value CGPointValue];
[self queueFloodFill8:nextPoint.x y:nextPoint.y];
The question is: what can I do to avoid creating large number of CGPoint
and NSValue
objects?
I don't really need points, the algorithm uses pairs of integer values, so I think there might be a better way to store such pairs.
UPDATE: I looked into implementing C-style solution like @mattjgalloway and @CRD suggested.
I've introduced
typedef struct lookup_point_struct
{
int x;
int y;
struct lookup_point_struct* next;
} LookupPoint;
and have rewritten code to use linked list of such structs instead of NSMutableArray
and CGPoint
/NSValue
.
All this made my code about 3 times faster. And memory consumption dropped significantly too.
回答1:
There wouldn't really be a better Objective-C / Foundation way of doing it, apart from maybe creating your own class such as NumberPair
or something which you put into the array rather than using NSValue
and CGPoint
. It might be slightly more memory efficient to do that and you could make NumberPair
contain two integers rather than floats like you are concerned about. Something like:
@interface NumberPair : NSObject
@property (nonatomic, assign) int x;
@property (nonatomic, assign) int y;
@end
@implementation NumberPair
@synthesize x, y;
@end
...
m_queue = [NSMutableArray array];
NumberPair *newPair = [[NumberPair alloc] init];
newPair.x = 1;
newPair.y = 2;
[m_queue addObject:newPair];
...
NumberPair *nextPoint = [m_queue objectAtIndex:0];
[m_queue removeObjectAtIndex:0];
[self queueFloodFill8:nextPoint.x y:nextPoint.y];
Other than that you could do a more C-like thing of having a struct
containing two integers, create a dynamically allocated array to store the structs (you'd need to know the max size of the queue or keep reallocating). Something like:
typedef struct {
int x;
int y;
} NumberPair;
NumberPair *m_queue = (NumberPair*)malloc(sizeof(NumberPair) * QUEUE_SIZE);
// ... etc
Also, you might want to check out my MJGStack class which wraps NSMutableArray
to provide a stack like interface which you might be able to adjust slightly to do what you want rather than using NSMutableArray
directly. Although that's not essential by any means.
回答2:
How large do you expect your m_queue
array to get?
If the cost of the NSMutableArray
and NSValue
objects (CGPoint
is a struct, no real cost there) is impacting your algorithm then consider using a C-style array of structs as a circular buffer together with two indexes for front/back of the queue. You can abstract this into a queue class (or an adt using functions to save on dynamic method call overhead if you need to).
If you need to deal with an unbounded queue you can malloc
& realloc
the array with your queue class/adt as needed (which is essentially what NSMutableArray
does behind the scenes but with more overhead for its generality).
来源:https://stackoverflow.com/questions/9110009/fast-way-to-store-and-retrieve-pairs-of-numbers-in-objective-c