数据结构

数据结构在计算机科学中是必不可少的重要概念,它们用于组织和存储数据。选择合适的数据结构能够显著提高程序的性能和效率。以下是几种经典数据结构的详细介绍,包括分析其优缺点以及在 iOS 中的对应类和结构。

1. 数组 (Array)

思想

数组是一种线性数据结构,它由一组元素组成,这些元素通过连续的内存地址进行存储。数组元素可以通过索引进行访问。

优缺点

  • 优点:
    • 访问速度快,时间复杂度为 O(1)。
    • 有序存储,支持随机访问。
  • 缺点:
    • 插入和删除操作效率低,因为需要移动大量元素,时间复杂度为 O(n)。
    • 固定大小,在创建数组时需要先定义长度。

iOS 中的对应类和结构

  • Objective-C: NSArray (不可变数组),NSMutableArray (可变数组)
  • Swift: Array

使用示例

Objective-C:

NSArray *immutableArray = @[@1, @2, @3];
NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:immutableArray];
[mutableArray addObject:@4];
NSLog(@"%@", mutableArray); // 输出: (1, 2, 3, 4)

Swift:

let immutableArray = [1, 2, 3]
var mutableArray = immutableArray
mutableArray.append(4)
print(mutableArray) // 输出: [1, 2, 3, 4]

2. 链表 (Linked List)

思想

链表是一种线性数据结构,每个元素包含数据和指向下一个元素的指针。链表的末尾元素指针为空。

优缺点

  • 优点:
    • 动态大小,链表长度可以随时改变。
    • 插入和删除操作效率高,因为只需改变指针,时间复杂度为 O(1)。
  • 缺点:
    • 访问速度慢,需要从头开始遍历,时间复杂度为 O(n)。
    • 额外的存储空间,用于存储指针。

iOS 中的对应类和结构

链表在 iOS 的标准库中没有直接对应的类或结构,但可以自定义实现。

自定义实现示例

Objective-C:

@interface ListNode : NSObject
@property (nonatomic) NSInteger val;
@property (nonatomic, strong, nullable) ListNode *next;
- (instancetype)initWithValue:(NSInteger)value;
@end

@implementation ListNode
- (instancetype)initWithValue:(NSInteger)value {
    self = [super init];
    if (self) {
        self.val = value;
        self.next = nil;
    }
    return self;
}
@end

@interface LinkedList : NSObject
@property (nonatomic, strong, nullable) ListNode *head;
- (void)addNodeWithValue:(NSInteger)value;
@end

@implementation LinkedList
- (void)addNodeWithValue:(NSInteger)value {
    ListNode *newNode = [[ListNode alloc] initWithValue:value];
    if (!self.head) {
        self.head = newNode;
    } else {
        ListNode *current = self.head;
        while (current.next) {
            current = current.next;
        }
        current.next = newNode;
    }
}
@end

Swift:

class ListNode {
    var val: Int
    var next: ListNode?
    
    init(_ val: Int) {
        self.val = val
        self.next = nil
    }
}

class LinkedList {
    var head: ListNode?
    
    func addNode(_ val: Int) {
        let newNode = ListNode(val)
        if head == nil {
            head = newNode
        } else {
            var current = head
            while current?.next != nil {
                current = current?.next
            }
            current?.next = newNode
        }
    }
}

3. 栈 (Stack)

思想

栈是一种线性数据结构,遵循后进先出(LIFO)的原则。栈只允许在一端进行插入和删除操作。

优缺点

  • 优点:
    • 操作简单,插入和删除操作时间复杂度为 O(1)。
    • 实现递归和任务调度非常方便。
  • 缺点:
    • 访问任意元素时间复杂度高,为 O(n) 。
    • 空间利用不如数组高。

iOS 中的对应类和结构

  • Objective-C: 一般会使用 NSMutableArray 作为栈来使用。
  • Swift: 可以使用 Array 来实现栈。

使用示例

Objective-C:

NSMutableArray *stack = [NSMutableArray array];
[stack addObject:@1]; // push
[stack addObject:@2];
NSNumber *top = [stack lastObject]; // peek
[stack removeLastObject]; // pop
NSLog(@"%@", top); // 输出: 2

Swift:

var stack = [Int]()
stack.append(1) // push
stack.append(2)
let top = stack.last // peek
let popped = stack.popLast() // pop
print(top ?? -1) // 输出: 2

4. 队列 (Queue)

思想

队列是一种线性数据结构,遵循先进先出(FIFO)的原则。队列允许在一端进行插入(入队),在另一端进行删除(出队)。

优缺点

  • 优点:
    • 操作简单,入队和出队操作时间复杂度为 O(1)。
    • 在任务管理、线程池、广度优先搜索等方面非常有用。
  • 缺点:
    • 访问任意元素时间复杂度高,为 O(n)。
    • 空间利用不如数组高。

iOS 中的对应类和结构

  • Objective-C: 一般会使用 NSMutableArray 作为队列来使用。
  • Swift: 可以使用 Array 来实现队列。

使用示例

Objective-C:

NSMutableArray *queue = [NSMutableArray array];
[queue addObject:@1]; // enqueue
[queue addObject:@2];
NSNumber *front = [queue firstObject]; // peek
[queue removeObjectAtIndex:0]; // dequeue
NSLog(@"%@", front); // 输出: 1

Swift:

var queue = [Int]()
queue.append(1) // enqueue
queue.append(2)
let front = queue.first // peek
let dequeued = queue.removeFirst() // dequeue
print(front ?? -1) // 输出: 1

5. 树 (Tree)

思想

树是一种层次数据结构,由节点和边组成。常见的树结构有二叉树、平衡树、红黑树、B树等。

优缺点

  • 优点:
    • 多种变体,适用于不同场景(如二叉搜索树用于快速查找)。
    • 插入、删除和查找操作时间复杂度平均为 O(log n)。
  • 缺点:
    • 实现比较复杂。
    • 需要额外的内存空间来存储节点和指针。

iOS 中的对应类和结构

树结构一般需要自定义实现 iOS 标准库中没有直接对应的类或结构。

自定义实现示例

Objective-C(以二叉搜索树为例):

@interface TreeNode : NSObject
@property (nonatomic) NSInteger val;
@property (nonatomic, strong, nullable) TreeNode *left;
@property (nonatomic, strong, nullable) TreeNode *right;
- (instancetype)initWithValue:(NSInteger)value;
@end

@implementation TreeNode
- (instancetype)initWithValue:(NSInteger)value {
    self = [super init];
    if (self) {
        self.val = value;
        self.left = nil;
        self.right = nil;
    }
    return self;
}
@end

@interface BinarySearchTree : NSObject
@property (nonatomic, strong, nullable) TreeNode *root;
- (void)insertValue:(NSInteger)value;
@end

@implementation BinarySearchTree

- (void)insertValue:(NSInteger)value {
    self.root = [self insertInto:self.root value:value];
}

- (TreeNode *)insertInto:(TreeNode *)node value:(NSInteger)value {
    if (!node) {
        return [[TreeNode alloc] initWithValue:value];
    }
    if (value < node.val) {
        node.left = [self insertInto:node.left value:value];
    } else if (value > node.val) {
        node.right = [self insertInto:node.right value:value];
    }
    return node;
}
@end

Swift(以二叉搜索树为例):

class TreeNode {
    var val: Int
    var left: TreeNode?
    var right: TreeNode?
    
    init(_ val: Int) {
        self.val = val
        self.left = nil
        self.right = nil
    }
}

class BinarySearchTree {
    var root: TreeNode?
    
    func insert(_ val: Int) {
        root = insertInto(root, val)
    }
    
    private func insertInto(_ node: TreeNode?, _ val: Int) -> TreeNode? {
        guard let node = node else {
            return TreeNode(val)
        }
        if val < node.val {
            node.left = insertInto(node.left, val)
        } else if val > node.val {
            node.right = insertInto(node.right, val)
        }
        return node
    }
}

6. 哈希表 (Hash Table)

思想

哈希表是一种基于散列函数的数据结构,用于实现映射关系(键值对)。通过散列函数,将键映射到数组中的一个位置。

优缺点

  • 优点:
    • 查找、插入和删除操作时间复杂度平均为 O(1)。
    • 非常高效,适用于大量数据的快速访问。
  • 缺点:
    • 处理哈希碰撞的开销较大。
    • 需要有效的哈希函数来减少冲突。
    • 使用不当可能导致性能下降。

iOS 中的对应类和结构

  • Objective-C: NSDictionary(不可变字典),NSMutableDictionary(可变字典)
  • Swift: Dictionary

使用示例

Objective-C:

NSMutableDictionary *hashTable = [NSMutableDictionary dictionary];
[hashTable setObject:@1 forKey:@"one"];
[hashTable setObject:@2 forKey:@"two"];
NSNumber *value = [hashTable objectForKey:@"one"];
NSLog(@"%@", value); // 输出: 1

Swift:

var hashTable = [String: Int]()
hashTable["one"] = 1
hashTable["two"] = 2
let value = hashTable["one"]
print(value ?? -1) // 输出: 1

7. 图 (Graph)

思想

图是一种由顶点和边组成的数据结构。图可以是无向图或有向图,存在自环和多重边。

优缺点

  • 优点:
    • 适用于表示多对多关系的数据结构,如社交网络、地图路径、网络拓扑等。
    • 提供多种算法解决图中的问题(如最短路径、最小生成树等)。
  • 缺点:
    • 实现复杂,存储占用空间较多。
    • 操作复杂度高,尤其在稠密图中。

iOS 中的对应类和结构

图结构没有标准库的类或结构,需要自定义实现。

自定义实现示例

Objective-C(邻接表表示):

@interface GraphNode : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSMutableArray<GraphNode *> *adjacentNodes;
- (instancetype)initWithName:(NSString *)name;
@end

@implementation GraphNode
- (instancetype)initWithName:(NSString *)name {
    self = [super init];
    if (self) {
        self.name = name;
        self.adjacentNodes = [NSMutableArray array];
    }
    return self;
}
@end

@interface Graph : NSObject
@property (nonatomic, strong) NSMutableDictionary<NSString *, GraphNode *> *nodes;
- (void)addEdgeFromNode:(NSString *)fromNode toNode:(NSString *)toNode;
@end

@implementation Graph
- (instancetype)init {
    self = [super init];
    if (self) {
        self.nodes = [NSMutableDictionary dictionary];
    }
    return self;
}

- (void)addEdgeFromNode:(NSString *)fromNode toNode:(NSString *)toNode {
    GraphNode *sourceNode = self.nodes[fromNode];
    if (!sourceNode) {
        sourceNode = [[GraphNode alloc] initWithName:fromNode];
        self.nodes[fromNode] = sourceNode;
    }
    GraphNode *destinationNode = self.nodes[toNode];
    if (!destinationNode) {
        destinationNode = [[GraphNode alloc] initWithName:toNode];
        self.nodes[toNode] = destinationNode;
    }
    [sourceNode.adjacentNodes addObject:destinationNode];
}
@end

Swift(邻接表表示):

class GraphNode {
    var name: String
    var adjacentNodes: [GraphNode]
    
    init(_ name: String) {
        self.name = name
        self.adjacentNodes = []
    }
}

class Graph {
    var nodes: [String: GraphNode]
    
    init() {
        nodes = [:]
    }
    
    func addEdge(from fromNode: String, to toNode: String) {
        let sourceNode = nodes[fromNode, default: GraphNode(fromNode)]
        nodes[fromNode] = sourceNode
        
        let destinationNode = nodes[toNode, default: GraphNode(toNode)]
        nodes[toNode] = destinationNode
        
        sourceNode.adjacentNodes.append(destinationNode)
    }
}

总结

  1. 数组:快速访问,但插入和删除效率低。iOS 中使用 NSArrayNSMutableArray
  2. 链表:动态大小,插入和删除效率高,但访问速度慢。自定义实现。
  3. :后进先出,适合递归和任务调度。使用 NSMutableArray 或 Swift 的 Array
  4. 队列:先进先出,任务管理常用。使用 NSMutableArray 或 Swift 的 Array
  5. :适用于快速查找、多种变体,适应不同场景。自定义实现。
  6. 哈希表:快速查找,处理哈希碰撞。iOS 中使用 NSDictionaryNSMutableDictionary
  7. :表示多对多关系,高效解决图问题。自定义实现。

这些数据结构的选择和使用因场景和需求而异,每种数据结构有其独特的优缺点和适用场景。iOS 开发者可以根据实际需要选择合适的数据结构以优化性能和效率。

posted @   Mr.陳  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!
历史上的今天:
2015-07-17 iOS开发基础10-UIButton内边距和图片拉伸模式
2015-07-17 iOS开发基础9-提示框(UIAlertController)
点击右上角即可分享
微信分享提示