• OC中双向链表的实现


    双向链表的概念

    双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。

    双向链表的实现

    链表的是由节点构成的,节点的创建代码如下:

    @interface BOLoopListNode : NSObject
    {
        BOLoopListNode *mpPrev;
        id mpData;
        BOLoopListNode *mpNext;
    }
    /**
     指向前一个数据
     */
    @property (nonatomic, strong) BOLoopListNode *prev;
    
    /**
     当前数据
     */
    @property (nonatomic, strong) id data;
    
    /**
     指向后一个数据
     */
    @property (nonatomic, strong) BOLoopListNode *next;
    
    + (BOLoopListNode *)node;
    + (BOLoopListNode *)nodeWithData:(id)data;
    - (id)initWithData:(id)data;

    主要方法

    1.链表的初始化方法

    - (instancetype)init {
        if (self = [super init]) {
            mpHead = [[BOLoopListNode alloc] init];
            mpHead.prev = mpHead;
            mpHead.next = mpHead;
            mpCurrent = mpHead;
        }
        return self;
    }

    链表的初始化方法,此时已经形成了一个双向链表。该链表只有一个头结点,并且该节点的前驱和后继都指向自己。

    2.拼接节点

    - (BOLoopListNode *) appendNode:(BOLoopListNode *)pNode withPrevNode:(BOLoopListNode *) pPrevNode
    {
        if (!pNode)
        {
            return nil;
        }
        pNode.prev = pPrevNode;
        pNode.next = pPrevNode.next;
        pPrevNode.next.prev = pNode;
        pPrevNode.next = pNode;
        muCount++;
        return pNode;
    }

    在pPrevNode处,插入pNode节点,并使当前链表的计数器加一。使pNode的前驱指向pPrevNode,使pNode的后继指向pPrevNode的next,并且使pPrevNode的next的前驱指向pNode。

    3.移除节点

    - (BOLoopListNode *) removeNode:(BOLoopListNode*) pNode
    {
        if (!pNode)
        {
            pNode = mpCurrent;
        }
        if (pNode != mpHead)
        {
            pNode.prev.next = pNode.next;
            pNode.next.prev = pNode.prev;
            if (mpCurrent == pNode)
            {
                if (mpCurrent.next != mpHead)
                {
                    mpCurrent = mpCurrent.next;
                }
                else
                {
                    mpCurrent = mpCurrent.prev;
                }
                
            }
            muCount--;
            NSLog(@"%zd", muCount);
            return pNode;
        }
        else if(pNode == mpHead)
        {
            return nil;
        }
        return nil;
    }

    在判断要移除的节点非空并且不是头结点后,把pNode的prev的后继指向pNode的next,把pNode.next的前驱指向pNode的prev。并判断mpCurrent指针是否在该删除的节点上。

    4.添加链表到目标链表

    -(void)joinToListWithTargetList:(BOLoopList *)targetList withNode:(BOLoopListNode *)pNode {
        if (muCount == 0) {
            return;
        }else if (muCount == 1) {
            [targetList appendNode:[self getBegin] withPrevNode:pNode];
            muCount = 0;
        }else {
            pNode.next.prev = mpHead.prev;
            mpHead.prev.next = pNode.next;
            pNode.next = mpHead.next;
            mpHead.next.prev = pNode;
            mpHead.next = mpHead;
            mpHead.prev = mpHead;
            targetList.listCount += muCount;
            muCount = 0;
        }
    }

    判断要添加的链表长度,如果为一,当成一个节点拼接进去,若是不是一,就把该链表拼接到目标链表的尾端。

    5.排序函数

    // 升序排列
    - (void)sortByAscendingOrder {
        if (muCount < 2)
        {
            //空链表与一个节点的链表无需排序
            return;
        }
        //记录下开始节点
        BOLoopListNode* pBeginNode = mpHead.next.next;
        BOLoopListNode* pEndNode = mpHead.prev;
        BOLoopListNode* pCurrentNode = pBeginNode;
        //取下链表中第一个节点之外的节点
        mpHead.next.next = mpHead;
        mpHead.next.prev = mpHead;
        mpHead.prev = mpHead.next;
        //使取下节点中的开始节点的前一节点与结束节点的后一节点指向nil
        pBeginNode.prev = nil;
        pEndNode.next = nil;
        BOLoopListNode* pEnumNode = nil;
        BOLoopListNode* pAddNode = nil;
        kNodeCompare compareResult = kNodeCompareLessThan;
        
        while (pCurrentNode)
        {
            pAddNode = pCurrentNode;
            pCurrentNode = pCurrentNode.next;
            for (pEnumNode = mpHead.prev; pEnumNode != mpHead; pEnumNode = pEnumNode.prev)
            {
                //当前链表从大到小(降序)遍历
            
                compareResult = (kNodeCompare)[self.delegate nodeCompare:(pAddNode.data) withSecondData:pEnumNode.data];;
                if (compareResult != kNodeCompareLessThan)
                {
                    //要添加的节点不小于当前链表中枚举节点
                    //将要添加的节点加到枚举节点后面
                    pAddNode.next = pEnumNode.next;
                    pAddNode.next.prev = pAddNode;
                    pAddNode.prev = pEnumNode;
                    pEnumNode.next = pAddNode;
                    break;
                }
            }
            //要添加的节点比链表中所有的节点都小
            //加到头结点的后面
            if (pEnumNode == mpHead)
            {
                pAddNode.next = mpHead.next;
                mpHead.next.prev = pAddNode;
                pAddNode.prev = mpHead;
                mpHead.next = pAddNode;
            }
        }
    }

    这里以升序排序为例,在这里为什么取链表中第一个节点之外的节点。相当于在第二个节点之前截断,第一个节点用作比较,此时从某种意义上说,自头指针那儿分割,已经变成了两个链表。每次取head指针左边的和右边的比较,在合适的节点处插入。

    而代码:

    compareResult = (kNodeCompare)[self.delegate nodeCompare:(pAddNode.data) withSecondData:pEnumNode.data];

    因为链表中的数据类型是不确定的,所以比较方法也是不确定的。则是外界成为了我的代理,传进来的比较链表中数据的方法。

    协议代码如下:

    typedef enum
    {
        kNodeCompareLessThan = -1,
        kNodeCompareEqual,
        kNodeCompareMoreThan
    }kNodeCompare;
    
    @protocol kNodeCompareDelegate <NSObject>
    - (kNodeCompare) nodeCompare:(id)firsrData withSecondData:(id)secondData;

    降序排序跟这个类似,就不多说了。

    详细代码BOLoopListNode类如下:

    #import <Foundation/Foundation.h>
    
    @interface BOLoopListNode : NSObject
    {
        BOLoopListNode *mpPrev;
        id mpData;
        BOLoopListNode *mpNext;
    }
    /**
     指向前一个数据
     */
    @property (nonatomic, strong) BOLoopListNode *prev;
    
    /**
     当前数据
     */
    @property (nonatomic, strong) id data;
    
    /**
     指向后一个数据
     */
    @property (nonatomic, strong) BOLoopListNode *next;
    
    + (BOLoopListNode *)node;
    + (BOLoopListNode *)nodeWithData:(id)data;
    - (id)initWithData:(id)data;
    @end
    #import "BOLoopListNode.h"
    
    @implementation BOLoopListNode
    
    - (void)dealloc {
        self.data = nil;
        self.prev = nil;
        self.next = nil;
    }
    - (instancetype)init {
        return [self initWithData:nil];
    }
    - (instancetype)initWithData:(id)data {
        if (self = [super init]) {
            self.prev = nil;
            self.data = data;
            self.next = nil;
        }
        return self;
    }
    
    + (BOLoopListNode *)node {
        BOLoopListNode *node = [[BOLoopListNode alloc] init];
        return node;
    }
    
    + (BOLoopListNode *)nodeWithData:(id)data {
        BOLoopListNode *node = [[BOLoopListNode alloc] initWithData:data];
        return node;
    }
    @end

    BOLoopList类代码如下:

    #import <Foundation/Foundation.h>
    #import "BOLoopListNode.h"
    
    typedef enum
    {
        kNodeCompareLessThan = -1,
        kNodeCompareEqual,
        kNodeCompareMoreThan
    }kNodeCompare;
    
    @protocol kNodeCompareDelegate <NSObject>
    - (kNodeCompare) nodeCompare:(id)firsrData withSecondData:(id)secondData;
    @end;
    
    @interface BOLoopList : NSObject
    {
        BOLoopListNode *mpHead;
        BOLoopListNode *mpCurrent;
        NSUInteger muCount;
    }
    @property (nonatomic, weak) id<kNodeCompareDelegate> delegate;
    /**头指针*/
    @property (nonatomic, strong) BOLoopListNode *head;
    
    /**开始的指针*/
    @property (nonatomic, strong) BOLoopListNode *begin;
    
    /**末尾指针*/
    @property (nonatomic, strong) BOLoopListNode *end;
    
    /**当前的指针*/
    @property (nonatomic, strong) BOLoopListNode *current;
    
    /**当前链表数据个数*/
    @property (nonatomic, assign) NSUInteger listCount;
    
    + (id)list;
    
    /**得到头部指针*/
    - (BOLoopListNode *)getHead;
    
    /**得到开始数据的指针*/
    - (BOLoopListNode *)getBegin;
    
    /**得到末尾数据*/
    - (BOLoopListNode *)getEnd;
    
    /**移动当前数据指针到开始*/
    - (BOLoopListNode *)moveBegin;
    
    /**移动当前数据指针到末尾*/
    - (BOLoopListNode *)moveEnd;
    
    /**移动到头指针*/
    - (BOLoopListNode *)moveHead;
    
    /**移动当前数据指针到下一个*/
    - (BOLoopListNode*) moveNext;
    
    /**移动当前指针到上一个*/
    - (BOLoopListNode*) movePrev;
    
    /**拼接数据*/
    - (BOLoopListNode *)appendData:(id)data;
    
    /**在某一节点处拼接数据*/
    - (BOLoopListNode *)appendData:(id)data withPrevNode:(BOLoopListNode *)prevNode;
    
    /**拼接节点*/
    - (BOLoopListNode *)appendNode:(BOLoopListNode *)pNode;
    
    /**在某个节点处拼接节点*/
    - (BOLoopListNode *)appendNode:(BOLoopListNode *)pNode withPrevNode:(BOLoopListNode *)pNode;
    
    /**删除某个数据对应的节点*/
    - (BOLoopListNode *)removeNodeWithData:(id)data;
    
    /**删除某个节点*/
    - (BOLoopListNode *)removeNode:(BOLoopListNode *)pNode;
    
    /**添加一个链表到另外一个链表*/
    - (void)joinToListWithTargetList:(BOLoopList *)targetList withNode:(BOLoopListNode *)pNode;
    
    /**升序排列链表*/
    - (void) sortByAscendingOrder;
    
    /**按降序排序*/
    - (void) sortByDeScendingOrder;
    
    /**在某个节点后面拼接一个节点*/
    - (BOLoopListNode*) preAppendNode:(BOLoopListNode*) pNode withNextNode:(BOLoopListNode*) pNextNode;
    
    /**清空链表*/
    - (void)clearList;
    @end
    #import "BOLoopList.h"
    @interface BOLoopList()
    
    @end
    @implementation BOLoopList
    @synthesize listCount = muCount;
    
    - (instancetype)init {
        if (self = [super init]) {
            mpHead = [[BOLoopListNode alloc] init];
            mpHead.prev = mpHead;
            mpHead.next = mpHead;
            mpCurrent = mpHead;
        }
        return self;
    }
    + (id)list {
        return [[self alloc] init];
    }
    
    - (BOLoopListNode *)getHead {
        return mpHead;
    }
    
    - (BOLoopListNode *)getBegin {
        return mpHead.next;
    }
    
    - (BOLoopListNode *)getEnd {
        return mpHead.prev;
    }
    
    - (BOLoopListNode *) moveBegin
    {
        return mpCurrent = mpHead.next;
    }
    
    - (BOLoopListNode *) moveEnd
    {
        return mpCurrent = mpHead.prev;
    }
    
    - (BOLoopListNode *) moveHead
    {
        return mpCurrent = mpHead;
    }
    
    - (BOLoopListNode *) moveNext
    {
        return mpCurrent = mpCurrent.next;
    }
    
    - (BOLoopListNode *) movePrev
    {
        return mpCurrent = mpCurrent.prev;
    }
    
    - (BOLoopListNode *) appendData:(id) data
    {
        return [self appendData:data withPrevNode:mpHead.prev];
    }
    
    - (BOLoopListNode *) appendData:(NSString *)data withPrevNode:(BOLoopListNode *) pPrevNode
    {
        NSLog(@"liupeng%@",data);
        BOLoopListNode* pNode = [BOLoopListNode nodeWithData:data];
        return [self appendNode:pNode withPrevNode:pPrevNode];
    }
    
    - (BOLoopListNode *) appendNode:(BOLoopListNode *) pNode
    {
        return [self appendNode:pNode withPrevNode:mpHead.prev];
    }
    
    - (BOLoopListNode *) appendNode:(BOLoopListNode *)pNode withPrevNode:(BOLoopListNode *) pPrevNode
    {
        if (!pNode)
        {
            return nil;
        }
        pNode.prev = pPrevNode;
        pNode.next = pPrevNode.next;
        pPrevNode.next.prev = pNode;
        pPrevNode.next = pNode;
        muCount++;
        return pNode;
    }
    - (BOLoopListNode*) removeNodeWithData:(id) data
    {
        for (BOLoopListNode* pNode = mpHead.next; pNode != mpHead; pNode = pNode.next)
        {
            if (pNode.data == data)
            {
                return [self removeNode:pNode];
            }
        }
        return nil;
    }
    
    - (BOLoopListNode *) removeNode:(BOLoopListNode*) pNode
    {
        if (!pNode)
        {
            pNode = mpCurrent;
        }
        if (pNode != mpHead)
        {
            pNode.prev.next = pNode.next;
            pNode.next.prev = pNode.prev;
            if (mpCurrent == pNode)
            {
                if (mpCurrent.next != mpHead)
                {
                    mpCurrent = mpCurrent.next;
                }
                else
                {
                    mpCurrent = mpCurrent.prev;
                }
                
            }
            muCount--;
            NSLog(@"%zd", muCount);
            return pNode;
        }
        else if(pNode == mpHead)
        {
            return nil;
        }
        return nil;
    }
    -(void)joinToListWithTargetList:(BOLoopList *)targetList withNode:(BOLoopListNode *)pNode {
        if (muCount == 0) {
            return;
        }else if (muCount == 1) {
            [targetList appendNode:[self getBegin] withPrevNode:pNode];
            muCount = 0;
        }else {
            pNode.next.prev = mpHead.prev;
            mpHead.prev.next = pNode.next;
            pNode.next = mpHead.next;
            mpHead.next.prev = pNode;
            mpHead.next = mpHead;
            mpHead.prev = mpHead;
            targetList.listCount += muCount;
            muCount = 0;
        }
    }
    - (void) clearList
    {
        mpCurrent = mpHead.next;
        while (muCount)
        {
            mpCurrent = mpCurrent.next;
            muCount--;
        }
        mpCurrent = mpHead;
        mpHead.prev = mpHead;
        mpHead.next = mpHead;
       
        return;
    }
    // 升序排列
    - (void)sortByAscendingOrder {
        if (muCount < 2)
        {
            //空链表与一个节点的链表无需排序
            return;
        }
        //记录下开始节点
        BOLoopListNode* pBeginNode = mpHead.next.next;
        BOLoopListNode* pEndNode = mpHead.prev;
        BOLoopListNode* pCurrentNode = pBeginNode;
        //取下链表中第一个节点之外的节点
        mpHead.next.next = mpHead;
        mpHead.next.prev = mpHead;
        mpHead.prev = mpHead.next;
        //使取下节点中的开始节点的前一节点与结束节点的后一节点指向nil
        pBeginNode.prev = nil;
        pEndNode.next = nil;
        BOLoopListNode* pEnumNode = nil;
        BOLoopListNode* pAddNode = nil;
        kNodeCompare compareResult = kNodeCompareLessThan;
        
        while (pCurrentNode)
        {
            pAddNode = pCurrentNode;
            pCurrentNode = pCurrentNode.next;
            for (pEnumNode = mpHead.prev; pEnumNode != mpHead; pEnumNode = pEnumNode.prev)
            {
                //当前链表从大到小(降序)遍历
            
                compareResult = (kNodeCompare)[self.delegate nodeCompare:(pAddNode.data) withSecondData:pEnumNode.data];
                if (compareResult != kNodeCompareLessThan)
                {
                    //要添加的节点不小于当前链表中枚举节点
                    //将要添加的节点加到枚举节点后面
                    pAddNode.next = pEnumNode.next;
                    pAddNode.next.prev = pAddNode;
                    pAddNode.prev = pEnumNode;
                    pEnumNode.next = pAddNode;
                    break;
                }
            }
            //要添加的节点比链表中所有的节点都小
            //加到头结点的后面
            if (pEnumNode == mpHead)
            {
                pAddNode.next = mpHead.next;
                mpHead.next.prev = pAddNode;
                pAddNode.prev = mpHead;
                mpHead.next = pAddNode;
            }
        }
    }
    
    // 降序排列
    - (void)sortByDeScendingOrder {
        if (muCount < 2)
        {
            //空链表与一个节点的链表无需排序
            return;
        }
        //记录下开始节点
        BOLoopListNode* pBeginNode = mpHead.next.next;
        BOLoopListNode* pEndNode = mpHead.prev;
        BOLoopListNode* pCurrentNode = pBeginNode;
        //取下链表中第一个节点之外的节点
        mpHead.next.next = mpHead;
        mpHead.next.prev = mpHead;
        mpHead.prev = mpHead.next;
        //使取下节点中的开始节点的前一节点与结束节点的后一节点指向nil
        pBeginNode.prev = nil;
        pEndNode.next = nil;
        BOLoopListNode* pEnumNode = nil;
        BOLoopListNode* pAddNode = nil;
        kNodeCompare compareResult = kNodeCompareLessThan;
        
        while (pCurrentNode)
        {
            pAddNode = pCurrentNode;
            pCurrentNode = pCurrentNode.next;
            for (pEnumNode = mpHead.next; pEnumNode != mpHead; pEnumNode = pEnumNode.next)
            {
                //当前链表从大到小(降序)遍历
                compareResult = (kNodeCompare)[self.delegate nodeCompare:(pAddNode.data) withSecondData:pEnumNode.data];
                if (compareResult != kNodeCompareLessThan)
                {
                    //要添加的节点不小于当前链表中枚举节点
                    //将要添加的节点加到枚举节点前面
                    pAddNode.prev = pEnumNode.prev;
                    pAddNode.prev.next = pAddNode;
                    pAddNode.next = pEnumNode;
                    pEnumNode.prev = pAddNode;
                    break;
                    
                }
            }
            //要添加的节点比链表中所有的节点都小
            //加到头结点的前面
            if (pEnumNode == mpHead)
            {
                pAddNode.prev = mpHead.prev;
                pAddNode.prev.next = pAddNode;
                pAddNode.next = mpHead;
                mpHead.prev = pAddNode;
            }
        }
    
    }
    
    - (BOLoopListNode*) preAppendNode:(BOLoopListNode*) pNode withNextNode:(BOLoopListNode*) pNextNode
    {
        if (!pNode)
        {
            return nil;
        }
        pNode.prev = pNextNode.prev;
        pNode.next = pNextNode;
        pNextNode.prev.next = pNode;
        pNextNode.prev = pNode;
        muCount++;
        return pNode;
    }
    @end
  • 相关阅读:
    Webdriver启动Firefox浏览器后,页面显示空白
    Windows+Python+Selenium基础篇之1-环境搭建
    office2010无法卸载问题
    .NET使用FastDBF读写DBF
    并发编程相关概念
    C#的多线程简洁笔记
    asp.net core 3.1 入口:Program.cs中的Main函数
    【WPF学习】第四十四章 图画
    .NET知识梳理——1.泛型Generic
    C#个推SDK推送安卓+iOS
  • 原文地址:https://www.cnblogs.com/muzichenyu/p/7390749.html
Copyright © 2020-2023  润新知