मैं अपने उद्देश्य-सी कार्यक्रम में एक कतार डेटा संरचना का उपयोग करना चाहता हूं। C ++ में मैं STL कतार का उपयोग करूँगा। ऑब्जेक्टिव-सी में समतुल्य डेटा संरचना क्या है? मैं पुश / पॉप आइटम कैसे करूं?
मैं अपने उद्देश्य-सी कार्यक्रम में एक कतार डेटा संरचना का उपयोग करना चाहता हूं। C ++ में मैं STL कतार का उपयोग करूँगा। ऑब्जेक्टिव-सी में समतुल्य डेटा संरचना क्या है? मैं पुश / पॉप आइटम कैसे करूं?
जवाबों:
बेन का संस्करण एक कतार के बजाय एक स्टैक है, इसलिए मैंने इसे थोड़ा ट्विक किया:
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 , ऑब्जेक्ट-सी में एक लाइब्रेरी / फ्रेमवर्क की जाँच करें जो मैं काम कर रहा हूं। इसमें कतारों के कार्यान्वयन के साथ-साथ स्टैक, डेक्स, सॉर्ट किए गए सेट आदि हैं। आपके उद्देश्यों के लिए, CHCircularBufferQueue , NSMutableArray का उपयोग करने की तुलना में काफी तेज (यानी बेंचमार्क के साथ सिद्ध) और अधिक पठनीय (भर्ती व्यक्ति) है।
C ++ STL वर्ग के बजाय एक मूल उद्देश्य-सी कक्षा का उपयोग करने का एक बड़ा फायदा यह है कि यह कोको कोड के साथ मूल रूप से एकीकृत होता है, और एनकोड / डिकोड (क्रमबद्धता) के साथ बहुत बेहतर काम करता है। यह पूरी तरह से कचरा संग्रह और तेजी से संचय (दोनों 10.5+ में मौजूद है, लेकिन केवल iPhone पर उत्तरार्द्ध) के साथ पूरी तरह से काम करता है और आपको इस बारे में चिंता करने की जरूरत नहीं है कि एक वस्तु-सी वस्तु क्या है और सी ++ वस्तु क्या है।
अंत में, हालांकि NSMutableArray एक मानक सी सरणी से बेहतर है, जब दोनों छोर से जोड़ना और निकालना, यह कतार का सबसे तेज़ समाधान भी नहीं है। अधिकांश अनुप्रयोगों के लिए यह संतोषजनक है, लेकिन अगर आपको गति की आवश्यकता है, तो एक परिपत्र बफर (या कुछ मामलों में कैश लाइनों को गर्म रखने के लिए अनुकूलित एक लिंक की गई सूची) आसानी से एक NSMutableArray को प्रसारित कर सकता है।
जहाँ तक मुझे पता है, Objective-C एक क्यू डेटा संरचना प्रदान नहीं करता है। तुम्हारा सबसे अच्छा शर्त एक बनाने के लिए है 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 का उपयोग प्रभावी रूप से एक ही चीज़ के लिए किया जा सकता है। यदि आप चाहें तो पॉप / पुश विधियों को सुविधा के रूप में जोड़ने के लिए एक श्रेणी को परिभाषित कर सकते हैं।
हां, NSMutableArray का उपयोग करें। NSMutableArray वास्तव में 2-3 पेड़ के रूप में लागू किया गया है; आपको आम तौर पर मनमाने सूचकांकों में NSMutableArray से वस्तुओं को जोड़ने या हटाने की प्रदर्शन विशेषताओं के साथ खुद को चिंता करने की आवश्यकता नहीं है।
समाधान जो किसी श्रेणी का उपयोग करते 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
क्या कोई विशेष कारण है कि आप एसटीएल कतार का उपयोग नहीं कर सकते हैं? ऑब्जेक्टिव C ++, C ++ का एक सुपरसेट है (केवल उपयोग करें। ऑब्जेक्टिव C के बजाय ऑब्जेक्टिव C ++ का उपयोग करने के लिए .m के बजाय एक्सटेंशन के रूप में उपयोग करें)। फिर आप एसटीएल या किसी अन्य C ++ कोड का उपयोग कर सकते हैं।
उद्देश्य सी वस्तुओं के साथ एसटीएल कतार / वेक्टर / सूची आदि का उपयोग करने का एक मुद्दा यह है कि वे आम तौर पर बनाए रखने / जारी करने / ऑटोरेलिज़ मेमोरी प्रबंधन का समर्थन नहीं करते हैं। यह आसानी से C ++ स्मार्ट पॉइंटर कंटेनर क्लास के साथ काम किया जाता है, जो निर्माण के समय अपनी ऑब्जेक्टिव C ऑब्जेक्ट को बनाए रखता है और नष्ट होने पर उसे छोड़ देता है। आप एसटीएल कतार में क्या डाल रहे हैं, इसके आधार पर यह अक्सर आवश्यक नहीं होता है।
-count
जांचने के लिए पहले से कॉल कर सकते हैं कि क्या कोई वस्तुओं को नष्ट करना है। यह वास्तव में वरीयता की बात है।