iOS - 节点,链表的实现
2018-10-27 本文已影响122人
路飞_Luck
序言
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。
一 节点
链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
详情代码如下
- ListNode.h
/**
模拟链表实现
*/
@interface ListNode : NSObject
/** 上个节点 */
@property (strong , nonatomic) ListNode *previous;
/** 下个节点 */
@property (strong , nonatomic) ListNode *next;
/** 当前节点内容 */
@property (strong , nonatomic) id content;
/** int */
@property(nonatomic, assign) int value;
/** 打印从当前节点开始之后所有的节点数据 */
- (void)printAllListNode;
@end
- ListNode.m
@implementation ListNode
- (int)value {
if (_content != nil && [_content isKindOfClass:NSClassFromString(@"NSNumber")]) {
return [(NSNumber *)_content intValue];
}
return 0;
}
// 打印从当前节点开始之后所有的节点数据
- (void)printAllListNode {
ListNode *curNode = self;
while (curNode) {
ListNode *preNode = curNode.previous;
ListNode *nextNode = curNode.next;
NSLog(@"curNode=%p, value=%d, preNode=%p, nextNode=%p",curNode, curNode.value, preNode, nextNode);
curNode = curNode.next;
}
}
@end
二 链表
- LinkedArray.h
/**
模拟链表实现
*/
@interface LinkedArray : NSObject
/** 数组长度 */
@property (assign , nonatomic) NSUInteger size;
/** 数组初始化 */
+ (instancetype)array;
/** 通过一个 number 数组返回一个链表 */
- (instancetype)initLiknedArrayWithNunbers:(NSArray *)numbers;
/** 添加元素 */
- (void)addObject:(NSObject *)obj;
/** 移除指定元素 */
- (void)remove:(NSObject *)obj;
/** 移除指定索引元素 */
- (void)removeAtIndex:(NSInteger)index;
/** 获取指定位置的值 */
- (NSObject *)objectAtIndex:(NSInteger)index;
/** 获取第一个节点 */
- (ListNode *)getFirstListNode;
/** 获取最后换一个节点 */
- (ListNode *)getLastListNode;
/** 获取指定位置节点 */
- (ListNode *)getListNodeAtIndex:(int)index;
/** 打印所有节点 */
- (void)printAllListNode;
@end
- LinkedArray.m
@interface LinkedArray()
@property (nonatomic, strong) ListNode *first; //首个节点
@property (nonatomic, strong) ListNode *last; //最后节点
@end
@implementation LinkedArray
//构造方法
+ (instancetype)array {
return [[self alloc]init];
}
/** 通过一个 number 数组返回一个链表 */
- (instancetype)initLiknedArrayWithNunbers:(NSArray *)numbers {
self = [super init];
if (self) {
[self createLinkedArray:numbers];
}
return self;
}
#pragma mark - add
//添加元素
- (void)addObject:(NSObject *)obj {
if (!obj) return;
_size ++ ;
ListNode *node = [[ListNode alloc]init];
//首个节点为空
if (!_first) {
_first = node;
_last = node;
node.previous = nil;
node.next = nil;
node.content = obj;
return;
}
//数组中有值
node.previous = _last;
_last.next = node;
node.next = nil;
node.content = obj;
_last = node;
}
#pragma mark - remove
//移除元素
- (void)remove:(NSObject *)obj {
if (!obj||!_size) return;
ListNode *tmpNode = _first;
for (NSInteger index = 0; index < _size; index ++) {
if ([tmpNode.content isEqual:obj]) {
[self removeNode:tmpNode]; //移除节点
break;
}
}
}
//根据索引移除元素
- (void)removeAtIndex:(NSInteger)index {
if (index<0||index>=_size) return;
ListNode *tmpNode = _first;
for (NSInteger i = 0; i < _size; i ++) {
if (i == index) {
[self removeNode:tmpNode]; //移除节点
break;
}
tmpNode = tmpNode.next;
}
}
#pragma mark - get
//获取指定索引元素
- (NSObject *)objectAtIndex:(NSInteger)index {
if (index<0||index>=_size) return nil;
ListNode *tmpNode = _first;
for (NSInteger i = 0; i < _size; i ++) {
if (i == index) {
return tmpNode.content;
}
tmpNode = tmpNode.next;
}
return nil;
}
#pragma mark - get
- (ListNode *)getFirstListNode {
return _first;
}
- (ListNode *)getLastListNode {
return _last;
}
// 获取指定位置节点
- (ListNode *)getListNodeAtIndex:(int)index {
if (index >= _size) {
return nil;
}
if (_first == nil) {
return nil;
}
ListNode *curListNode = _first.next;
for (int i = 0; i < index; i++) {
curListNode = curListNode.next;
}
return curListNode;
}
#pragma mark - other function
// 打印所有节点
- (void)printAllListNode {
ListNode *curNode = [self getFirstListNode];
if (curNode == nil) {
return;
}
while (curNode) {
ListNode *preNode = curNode.previous;
ListNode *nextNode = curNode.next;
NSLog(@"curNode=%p, value=%d, preNode=%p, nextNode=%p",curNode, curNode.value, preNode, nextNode);
curNode = curNode.next;
}
}
#pragma mark - private
//私有
- (void)removeNode:(ListNode *)node {
//连接上下节点
ListNode *preNode = node.previous;
ListNode *nextNode = node.next;
preNode.next = nextNode;
nextNode.previous = preNode;
node.content = nil; //清空被移除节点内容
_size -- ;//长度更新
}
// 初始化一个链表
- (void)createLinkedArray:(NSArray *)numbers {
if (numbers == nil || numbers.count == 0) {
return;
}
// 生成一个链表
for (int i = 0; i < numbers.count; i++) {
[self addObject:numbers[i]];
}
}
@end
使用
题目描述 删除链表中重复的结点
链表.png详细代码如下
/** 删除 重复节点 */
- (void)deleteDuplicationNode {
NSMutableArray *numbers = [NSMutableArray array];
for (int i = 0; i < 10; i++) {
if (i / 2 == 1) {
[numbers addObject:@(2)];
} else if (i / 3 == 1) {
[numbers addObject:@(3)];
} else {
[numbers addObject:@(i)];
}
}
LinkedArray *linkArray = [[LinkedArray alloc] initLiknedArrayWithNunbers:numbers];
NSLog(@"原始链表数据:");
[linkArray printAllListNode];
NSLog(@"------------------");
ListNode *firstNode = [linkArray getFirstListNode];
ListNode *headNode = [self deleteDuplicationListNode:firstNode];
NSLog(@"删除重复节点后的链表数据:");
[headNode printAllListNode];
}
// 删除重复节点
- (ListNode *)deleteDuplicationListNode:(ListNode *)pHeadNode {
if (pHeadNode == nil || pHeadNode.next == nil) {
return pHeadNode;
}
ListNode *next = pHeadNode.next;
if (pHeadNode.value == next.value) {
while (next != nil && pHeadNode.value == next.value) {
next = next.next;
}
return [self deleteDuplicationListNode:next];
} else {
pHeadNode.next = [self deleteDuplicationListNode:pHeadNode.next];
return pHeadNode;
}
}
测试案例代码
// 18.在 O(1) 时间内删除链表节点
- (void)deleteNode {
DeleteNode_18 *deleteNode = [[DeleteNode_18 alloc] init];
[deleteNode deleteNode];
}
运行结果
image.png如有错误,欢迎指正,多多点赞,打赏更佳,您的支持是我写作的动力。