我想在我的Objective-C程序中使用队列数据结构。在C++中,我会使用STL队列。那么,在Objective-C中等价的数据结构是什么?如何进行push/pop操作?
我想在我的Objective-C程序中使用队列数据结构。在C++中,我会使用STL队列。那么,在Objective-C中等价的数据结构是什么?如何进行push/pop操作?
Ben的版本使用的是堆栈而不是队列,所以我稍微调整了一下:
NSMutableArray+QueueAdditions.h
@interface NSMutableArray (QueueAdditions)
- (id) dequeue;
- (void) enqueue:(id)obj;
@end
NSMutableArray+QueueAdditions.m
@implementation NSMutableArray (QueueAdditions)
// Queues are first-in-first-out, so we remove objects from the head
- (id) dequeue {
// if ([self count] == 0) return nil; // to avoid raising exception (Quinn)
id headObject = [self objectAtIndex:0];
if (headObject != nil) {
[[headObject retain] autorelease]; // so it isn't dealloc'ed on remove
[self removeObjectAtIndex:0];
}
return headObject;
}
// Add to the tail of the queue (no one likes it when people cut in line!)
- (void) enqueue:(id)anObject {
[self addObject:anObject];
//this method automatically adds to the end of the array
}
@end
只需在想要使用新方法的地方导入.h文件,并像使用任何其他NSMutableArray方法一样调用它们。
NSMutableArray
,然后使用[array lastObject]
、[array removeLastObject]
来获取项目,以及[array insertObject:o atIndex:0]
将项目插入到数组的开头。NSMutableArray
类的功能。分类允许您动态地向现有类(甚至是那些没有源代码的类)添加函数 - 您可以像这样创建一个队列:
(注意:此代码实际上是用于堆栈而不是队列。请参见下面的注释)@interface NSMutableArray (QueueAdditions)
- (id)pop;
- (void)push:(id)obj;
@end
@implementation NSMutableArray (QueueAdditions)
- (id)pop
{
// nil if [self count] == 0
id lastObject = [[[self lastObject] retain] autorelease];
if (lastObject)
[self removeLastObject];
return lastObject;
}
- (void)push:(id)obj
{
[self addObject: obj];
}
@end
虽然没有真正的队列集合类,但NSMutableArray可以用于实现类似的功能。如果需要方便地添加pop/push方法,可以定义一个category。
是的,请使用NSMutableArray。NSMutableArray实际上是作为2-3树实现的;通常您不需要关心在任意索引处向NSMutableArray添加或删除对象的性能特征。
关于Wolfcow -- 这里是Wolfcow出列方法的修正实现
- (id)dequeue {
if ([self count] == 0) {
return nil;
}
id queueObject = [[[self objectAtIndex:0] retain] autorelease];
[self removeObjectAtIndex:0];
return queueObject;
}
使用NSMutableArray
类别的解决方案并不是真正的队列,因为NSMutableArray
公开了超集的操作。例如,您不应该允许从队列中间删除项目(而这些类别解决方案仍然可以让您这样做)。封装功能是面向对象设计的一个重要原则,最好将其封装起来。
StdQueue.h
#import <Foundation/Foundation.h>
@interface StdQueue : NSObject
@property(nonatomic, readonly) BOOL empty;
@property(nonatomic, readonly) NSUInteger size;
@property(nonatomic, readonly) id front;
@property(nonatomic, readonly) id back;
- (void)enqueue:(id)object;
- (id)dequeue;
@end
StdQueue.m
#import "StdQueue.h"
@interface StdQueue ()
@property(nonatomic, strong) NSMutableArray* storage;
@end
@implementation StdQueue
#pragma mark NSObject
- (id)init
{
if (self = [super init]) {
_storage = [NSMutableArray array];
}
return self;
}
#pragma mark StdQueue
- (BOOL)empty
{
return self.storage.count == 0;
}
- (NSUInteger)size
{
return self.storage.count;
}
- (id)front
{
return self.storage.firstObject;
}
- (id)back
{
return self.storage.lastObject;
}
- (void)enqueue:(id)object
{
[self.storage addObject:object];
}
- (id)dequeue
{
id firstObject = nil;
if (!self.empty) {
firstObject = self.storage.firstObject;
[self.storage removeObjectAtIndex:0];
}
return firstObject;
}
@end
这是我的实现,希望能对你有所帮助。
这种实现方式比较简洁,所以需要通过在弹出元素时保存新的头部并丢弃旧的头部来跟踪头部。
@interface Queue : NSObject {
id _data;
Queue *tail;
}
-(id) initWithData:(id) data;
-(id) getData;
-(Queue*) pop;
-(void) push:(id) data;
@end
#import "Queue.h"
@implementation Queue
-(id) initWithData:(id) data {
if (self=[super init]) {
_data = data;
[_data retain];
}
return self;
}
-(id) getData {
return _data;
}
-(Queue*) pop {
return tail;
}
-(void) push:(id) data{
if (tail) {
[tail push:data];
} else {
tail = [[Queue alloc]initWithData:data];
}
}
-(void) dealloc {
if (_data) {
[_data release];
}
[super release];
}
@end
你为什么不能使用STL队列呢?Objective C++是C++的超集(只需使用.mm扩展名即可使用Objective C++而不是Objective C)。然后,您可以使用STL或任何其他C++代码。
使用STL队列/向量/列表等与Objective C对象存在一个问题,即它们通常不支持保留/释放/自动释放内存管理。这可以通过使用C++智能指针容器类轻松解决,该类在构造时保留其Objective C对象,并在销毁时释放它。根据您放入STL队列中的内容,通常不需要这样做。