programing tip

Objective-C에서 대기열을 어떻게 만들고 사용합니까?

itbloger 2020. 8. 9. 10:09
반응형

Objective-C에서 대기열을 어떻게 만들고 사용합니까?


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에는 하나가 내장되어 있지 않지만 다른 옵션이 있으며 처음부터 작성할 필요가 없습니다. 끝에서 추가 및 제거 만하는 진정한 대기열의 경우 원형 버퍼 배열은 매우 빠른 구현입니다. 제가 작업해온 Objective-C의 라이브러리 / 프레임 워크 인 CHDataStructures.framework를 확인하세요 . 스택, 데크, 정렬 된 세트 등의 다양한 큐 구현이 있습니다. 사용자의 목적을 위해 CHCircularBufferQueue 는 NSMutableArray를 사용하는 것보다 훨씬 빠르고 (즉, 벤치 마크로 증명 가능) 더 읽기 쉽고 (주관적 임) 더 읽기 쉽습니다 .

C ++ STL 클래스 대신 네이티브 Objective-C 클래스를 사용할 때의 큰 장점 중 하나는 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는 효과적으로 동일한 작업에 사용할 수 있습니다. 원하는 경우 편리하게 팝 / 푸시 메서드를 추가 하는 범주정의 할 수 있습니다 .


Yes, use NSMutableArray. NSMutableArray is actually implemented as 2-3 tree; you typically need not concern yourself with the performance characteristics of adding or removing objects from NSMutableArray at arbitrary indices.


re:Wolfcow -- Here is a corrected implementation of Wolfcow's dequeue method

- (id)dequeue {
    if ([self count] == 0) {
        return nil;
    }
    id queueObject = [[[self objectAtIndex:0] retain] autorelease];
    [self removeObjectAtIndex:0];
    return queueObject;
}

The solutions that use a category on NSMutableArray are not true queues, because NSMutableArray exposes operations that are a superset of queues. For example, you should not be allowed to remove an item from the middle of a queue (as those category solutions still let you do). It is best to encapsulate functionality, a major principle of object oriented design.

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

this is my implementation, hope it helps.

Is kind of minimalistic, so you must keep the track of the head by saving the new head at pop and discarding the old head

@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

Is there some particular reason you cannot just use the STL queue? Objective C++ is a superset of C++ (just use .mm as the extension instead of .m to use Objective C++ instead of Objective C). Then you can use the STL or any other C++ code.

One issue of using the STL queue/vector/list etc with Objective C objects is that they do not typically support retain/release/autorelease memory management. This is easily worked around with a C++ Smart Pointer container class which retains its Objective C object when constructed and releases it when destroyed. Depending on what you are putting in the STL queue this is often not necessary.


Use NSMutableArray.

참고URL : https://stackoverflow.com/questions/817469/how-do-i-make-and-use-a-queue-in-objective-c

반응형