سؤال

أرغب في استخدام بنية بيانات قائمة الانتظار في برنامج 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 هو بالضرورة الحل الأمثل أفضل الحل، خاصة إذا كنت تضيف طرقًا تحتوي على فئات، نظرًا للهشاشة التي يمكن أن تسببها في حالة تصادم أسماء الطرق.بالنسبة لقائمة الانتظار السريعة والقذرة، سأستخدم طرق الإضافة والإزالة في نهاية المصفوفة القابلة للتغيير.ومع ذلك، إذا كنت تخطط لإعادة استخدام قائمة الانتظار، أو إذا كنت تريد أن تكون التعليمات البرمجية الخاصة بك أكثر قابلية للقراءة وواضحة، فمن المحتمل أن تكون فئة قائمة الانتظار المخصصة هي ما تريده.

لا يحتوي Cocoa على خيار مدمج، ولكن هناك خيارات أخرى، ولا يتعين عليك كتابة واحد من الصفر أيضًا.بالنسبة لقائمة الانتظار الحقيقية التي تضيف وتزيل فقط من النهايات، فإن مصفوفة المخزن المؤقت الدائرية هي تطبيق سريع للغاية.الدفع CHDataStructures.framework, ، مكتبة/إطار عمل في Objective-C كنت أعمل عليه.لديها مجموعة متنوعة من تطبيقات قوائم الانتظار، بالإضافة إلى الأكوام، والمجموعات المصنفة، وما إلى ذلك.لأغراضك، CHCircularBufferQueue أسرع بشكل ملحوظ (أي.يمكن إثباته باستخدام المعايير) وأكثر قابلية للقراءة (ذاتية معترف بها) من استخدام NSMutableArray.

إحدى المزايا الكبيرة لاستخدام فئة Objective-C الأصلية بدلاً من فئة C++ STL هي أنها تتكامل بسلاسة مع كود Cocoa، وتعمل بشكل أفضل مع التشفير/فك التشفير (التسلسل).كما أنه يعمل بشكل مثالي مع جمع البيانات المهملة والتعداد السريع (كلاهما موجود في الإصدار 10.5+، ولكن الأخير فقط على iPhone) ولا داعي للقلق بشأن ما هو كائن Objective-C وما هو كائن C++.

أخيرًا، على الرغم من أن NSMutableArray أفضل من مصفوفة C القياسية عند الإضافة والإزالة من أي من الطرفين، إلا أنه ليس الحل الأسرع لقائمة الانتظار.يعد ذلك مرضيًا بالنسبة لمعظم التطبيقات، ولكن إذا كنت بحاجة إلى السرعة، فيمكن لمخزن مؤقت دائري (أو في بعض الحالات قائمة مرتبطة محسنة للحفاظ على خطوط ذاكرة التخزين المؤقت ساخنة) أن يتغلب بسهولة على NSMutableArray.

بقدر ما أعرف، لا يوفر Objective-C بنية بيانات قائمة الانتظار.أفضل رهان لك هو إنشاء 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 في مؤشرات التعسفية.

وإعادة: Wolfcow - هنا هو تطبيق تصحيح طريقة dequeue 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؟ الهدف C ++ هي مجموعة شاملة من C ++ (مجرد استخدام .mm كامتداد بدلا من .M استخدام الهدف C ++ بدلا من الهدف C). ثم يمكنك استخدام STL أو أي رمز آخر C ++.

والقضية واحدة من استخدام قائمة انتظار STL / ناقلات / قائمة غيرها مع كائنات C الهدف هو أنها لا عادة دعم تحتفظ / تحرير / إدارة الذاكرة autorelease. وعمل ذلك بسهولة حولها مع الذكية مؤشر الفئة C ++ الحاويات التي تحتفظ هدفها C الهدف عندما شيدت والنشرات عندما دمرت. اعتمادا على ما كنت في وضع قائمة انتظار STL هذه غالبا ما تكون غير ضرورية.

استخدم NSMutableArray.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top