iOS-数据结构之链表以及二叉树

(一)前言

对于频繁使用或者是操作的数据应当使用链表,提升效率;

(1)链表的优点:链表插入和删除节点付出的代价较小,主要的操作在于prev或next指针的重指向。缺点:链表不能通过下标或者是key查询某个节点,要想获取某一指定的节点,需要从_headNode从头开始遍历,消耗是极大的。

(2)数组、字典等数据结构,相对于链表而言,遍历的效率要好得多,也可以通过下标或key获取指定的元素,这个恰好是链表的缺点;而数组、字典等,在添加或删除元素之后,会从头到尾重新的排列所有的元素,消耗极大;

因此,结合两者的优点,下面所要介绍的双向链表内容,会使用dictionary保存所有的节点信息,以便通过key能获取到指定的节点,用于链表的操作;

(3)二叉树,大多数操作都采用递归思想,比如添加节点、前序遍历、中序遍历、后序遍历以及计算节点数等;(递归调用是通过栈来实现的,每调用一次函数,系统都将函数当前的变量、返回地址等信息保存为一个栈帧压入到栈中,那么一旦要处理的运算很大或者数据很多,有可能会导致很多函数调用或者很大的栈帧,这样不断的压栈,很容易导致栈的溢出);

 

(二)双向链表;

(1)双向链表节点类,包含key、value以及前节点和后节点等信息;

#import <Foundation/Foundation.h>

@interface NTLinkedNode : NSObject

@property (nonatomic, strong) NSString *key;
@property (nonatomic, strong) NSString *value;
@property (nonatomic, strong) NTLinkedNode *prev;
@property (nonatomic, strong) NTLinkedNode *next;

@end



 

(2)双向链表管理类,可以添加、移动、删除节点;

#import <Foundation/Foundation.h>
@class NTLinkedNode;

@interface NTLinkedMap : NSObject

- (void)addNodeAtHead:(NTLinkedNode *)node;
- (void)addNode:(NTLinkedNode *)newNode beforeNodeForKey:(NSString *)key;
- (void)addNode:(NTLinkedNode *)newNode behindNodeForKey:(NSString *)key;
- (void)bringNodeToHead:(NTLinkedNode *)node;

- (void)readAllNode;
- (void)removeNodeForKey:(NSString *)key;
- (NTLinkedNode *)removeTailNode;

- (void)headNode;
- (void)tailNode;

@end



#import "NTLinkedMap.h"
#import "NTLinkedNode.h"

@interface NTLinkedMap () {
    
    NTLinkedNode *_headNode;//头节点;
    NTLinkedNode *_tailNode;//尾节点;
    NSMutableDictionary *dicKeyValue;//用于保存所有节点;
}

@end

@implementation NTLinkedMap

- (instancetype)init {
    
    self = [super init];
    if (self) {
        
        dicKeyValue = [NSMutableDictionary dictionary];
    }
    
    return self;
}

//将节点添加在头部之前;
- (void)addNodeAtHead:(NTLinkedNode *)node {
    
    dicKeyValue[node.key] = node;
    if (_headNode) {
        
        node.next = _headNode;
        _headNode.prev = node;
        _headNode = node;
        
    } else {
        
        _headNode = _tailNode = node;
    }
}

//在指定的节点之前添加新节点;
- (void)addNode:(NTLinkedNode *)newNode beforeNodeForKey:(NSString *)key {
    
    NTLinkedNode *node = dicKeyValue[key];
    dicKeyValue[newNode.key] = newNode;
    
    if (!_headNode && !_tailNode) {
        
        _headNode = _tailNode = newNode;
    }
    
    if (node) {
        
        if ([_headNode isEqual:node]) {
            
            _headNode = newNode;
        }
        
        if (node.prev) {
            
            newNode.prev = node.prev;
            node.prev.next = newNode;
        }
        
        newNode.next = node;
        node.prev = newNode;
    }
}


//在指定的节点之后添加新节点;
- (void)addNode:(NTLinkedNode *)newNode behindNodeForKey:(NSString *)key {
    
    NTLinkedNode *node = dicKeyValue[key];
    dicKeyValue[newNode.key] = newNode;
    
    if (!_headNode && !_tailNode) {
        
        _headNode = _tailNode = newNode;
        
    } else {
        
        if (node) {
            
            if ([_tailNode isEqual:node]) {
                
                _tailNode = newNode;
            }
            
            if (node.next) {
                
                node.next.prev = newNode;
                newNode.next = node.next;
            }
            
            newNode.prev = node;
            node.next = newNode;
        }
    }
}


//移动node至头部节点;
- (void)bringNodeToHead:(NTLinkedNode *)node {
    
    if ([_headNode isEqual:node]) {
        
        return;
    }
    
    if ([_tailNode isEqual:node]) {
        
        _tailNode = node.prev;
        _tailNode.next = nil;
        
    } else {
        
        node.next.prev = node.prev;
        node.prev.next = node.next;
    }
    
    _headNode.prev = node;
    node.next = _headNode;
    node.prev = nil;
    _headNode = node;
}


//移除某个节点;
- (void)removeNodeForKey:(NSString *)key {
    
    NTLinkedNode *node = dicKeyValue[key];
    if (node) {
        
        [dicKeyValue removeObjectForKey:key];
        if (node.next) {
            
            node.next.prev = node.prev;
        }
        
        if (node.prev) {
            
            node.prev.next = node.next;
        }
        
        if ([_headNode isEqual:node]) {
            
            _headNode = node.next;
        }
        
        if ([_tailNode isEqual:node]) {
            
            _tailNode = node.prev;
        }
    }
}


//移除尾部节点;
- (NTLinkedNode *)removeTailNode {
    
    if (!_tailNode) {
        
        return nil;
    }
    
    NTLinkedNode *tailNode = _tailNode;
    [dicKeyValue removeObjectForKey:_tailNode.key];
    if (_headNode == _tailNode) {
        
        _headNode = _tailNode = nil;
        
    } else {
        
        _tailNode = _tailNode.prev;
        _tailNode.next = nil;
    }
    
    return tailNode;
}


//遍历所有的node节点;
- (void)readAllNode {
    
    if (_headNode) {
        
        NTLinkedNode *node = _headNode;
        while (node) {
            
            NSLog(@"key -- %@, value -- %@", node.key, node.value);
            node = node.next;
        }
    }
}

- (void)headNode {
    
    NSLog(@"head node key -- %@, head node value -- %@", _headNode.key, _headNode.value);
    NSLog(@"node count -- %lu", (unsigned long)dicKeyValue.count);
}

- (void)tailNode {
    
    NSLog(@"tail node key -- %@, tail node value -- %@", _tailNode.key, _tailNode.value);
    NSLog(@"node count -- %lu", (unsigned long)dicKeyValue.count);
}
@end

 

(三)单向链表;

(1)单向链表节点类,保存节点信息;

#import <Foundation/Foundation.h>

@interface NTSingleLinkedNode : NSObject

@property (nonatomic, strong) NSString *key;
@property (nonatomic, strong) NSString *value;
@property (nonatomic, strong) NTSingleLinkedNode *next;

@end

 

(2)单向链表管理类,用于添加、删除、移动以及遍历链表节点;

#import <Foundation/Foundation.h>
@class NTSingleLinkedNode;

@interface NTSingleLinkedList : NSObject

- (void)addNodeAtHead:(NTSingleLinkedNode *)node;
- (NTSingleLinkedNode *)addNode:(NTSingleLinkedNode *)newNode behindNodeForKey:(NSString *)key;

- (NTSingleLinkedNode *)removeNode:(NTSingleLinkedNode *)node;
- (NTSingleLinkedNode *)selectNode:(NSString *)key;
- (void)bringNodeToHead:(NTSingleLinkedNode *)node;

- (void)readAllNode;

@end


#import "NTSingleLinkedList.h"
#import "NTSingleLinkedNode.h"

@interface NTSingleLinkedList () {
    
    NTSingleLinkedNode *_headNode;
    NSMutableDictionary *dictKeyValue;
}

@end

@implementation NTSingleLinkedList

- (instancetype)init {
    
    self = [super init];
    if (self) {
        
        dictKeyValue = [NSMutableDictionary dictionary];
    }
    
    return self;
}

//新节点添加在头部之前;
- (void)addNodeAtHead:(NTSingleLinkedNode *)node {
    
    dictKeyValue[node.key] = node;
    if (_headNode) {
        
        node.next = _headNode;
        _headNode = node;
        
    } else {
        
        _headNode = node;
    }
}


//新节点添加值指定节点之后(节点不可重复);
- (NTSingleLinkedNode *)addNode:(NTSingleLinkedNode *)newNode behindNodeForKey:(NSString *)key {
    
    if (!key) {
        
        return _headNode;
    }
    
    NTSingleLinkedNode *node = dictKeyValue[key];
    if (dictKeyValue[newNode.key]) {//判断节点是否存在;
        
        return _headNode;
    }
    
    dictKeyValue[newNode.key] = newNode;
    newNode.next = node.next;
    node.next = newNode;
    
    
    return newNode;
}


//删除节点;
- (NTSingleLinkedNode *)removeNode:(NTSingleLinkedNode *)node {
    
    if (!_headNode || !node) {
        
        return _headNode;
    }
    
    NTSingleLinkedNode *tempNode;
    [dictKeyValue removeObjectForKey:node.key];
    
    //若删除节点不是尾节点,则将当前节点替换成当前节点的下一个节点;
    if (node.next) {
        
        tempNode = node.next;
        node.next = node.next.next;
        node.key = tempNode.key;
        node.value = tempNode.value;
        
        tempNode = nil;
        return _headNode;
        
    } else {
        
        //从_headNode开始遍历链表,找到tempNode即node的前一个节点;
        tempNode = _headNode;
        while (tempNode.next && ![tempNode.next isEqual:node]) {
            
            tempNode = tempNode.next;
        }
        
        if (tempNode.next) {
            
            tempNode.next = node.next;
        }
    }
    
    return _headNode;
}


//将node移至头部head;
- (void)bringNodeToHead:(NTSingleLinkedNode *)node {
    
    if (!_headNode || !node) {
        
        return;
    }
    
    if ([_headNode isEqual:node]) {
        
        return ;
    }
    
    //从_headNode开始遍历链表,找到tempNode即node的前一个节点;
    NTSingleLinkedNode *tempNode = _headNode;
    while (tempNode.next && ![tempNode.next isEqual:node]) {
        
        tempNode = tempNode.next;
    }
    
    if (tempNode.next) {
        
        tempNode.next = node.next;
    }
    
    node.next = _headNode;
    _headNode = node;
}


//查找单向列表中的一个节点;
- (NTSingleLinkedNode *)selectNode:(NSString *)key {
    
    //当然了,因为定义了字典dicKeyVaue,可以通过此字典,直接返回对应key的node;
    //return dicKeyVaue[key];
    
    NTSingleLinkedNode *tempNode = _headNode;
    while (tempNode) {
        
        if ([tempNode.key isEqualToString:key]) {
            
            return tempNode;
        }
        
        tempNode = tempNode.next;
    }
    
    return _headNode;
}


//遍历所有节点;
- (void)readAllNode {
    
    NTSingleLinkedNode *tempNode = _headNode;
    while (tempNode) {
        
        NSLog(@"node key -- %@, node value -- %@", tempNode.key, tempNode.value);
        tempNode = tempNode.next;
    }
}
@end

 

(四)二叉树(二叉排序树),参考来自网络收集资料

(1)二叉树节点定义,包含左节点leftNode、右节点rightNode、父节点(未使用)以及节点值value;

#import <Foundation/Foundation.h>

@interface NTBinaryTreeNode : NSObject

@property (nonatomic, assign) NSInteger value;

/**
 *  父节点
 */
@property (nonatomic, strong) NTBinaryTreeNode *fatherNode;

/**
 *  左节点
 */
@property (nonatomic, strong) NTBinaryTreeNode *leftNode;
/**
 *  右节点
 */
@property (nonatomic, strong) NTBinaryTreeNode *rightNode;

@end

 

(2)二叉树管理类,创建和遍历二叉树以及增加二叉树节点等;

#import <Foundation/Foundation.h>
@class NTBinaryTreeNode;

@interface NTBinaryTree : NSObject

+ (NTBinaryTreeNode *)createTreeWithValues:(NSArray *)values;
+ (NTBinaryTreeNode *)addTreeNode:(NTBinaryTreeNode *)treeNode value:(NSInteger)value;

+ (NTBinaryTreeNode *)invertBinaryTree:(NTBinaryTreeNode *)rootNode;

+ (NTBinaryTreeNode *)treeNodeAtIndex:(NSInteger)index inTree:(NTBinaryTreeNode *)treeNode;

+ (void)levelTraverseTree:(NTBinaryTreeNode *)treeNode handler:(void (^)(NTBinaryTreeNode *node))handler;
+ (void)depthTraverseTree:(NTBinaryTreeNode *)treeNode handler:(void (^)(NTBinaryTreeNode *node))handler;

+ (void)preOrderTraverseTree:(NTBinaryTreeNode *)rootNode handler:(void(^)(NTBinaryTreeNode *treeNode))handler;

//非递归遍历二叉树;
+ (void)preTraverseTree:(NTBinaryTreeNode *)treeNode handler:(void (^)(NTBinaryTreeNode *node))handler;
+ (void)inTraverseTree:(NTBinaryTreeNode *)treeNode handler:(void (^)(NTBinaryTreeNode *node))handler;
+ (void)postTraverseTree:(NTBinaryTreeNode *)treeNode handler:(void (^)(NTBinaryTreeNode *node))handler;

@end



#import "NTBinaryTree.h"
#import "NTBinaryTreeNode.h"

@implementation NTBinaryTree


/**
 *  创建二叉排序树
 *  二叉排序树:左节点值全部小于根节点值,右节点值全部大于根节点值
 *
 *  @param values 数组
 *
 *  @return 二叉树根节点
 */
+ (NTBinaryTreeNode *)createTreeWithValues:(NSArray *)values {
    
    NTBinaryTreeNode *root = nil;
    for (NSInteger i = 0; i < values.count; i++) {
        
        NSInteger value = [(NSNumber *)[values objectAtIndex:i] integerValue];
        root = [NTBinaryTree addTreeNode:root value:value];
    }
    
    return root;
}


//递归添加节点,始终返回根节点;
+ (NTBinaryTreeNode *)addTreeNode:(NTBinaryTreeNode *)treeNode value:(NSInteger)value {
    
    //根节点不存在,创建节点
    if (!treeNode) {
        
        treeNode = [NTBinaryTreeNode new];
        treeNode.value = value;
        //NSLog(@"node:%@", @(value));
        
    } else if (value <= treeNode.value) {
        
        NSLog(@"to left");
        //值小于根节点,则插入到左子树
        treeNode.leftNode = [NTBinaryTree addTreeNode:treeNode.leftNode value:value];
        
    } else {
        
        NSLog(@"to right");
        //值大于根节点,则插入到右子树
        treeNode.rightNode = [NTBinaryTree addTreeNode:treeNode.rightNode value:value];
    }
    
    return treeNode;
}


//反转二叉树(左右节点互换),递归思想;
+ (NTBinaryTreeNode *)invertBinaryTree:(NTBinaryTreeNode *)rootNode {
    
    if (!rootNode) {
        
        return nil;
    }
    
    if (!rootNode.leftNode && !rootNode.rightNode) {
        
        return rootNode;
    }
    
    [self invertBinaryTree:rootNode.leftNode];//递归反转左节点;
    [self invertBinaryTree:rootNode.rightNode];//递归反转右节点;
    NTBinaryTreeNode *tempNode = rootNode.leftNode;
    rootNode.leftNode = rootNode.rightNode;
    rootNode.rightNode = tempNode;
    
    
    return rootNode;
}

//查找index位置的node -- 从0开始查找,根据先进先出的顺序查找;
+ (NTBinaryTreeNode *)treeNodeAtIndex:(NSInteger)index inTree:(NTBinaryTreeNode *)treeNode {
    
    if (!treeNode || index < 0) {
        
        return nil;
    }
    
    NSMutableArray *queryArray = [NSMutableArray array];
    [queryArray addObject:treeNode];
    
    while (queryArray.count > 0) {
        
        NTBinaryTreeNode *node = [queryArray firstObject];
        
        if (index == 0) {
            
            return node;
        }
        
        [queryArray removeObjectAtIndex:0];
        index--;
        
        if (node.leftNode) {
            
            [queryArray addObject:node.leftNode];
        }
        
        if (node.rightNode) {
            
            [queryArray addObject:node.rightNode];
        }
    }
    
    return nil;
}


//广度优先遍历二叉树,从上到下,从左到右依次遍历,先遍历完一层再遍历下一层;
+ (void)levelTraverseTree:(NTBinaryTreeNode *)treeNode handler:(void (^)(NTBinaryTreeNode *))handler {
    
    if (!treeNode) {
        
        return;
    }
    
    NSMutableArray *queryArray = [NSMutableArray array];
    [queryArray addObject:treeNode];
    
    while (queryArray.count > 0) {
        
        NTBinaryTreeNode *node = [queryArray firstObject];
        
        if (handler) {
            
            handler(node);
        }
        
        [queryArray removeObjectAtIndex:0];//仿照队列fifo原则;
        
        if (node.leftNode) {
            
            [queryArray addObject:node.leftNode];
        }
        
        if (node.rightNode) {
            
            [queryArray addObject:node.rightNode];
        }
    }
}


//深度优先遍历,先遍历左子树,再遍历右子树;
+ (void)depthTraverseTree:(NTBinaryTreeNode *)treeNode handler:(void (^)(NTBinaryTreeNode *))handler {
    
    if (!treeNode) {
        
        return;
    }
    
    NSMutableArray *queryArray = [NSMutableArray array];
    [queryArray addObject:treeNode];
    
    while (queryArray.count > 0) {
        
        NTBinaryTreeNode *node = [queryArray firstObject];
        
        if (handler) {
            
            handler(node);
        }
        
        [queryArray removeObjectAtIndex:0];//仿照队列fifo原则;
        
        if (node.rightNode) {
            
            [queryArray addObject:node.rightNode];
        }
        
        if (node.leftNode) {
            
            [queryArray addObject:node.leftNode];
        }
    }
}


/**
 *  前序遍历 (中序遍历 -- 先左子树,再根,再右子树;后序遍历 -- 先左子树,再右子树,再根。)
 *  先访问根,再遍历左子树,再遍历右子树;递归思想,每一个不为空的节点都重复先访问根,再遍历左子树,再遍历右子树的流程;
 *
 *  @param rootNode 根节点
 *  @param handler  访问节点处理函数
 */
+ (void)preOrderTraverseTree:(NTBinaryTreeNode *)rootNode handler:(void(^)(NTBinaryTreeNode *treeNode))handler {
    
    if (rootNode) {
        
        //读取节点信息;
        if (handler) {
            
            handler(rootNode);
        }
        
        [self preOrderTraverseTree:rootNode.leftNode handler:handler];
        [self preOrderTraverseTree:rootNode.rightNode handler:handler];
    }
}


//非递归 -- 模拟节点进出栈方法实现,前序遍历;
+ (void)preTraverseTree:(NTBinaryTreeNode *)treeNode handler:(void (^)(NTBinaryTreeNode *))handler {
    
    if (!treeNode) {
        
        return;
    }
    
    NSMutableArray *queryArray = [NSMutableArray array];
    NTBinaryTreeNode *node = treeNode;
    
    while (node || queryArray.count > 0) {
        
        while (node) {
            
            //读取节点信息;
            if (handler) {
                
                handler(node);
            }
            
            [queryArray addObject:node];
            node = node.leftNode;
        }
        
        if (queryArray.count > 0) {
            
            node = [queryArray lastObject];
            [queryArray removeObject:node];
            node = node.rightNode;
        }
    }
}


//非递归 -- 模拟节点进出栈方法实现,中序遍历;
+ (void)inTraverseTree:(NTBinaryTreeNode *)treeNode handler:(void (^)(NTBinaryTreeNode *))handler {
    
    if (!treeNode) {
        
        return;
    }
    
    NTBinaryTreeNode *node = treeNode;
    NSMutableArray *queryArray = [NSMutableArray array];
    
    while (node || queryArray.count > 0) {
        
        while (node) {
            
            [queryArray addObject:node];
            node = node.leftNode;
        }
        
        if (queryArray.count > 0) {
            
            node = [queryArray lastObject];
            [queryArray removeObject:node];
            
            //读取节点信息;
            if (handler) {
                
                handler(node);
            }
            
            node = node.rightNode;
        }
    }
}


//非递归 -- 模拟节点进出栈方法实现,后序遍历;
+ (void)postTraverseTree:(NTBinaryTreeNode *)treeNode handler:(void (^)(NTBinaryTreeNode *))handler {
    
    if (!treeNode) {
        
        return;
    }
    
    NTBinaryTreeNode *preNode = nil;
    NTBinaryTreeNode *curNode;
    NSMutableArray *queryArray = [NSMutableArray array];
    [queryArray addObject:treeNode];
    
    while (queryArray.count > 0) {
        
        //(1)当前节点左右孩子都不存在,可以直接访问该节点;
        //(2)存在左孩子节点或者是右孩子节点,且其左右孩子节点已经被访问过,也可以直接访问该节点;
        curNode = [queryArray lastObject];
        if ((!curNode.leftNode && !curNode.rightNode) || (preNode && ([preNode isEqual:curNode.leftNode] || [preNode isEqual:curNode.rightNode]))) {
            
            if (handler) {
                
                handler(curNode);
            }
            
            [queryArray removeObject:curNode];
            preNode = curNode;
            
        }  else {
            
            if (curNode.rightNode) {
                
                [queryArray addObject:curNode.rightNode];
            }
            
            if (curNode.leftNode) {
                
                [queryArray addObject:curNode.leftNode];
            }
        }
    }
}
@end

 

转载于:https://my.oschina.net/u/1450995/blog/783137

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值