美文网首页队列
Object-c 队列的两种实现方式(数组与链表实现)

Object-c 队列的两种实现方式(数组与链表实现)

作者: 劉胡來 | 来源:发表于2020-05-09 16:27 被阅读0次
    • 队列是一个简单的等待序列,入队(新添加)的元素放在尾部,出队(删除的元素)从第一个开始。队列是先进先出结构(First In First out)
    • 构造一个队列通常需要包含以下几个接口
    • 初始化,这个过程用来设定队列的大小。
    • 入队
    • 出队
    • 判断队空
    • 判断队满
    • 实现方式一:数组实现

    例:有一个序列 1,2,3,4,5依次入队。在队列的表现形式如下:

    • 初始时,假设队列空间大小为5。
      1入队时:|1|0|0|0|0|
      2入队时:|1|2|0|0|0|
      3入队时:|1|2|3|0|0|
      4入队时:|1|2|3|4|0|
      5入队时:|1|2|3|4|5|
      入队操作的代码为:
    -(void)enqueue:(NSObject *)e{
        if (![self isFull]) {
            if (self.last == -1) {
                [self.array addObject:e];
                self.last = 0;
                if (self.first == -1) {
                    self.first = 0;
                }
            }else{
                [self.array addObject:e];
                ++self.last;
            }
        }else{
            NSLog(@"44----------队列已满");
        }
    }
    
    • 假设在队满时连续3次出队得到的元素分别为:1,2,3,出队的过程如下所示
      第一次执行出队操作:|0|2|3|4|5|
      第二次执行出队操作:|0|0|3|4|5|
      第三次执行出队操作:|0|0|0|4|5|
      出队操作的代码:
    -(NSObject*)dequeue{
        if ([self isEmpty]) {
           NSAssert(![self isEmpty], @"队列为空,不能再出队");
        }
        NSObject* tmp = [self.array objectAtIndex:0];
        [self.array removeObjectAtIndex:0];
        if(self.first == self.last){
            self.first = -1;
            self.last = -1;
        }else{
            self.first ++;
        }
        return tmp;
    }
    
    • 判断队空
      如果此种情况下我们要判断队空,只有遍历一次数组了,数组没有进行任何的赋值操作则认为队列为空,通常做法为:
    bool isEmpty = fasle;
    for(int i = 0; i < array.size;  i ++){
        if(array[i] != 0){
          isEmpty = true;
          break;
       }
    }
    

    然后判断这个isEmpty 标志即可。这种做法有一个很大缺点,就是耗时(时间复杂度O(n))。

    • 队满判断。
      在不借助其他空间判断进行队满判断很困难。在此我们引入2个标记位first与last。其中first永远指向第一个元素,last永远指向最后一个元素。判断队满、队空的语句可通过下面代码:
    //判断队满
    bool isFull = (self.last == self.size - 1)
    //判断队空
    bool isEmpty = (self.first == -1)
    

    如果对空间利用率不做要求的话,此时已经能够达到队列的要求了。仔细观察的话,在进行第三次出队的时候,再执行一次入队操作(假设入队元素为6)这个时候会发现队列已经满了,因为last已经指向了数组的最后索引了,而情况却存在前面三个空间均没有存放其他元素,结果导致了碎片出现,这是一种极大的资源浪费,这个时候循环队列这个救星应运而生,只有当满足下面条件时才判断队满
    队满判断:

    -(BOOL)isFull{
        return (self.first == 0 && self.last == self.size - 1) || self.first == self.last + 1;
    }
    

    队空还是一样

    • 循环队列入队操作逻辑为
    -(void)enqueue:(NSObject *)e{
        if (![self isFull]) {
            if (self.last == self.size - 1 || self.last == -1) {
                [self.array addObject:e];
                self.last = 0;
                if (self.first == -1) {
                    self.first = 0;
                }
            }else{
                [self.array addObject:e];
                ++self.last;
            }
        }else{
            NSLog(@"44----------队列已满");
        }
    }
    
    • 出队逻辑为:
    -(NSObject*)dequeue{
        if ([self isEmpty]) {
           NSAssert(![self isEmpty], @"队列为空,不能再出队");
        }
        NSObject* tmp = [self.array objectAtIndex:0];
        [self.array removeObjectAtIndex:0];
        if(self.first == self.last){
            self.first = -1;
            self.last = -1;
        }else if (self.first == self.size - 1){
            self.first = 0;
        }else{
            self.first ++;
        }
        return tmp;
    }
    

    *整体的代码如下:

    #import <Foundation/Foundation.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface QueueArray : NSObject
    
    -(instancetype) initWithSize:(NSInteger)size;
    
    -(void) enqueue:(NSObject*)e;
    
    
    -(NSObject*) dequeue;
    
    -(BOOL) isFull;
    -(BOOL) isEmpty;
    
    -(void) test;
    
    @end
    
    NS_ASSUME_NONNULL_END
    
    
    #import "QueueArray.h"
    
    @interface QueueArray ()
    @property(nonatomic,assign) NSInteger first;
    @property(nonatomic,assign) NSInteger last;
    @property(nonatomic,assign) NSInteger size;
    @property(nonatomic,strong) NSMutableArray* array;
    
    @end
    
    @implementation QueueArray
    
    -(instancetype)initWithSize:(NSInteger)size{
        self = [super init];
        if (self) {
            self.last = -1;
            self.first = -1;
            self.size = size;
            self.array = [[NSMutableArray alloc] init];
        }
        return self;
    }
    
    -(void)enqueue:(NSObject *)e{
        if (![self isFull]) {
            if (self.last == self.size - 1 || self.last == -1) {
                [self.array addObject:e];
                self.last = 0;
                if (self.first == -1) {
                    self.first = 0;
                }
            }else{
                [self.array addObject:e];
                ++self.last;
            }
        }else{
            NSLog(@"44----------队列已满");
        }
    }
    
    -(NSObject*)dequeue{
        if ([self isEmpty]) {
           NSAssert(![self isEmpty], @"队列为空,不能再出队");
        }
        NSObject* tmp = [self.array objectAtIndex:0];
        [self.array removeObjectAtIndex:0];
        if(self.first == self.last){
            self.first = -1;
            self.last = -1;
        }else if (self.first == self.size - 1){
            self.first = 0;
        }else{
            self.first ++;
        }
        return tmp;
    }
    
    -(BOOL)isFull{
        return (self.first == 0 && self.last == self.size - 1) || self.first == self.last + 1;
    }
    - (BOOL)isEmpty{
        return self.first == -1;
    }
    
    -(void) test{
        [self.array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){
            NSLog(@"68---------队列余下元素:%@  index:%ld",obj,idx);
        }];
        
        
    }
    
    @end
    
    
    • 链表实现方式为:
    #import <Foundation/Foundation.h>
    @class LinkedList;
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface QueueLinkedList : NSObject
    
    -(instancetype) initWithSize:(NSInteger)size;
    
    -(void) enqueue:(NSObject*)e;
    
    
    -(LinkedList*) dequeue;
    
    -(BOOL) isFull;
    -(BOOL) isEmpty;
    
    -(void) test;
    
    
    @end
    
    NS_ASSUME_NONNULL_END
    
    
    #import "QueueLinkedList.h"
    #import "LinkedList.h"
    
    @interface QueueLinkedList ()
    @property(nonatomic,assign) NSInteger first;
    @property(nonatomic,assign) NSInteger last;
    @property(nonatomic,assign) NSInteger size;
    @property(nonatomic,strong) LinkedList* linkList;
    
    @end
    
    @implementation QueueLinkedList
    
    -(instancetype)initWithSize:(NSInteger)size{
        self = [super init];
        if (self) {
            self.last = -1;
            self.first = -1;
            self.size = size;
            self.linkList = [[LinkedList alloc] init]; //创建一个链表,此处为一个头结点
            self.linkList.data = @"head";
        }
        return self;
    }
    
    -(void)enqueue:(NSObject *)e{
        if (![self isFull]) {
            LinkedList* node = [[LinkedList alloc] init];
            node.data = e;
            if (self.last == self.size - 1 || self.last == -1) {
                [self.linkList insertAfterNode:node];
                self.last = 0;
                if (self.first == -1) {
                    self.first = 0;
                }
            }else{
                [self.linkList insertAfterNode:node];
                ++self.last;
            }
            NSLog(@"48---------链表b队列实现方式入队元素:%@",e);
        }else{
            NSLog(@"44----------队列已满");
        }
    }
    
    -(LinkedList*)dequeue{
        if ([self isEmpty]) {
           NSAssert(![self isEmpty], @"队列为空,不能再出队");
        }
        LinkedList* tmp = self.linkList.next;
        [self.linkList deleteNode:tmp];
        if(self.first == self.last){
            self.first = -1;
            self.last = -1;
        }else if (self.first == self.size - 1){
            self.first = 0;
        }else{
            self.first ++;
        }
        return tmp;
    }
    
    -(BOOL)isFull{
        return (self.first == 0 && self.last == self.size - 1) || self.first == self.last + 1;
    }
    - (BOOL)isEmpty{
        return self.first == -1;
    }
    -(void)test{
        LinkedList* p = self.linkList.next;
       while (p.next != nil) {
           
           NSObject* data = p.data;
           LinkedList* next = p.next;
           NSLog(@"65---------cur data :%@ next node:%@",data,next);
           
           p = p.next;
       }
       NSLog(@"69---------cur data :%@ next node:%@",p.data,p.next);
    }
    
    
    @end
    
    
    QQ20200509-172241-HD.gif

    相关文章

      网友评论

        本文标题:Object-c 队列的两种实现方式(数组与链表实现)

        本文链接:https://www.haomeiwen.com/subject/avvknhtx.html