一 链表
链表
是一种链式存储
的线性表,所有元素的内存地址不一定是连续的
特点
- 动态数组有个明显的缺点,可能会造成内存空间的大量浪费
- 链表可以做到用到多少内存就申请多少内存
二 自定义链表的实现
定义一个数据结构基本操作的基类
- List.h - 主要声明了数据操作的一些基本方法,只声明,实现交由子类完成
/// 数据结构基类
@interface List : NSObject
/**
* 清除所有元素
*/
- (void)clear;
/**
* 元素的数量
* @return int
*/
- (int)size;
/**
* 是否为空
* @return bool
*/
- (bool)isEmpty;
/**
* 是否包含某个元素
* @param element
* @return bool
*/
- (bool)contains:(id)element;
/**
* 添加元素到尾部
* @param element
*/
- (void)add:(id)element;
/**
* 获取index位置的元素
* @param index
* @return id
*/
- (id)get:(NSUInteger)index;
/**
* 设置index位置的元素
* @param index
* @param element
* @return 原来的元素ֵ
*/
- (id)set:(NSUInteger)index element:(id)element;
/**
* 在index位置插入一个元素
* @param index
* @param element
*/
- (void)add:(NSUInteger)index element:(id)element;
/**
* 删除index位置的元素
* @param index
* @return
*/
- (id)remove:(NSUInteger)index;
/**
* 查看元素的索引
* @param element
* @return
*/
- (NSUInteger)indexOf:(id)element;
链表的基类 - 主要完成链表的一些公共操作,继承自List
- AbstractList.h
/// 链表 抽象基类
@interface AbstractList : List
/** size*/
@property(nonatomic,assign)NSUInteger size;
/// 越界查询
- (bool)rangeCheck:(NSUInteger)index;
/// 添加元素越界检查
- (bool)rangeCheckForAdd:(NSUInteger)index;
@end
- AbstractList.m
/// 数量
- (NSUInteger)size {
return _size;
}
/// 是否为空
- (bool)isEmpty {
return _size == 0;
}
/// 是否包含某个元素
- (bool)contains:(id)element {
return [self indexOf:element] != NSNotFound;
}
/// 添加元素到尾部
- (void)add:(id)element {
[self add:_size element:element];
}
#pragma mark - pprivate
- (void)outOfBounds:(NSUInteger)index {
NSLog(@"index:%lu, size:%lu",(unsigned long)index,(unsigned long)_size);
}
/// 越界查询
- (bool)rangeCheck:(NSUInteger)index {
if (index < 0 || index >= _size) {
[self outOfBounds:index];
return YES;
}
return NO;
}
- (bool)rangeCheckForAdd:(NSUInteger)index {
if (index < 0 || index > _size) {
[self outOfBounds:index];
return YES;
}
return NO;
}
声明一个链表
- LinkedList.h
/// 链表
@interface LinkedList : AbstractList
/** first*/
@property(nonatomic,strong)LinkNode *first;
/** last*/
@property(nonatomic,strong)LinkNode *last;
/**
* 获取index位置对应的节点对象
* @param index
* @return
*/
- (LinkNode *)node:(NSUInteger)index;
@end
- LinkedList.m
- (void)clear {
self.size = 0;
_first = nil;
}
- (id)get:(NSUInteger)index {
return [self node:index];
}
- (id)set:(NSUInteger)index element:(id)element {
LinkNode *node = [self node:index];
id oldElement = node.element;
node.element = element;
return oldElement;
}
- (void)add:(NSUInteger)index element:(id)element {
if (index == 0) {
_first = [[LinkNode alloc] initWithElement:element next:_first];
} else {
LinkNode *prevNode = [self node:index - 1];
prevNode.next = [[LinkNode alloc] initWithElement:element next:prevNode.next];
}
self.size++;
}
- (id)remove:(NSUInteger)index {
LinkNode *node = _first;
if (index == 0) {
_first = _first.next;
} else {
LinkNode *prev = [self node:index - 1];
node = prev.next;
prev.next = node.next;
}
self.size--;
return node.element;
}
- (NSUInteger)indexOf:(id)element {
if (element == nil) { // 返回节点中第一个出现元素为空的节点
LinkNode *node = _first;
for (NSUInteger i = 0; i < self.size; i++) {
if (node.element == nil) {
return i;
}
node = node.next;
}
} else {
LinkNode *node = _first;
for (NSUInteger i = 0; i < self.size; i++) {
if (node.element == element) {
return i;
}
node = node.next;
}
}
return NSNotFound;
}
/// 获取index位置对应的节点对象
- (LinkNode *)node:(NSUInteger)index {
if ([self rangeCheck:index]) {
return nil;
}
LinkNode *node = _first;
for (int i = 0; i < index; i++) {
node = node.next;
}
return node;
}
/// 打印整个链表
- (NSString *)toString {
NSMutableString *strM = [NSMutableString string];
[strM appendString:[NSString stringWithFormat:@"size = %lu",self.size]];
[strM appendString:@" ["];
LinkNode *node = _first;
for (int i = 0; i < self.size; i++) {
if (i != 0) {
[strM appendString:@", "];
}
[strM appendString:[NSString stringWithFormat:@"%@",node.element]];
node = node.next;
}
[strM appendFormat:@"]"];
return strM.copy;
}
/// 重新系统的方法
- (NSString *)description {
[super description];
NSMutableString *strM = [NSMutableString string];
[strM appendString:[NSString stringWithFormat:@"size = %lu",self.size]];
[strM appendString:@" ["];
LinkNode *node = _first;
for (int i = 0; i < self.size; i++) {
if (i != 0) {
[strM appendString:@", "];
}
[strM appendString:[NSString stringWithFormat:@"%@",node.element]];
node = node.next;
}
[strM appendFormat:@"]"];
return strM.copy;
}
@end
测试验证
- (void)linkedListText {
LinkedList *list = [[LinkedList alloc] init];
[list add:@20];
[list add:0 element:NULL];
[list add:@30];
[list add:[list size] element:@40];
[list remove:1];
NSLog(@"%@",list.description);
[list clear];
NSLog(@"%@",list.description);
}
运行结果
三 重要方法解释说明
3.1 添加元素
- (void)add:(id)element;
3.2 删除元素
- (id)remove:(NSUInteger)index;
四 复杂度分析
4.1 动态数组,链表复杂度分析
4.2 动态数组add(E element)复杂度分析
- 最好:O(1)
- 最坏:O(n)
- 平均:O(1)
- 均摊:O(1)
- 什么情况下适合使用均摊复杂度
经过连续的多次复杂度比较低的情况后,出现个别复杂度比较高的情况
本文参考 MJ老师的 恋上数据结构与算法
本人技术水平有限,如有错误欢迎指正。
书写整理不易,您的打赏点赞是对我最大的支持和鼓励,欢迎点赞打赏。