ฉันต้องการใช้โครงสร้างข้อมูลคิวในโปรแกรม Objective-C ของฉัน ใน C ++ ฉันใช้คิว STL โครงสร้างข้อมูลที่เทียบเท่าใน Objective-C คืออะไร? ฉันจะพุช / ป๊อปไอเท็มได้อย่างไร
ฉันต้องการใช้โครงสร้างข้อมูลคิวในโปรแกรม Objective-C ของฉัน ใน C ++ ฉันใช้คิว STL โครงสร้างข้อมูลที่เทียบเท่าใน Objective-C คืออะไร? ฉันจะพุช / ป๊อปไอเท็มได้อย่างไร
คำตอบ:
เวอร์ชันของเบ็นเป็นสแต็กแทนที่จะเป็นคิวดังนั้นฉันจึงปรับแต่งเล็กน้อย:
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 จำเป็นต้องเป็นทางออกที่ดีที่สุดโดยเฉพาะอย่างยิ่งหากคุณกำลังเพิ่มวิธีการที่มีหมวดหมู่เนื่องจากความเปราะบางที่อาจทำให้เกิดขึ้นได้หากชื่อเมธอดชนกัน สำหรับคิวที่รวดเร็วและสกปรกฉันจะใช้วิธีการเพิ่มและลบที่ส่วนท้ายของอาร์เรย์ที่ไม่แน่นอน อย่างไรก็ตามหากคุณวางแผนที่จะใช้คิวซ้ำหรือถ้าคุณต้องการให้โค้ดของคุณอ่านง่ายและชัดเจนขึ้นคลาสคิวเฉพาะอาจเป็นสิ่งที่คุณต้องการ
โกโก้ไม่มีในตัว แต่มีทางเลือกอื่นและคุณไม่จำเป็นต้องเขียนตั้งแต่ต้น สำหรับคิวจริงที่เพิ่มและลบออกจากส่วนท้ายเท่านั้นอาร์เรย์บัฟเฟอร์แบบวงกลมเป็นการใช้งานที่รวดเร็วมาก ลองดูCHDataStructures.frameworkซึ่งเป็นไลบรารี / กรอบงานใน Objective-C ที่ฉันได้ทำ มันมีการใช้งานคิวที่หลากหลายเช่นเดียวกับสแต็ก, deques, ชุดที่เรียงลำดับ ฯลฯ สำหรับวัตถุประสงค์ของคุณCHCircularBufferQueueนั้นเร็วกว่าอย่างมาก (เช่นสามารถพิสูจน์ได้ด้วยการวัดประสิทธิภาพ) และอ่านได้ง่ายกว่า (ยอมรับในเชิงอัตนัย) มากกว่าการใช้ NSMutableArray
ข้อดีอย่างหนึ่งของการใช้คลาส Objective-C ดั้งเดิมแทนคลาส C ++ STL คือการรวมเข้ากับรหัสโกโก้อย่างราบรื่นและทำงานได้ดีขึ้นมากกับการเข้ารหัส / ถอดรหัส (การทำให้เป็นอนุกรม) นอกจากนี้ยังทำงานได้อย่างสมบูรณ์แบบกับการรวบรวมขยะและการแจงนับอย่างรวดเร็ว (ทั้งที่มีอยู่ใน 10.5+ แต่มีเพียงรุ่นหลังบน iPhone) และคุณไม่ต้องกังวลว่าวัตถุ Objective-C คืออะไรและวัตถุ C ++ คืออะไร
สุดท้ายนี้แม้ว่า NSMutableArray จะดีกว่าอาร์เรย์ C มาตรฐานเมื่อเพิ่มและลบจากปลายทั้งสองข้าง แต่ก็ไม่ใช่วิธีแก้ปัญหาที่เร็วที่สุดสำหรับคิว สำหรับแอปพลิเคชันส่วนใหญ่เป็นที่น่าพอใจ แต่ถ้าคุณต้องการความเร็วบัฟเฟอร์แบบวงกลม (หรือในบางกรณีรายการที่เชื่อมโยงได้รับการปรับให้เหมาะสมเพื่อให้สายแคชร้อน) สามารถทำให้ NSMutableArray ยากขึ้นได้อย่างง่ายดาย
เท่าที่ฉันรู้ Objective-C ไม่มีโครงสร้างข้อมูลคิว ทางออกที่ดีที่สุดของคุณคือการสร้างNSMutableArray
และใช้[array lastObject]
, [array removeLastObject]
สามารถดึงข้อมูลรายการและ[array insertObject:o atIndex:0]
...
หากคุณทำสิ่งนี้NSMutableArray
บ่อยมากคุณอาจต้องการสร้างประเภท Objective-C เพื่อขยายการทำงานของคลาส หมวดหมู่ช่วยให้คุณสามารถเพิ่มฟังก์ชันลงในคลาสที่มีอยู่ได้แบบไดนามิก (แม้กระทั่งคลาสที่คุณไม่มีซอร์ส) - คุณสามารถสร้างคิวได้ดังนี้:
(หมายเหตุ: รหัสนี้ใช้สำหรับสแต็กไม่ใช่คิวดูความคิดเห็นด้านล่าง)
@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 - นี่คือการปรับใช้วิธีการ 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 ได้หรือไม่? Objective C ++ เป็นส่วนเสริมของ C ++ (เพียงใช้. mm เป็นส่วนขยายแทน. m เพื่อใช้ Objective C ++ แทน Objective C) จากนั้นคุณสามารถใช้ STL หรือรหัส C ++ อื่น ๆ
ปัญหาหนึ่งของการใช้ STL que / vector / list etc กับ Objective C คือโดยทั่วไปแล้วพวกเขาไม่สนับสนุนการจัดการหน่วยความจำคง / release / autorelease สิ่งนี้สามารถทำงานได้อย่างง่ายดายกับคลาสคอนเทนเนอร์ C ++ Smart Pointer ซึ่งยังคงรักษาวัตถุ Objective C ไว้เมื่อสร้างและเผยแพร่เมื่อถูกทำลาย ขึ้นอยู่กับสิ่งที่คุณใส่ในคิว STL ซึ่งมักไม่จำเป็น
ใช้ NSMutableArray
-count
ล่วงหน้าเพื่อตรวจสอบว่ามีวัตถุใดที่จะยกเลิกการจัดคิวหรือไม่ มันเป็นเรื่องของความชอบจริงๆ