OC中雙向鏈表的實現

雙向鏈表的概念

雙向鏈表也叫雙鏈表,是鏈表的一種,它的每一個數據結點中都有兩個指針,分別指向直接後繼和直接前驅。因此,從雙向鏈表中的任意一個結點開始,均可以很方便地訪問它的前驅結點和後繼結點。通常咱們都構造雙向循環鏈表。node

雙向鏈表的實現

鏈表的是由節點構成的,節點的建立代碼以下:app

@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。oop

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指針是否在該刪除的節點上。atom

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;
    }
}

判斷要添加的鏈表長度,若是爲一,當成一個節點拼接進去,如果不是一,就把該鏈表拼接到目標鏈表的尾端。spa

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];

由於鏈表中的數據類型是不肯定的,因此比較方法也是不肯定的。則是外界成爲了個人代理,傳進來的比較鏈表中數據的方法。code

協議代碼以下:blog

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
相關文章
相關標籤/搜索