(一)前言
对于频繁使用或者是操作的数据应当使用链表,提升效率;
(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