Answers:
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一定是最好的解决方案,尤其是在添加带有类别的方法时,由于方法名称冲突可能导致它们的脆弱性,因此尤其如此。对于快速脏的队列,我将使用方法在可变数组的末尾添加和删除。但是,如果您打算重用队列,或者希望代码更具可读性和自明性,则可能需要专用的队列类。
Cocoa没有内置选项,但是还有其他选择,您也不必从头开始编写一个。对于只在末端添加和删除的真正队列,循环缓冲区数组是一种非常快速的实现。查看CHDataStructures.framework,这是我一直在研究的Objective-C库/框架。它具有队列的各种实现,以及堆栈,双端队列,排序集等。就您的目的而言,与使用NSMutableArray相比,CHCircularBufferQueue显着更快(即可以用基准进行验证)和可读性(主观上是主观的)。
使用本机的Objective-C类而不是C ++ STL类的一大优点是,它与Cocoa代码无缝集成,并且在编码/解码(序列化)方面工作得更好。它也与垃圾回收和快速枚举(两者均存在于10.5+中,但仅在iPhone上具有后者)完美配合,您不必担心什么是Objective-C对象以及什么是C ++对象。
最后,尽管在任一端添加和删除NSMutableArray都比标准C数组更好,但它也不是队列的最快解决方案。对于大多数应用程序来说,这是令人满意的,但是如果需要速度,则循环缓冲区(或在某些情况下,为使高速缓存行保持高温而优化的链表)可以轻易地使NSMutableArray中断。
据我所知,Objective-C没有提供Queue数据结构。最好的办法是创建一个NSMutableArray
,然后用[array lastObject]
,[array removeLastObject]
以获取项目,并[array insertObject:o atIndex:0]
...
如果您经常这样做,则可能要创建一个Objective-C类别来扩展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可以有效地用于同一件事。如果需要,您可以定义一个类别来添加弹出/推入方法,以方便使用。
在使用类别的解决方案NSMutableArray
不是真正的队列,因为NSMutableArray
公开的操作是队列的超集。例如,不应允许您从队列中间删除项目(因为这些类别解决方案仍然可以让您执行此操作)。最好封装功能,这是面向对象设计的主要原理。
标准队列
#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
标准队列
#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作为扩展名,而不是.m即可使用Objective C ++代替Objective C)。然后,您可以使用STL或任何其他C ++代码。
将STL队列/向量/列表等与Objective C对象一起使用的一个问题是它们通常不支持保留/释放/自动释放内存管理。这可以通过C ++ Smart Pointer容器类轻松解决,该容器类在构造时保留其Objective C对象,在销毁时释放它。根据您放入STL队列中的内容,这通常不是必需的。
-count
事先致电以检查是否有任何对象要出队。确实,这是一个偏好问题。