我想在Objective-C程序中使用队列数据结构。在C ++中,我使用STL队列。 Objective-C中的等效数据结构是什么?如何推送/弹出项目?

有帮助吗?

解决方案

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必然是最佳解决方案,特别是如果您要添加类别的方法,因为如果方法名称冲突,它们可能会导致脆弱性。对于快速n-dirty队列,我将使用这些方法在可变数组的末尾添加和删除。但是,如果您计划重用该队列,或者您希望您的代码更具可读性和不言而喻,那么可能就是您想要的专用队列类。

Cocoa没有内置的,但还有其他选项,你也不必从头开始编写。对于仅添加和删除末端的真实队列,循环缓冲区阵列是一种非常快速的实现。查看 CHDataStructures.framework ,这是我一直致力于Objective-C的库/框架。它有各种队列实现,以及堆栈,deques,排序集等。出于您的目的, 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实际上是实施为2-3树;您通常不必关心在任意索引处添加或删除NSMutableArray中的对象的性能特征。

re: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

这是我的实施,希望它有所帮助。

有点简约,所以你必须通过将新头保存在pop并保留旧头来保持头部的轨迹

@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 ++代码。

对Objective C对象使用STL队列/向量/列表等的一个问题是它们通常不支持保留/释放/自动释放内存管理。这很容易解决C ++ Smart Pointer容器类,它在构造时保留Objective C对象并在销毁时释放它。根据您在STL队列中的内容,通常不需要这样做。

使用NSMutableArray。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top