博客
关于我
2.3.Stack Queue
阅读量:798 次
发布时间:2023-04-16

本文共 2566 字,大约阅读时间需要 8 分钟。

Stack 实现

Stack(栈)是一种先进后出(LIFO)的数据结构,常用于管理程序运行时的方法调用顺序。在 .NET 中,Stack 类位于 System.dll 文件中,实现的逻辑位于 mscorlib.dll 的第 330 行。由于我们只关注泛型栈,因此需要调试 System.dll 来分析其内部逻辑。

在调试符号中选择添加 System.dll 即可轻松进入调试模式,这对 VS 的用户来说无疑是大大的便利。通过这种方式,我们可以直接查看栈的内部实现,深入了解其工作原理,从而更好地优化代码开发流程。

Stack 内部

Stack 的内部实现主要依赖动态数组和一些控制变量。以下是实现细节:

1. `_size`:表示当前栈的大小,用于控制数组中指针的位置。

2. `_array`:存储实际数据的动态数组,类型由泛型 T 决定。

3. `_num`:原先用于扩容时的计算字段,现已被 `_size` 取代。

4. `_defaultCapacity`:默认扩容时的容量大小,通常为 4。

5. `_emptyArray`:一个静态空数组,用于初始化栈。

6. `_version`:用于检测数组结构发生变化的版本号。

Stack 构造函数

Stack 提供多个构造函数以满足不同使用场景:

1. `public Stack()`:默认构造函数,初始化时使用空数组 `_emptyArray`。

2. `public Stack(int capacity)`:指定初始容量,直接创建大小为 capacity 的数组。

3. `public Stack(IEnumerable

collection)`:通过集合初始化栈,适用于从集合中逐一添加元素的场景。

Push 操作(O(1) 时间复杂度)

Push 操作将一个项添加到栈顶部。实现细节如下:

1. 检查当前栈是否已满,如果已满则扩容。

2. 扩容时创建新数组,大小为当前数组大小的两倍(或默认容量 4),并将现有数据复制到新数组中。

3. 将新项添加到栈顶,更新 `_size`。

4. 更新 `_version`,用于区分不同版本的栈实例。

Pop 操作(O(1) 时间复杂度)

Pop 操作从栈顶部移除一个项。实现细节如下:

1. 检查栈是否为空,若为空抛出异常。

2. 更新 `_version`。

3. 从 `_size` 递减的位置取出项,并将该位置设置为默认值(即数组中对应位置的 T 类型的默认值)。

4. 返回被移除的项。

Peek 操作(O(1) 时间复杂度)

Peek 操作允许开发者查看栈顶部的项而不移除它。实现细节如下:

1. 检查栈是否为空,若为空抛出异常。

2. 直接访问 `_array[_size - 1]`,返回栈顶部的项。

Contains 操作(O(n) 时间复杂度)

Contains 操作用于检查栈中是否存在指定的项。实现细节如下:

1. 遍历从 `_head` 到 `_tail` 的所有项(从栈底部到栈顶部)。

2. 使用 `EqualityComparer.Default` 比较项是否存在。

3. 如果找到匹配项返回 `true`,否则返回 `false`。

Queue 实现

Queue(队列)是一种先进先出(FIFO)的数据结构,在 .NET 中由 Queue 类实现,内部实现位于 mscorlib.dll 的第 471 行。与 Stack 不同,Queue 使用两个指针(_head 和 _tail)来管理数据的插入和移除操作。

Queue 的内部实现主要依赖以下字段:

1. `_array`:存储数据的动态数组。

2. `_head`:指针,指向队列的当前头部项的位置。

3. `_tail`:指针,指向队列的当前尾部项的位置。

4. `_size`:表示队列中当前有多少项。

5. `_DefaultCapacity`:默认扩容时的容量大小,通常为 4。

6. `_emptyArray`:静态空数组,用于初始化队列。

Queue 构造函数

Queue 提供多个构造函数:

1. `public Queue()`:默认构造函数,初始化时使用空数组 `_emptyArray`。

2. `public Queue(int capacity)`:指定初始容量,创建大小为 capacity 的数组。

3. `public Queue(IEnumerable

collection)`:通过集合初始化队列,逐一添加集合中的项。

Enqueue 操作(O(1) 时间复杂度)

Enqueue 操作将一个项添加到队列末尾。实现细节如下:

1. 检查是否有空间,如果没有空间调用 `SetCapacity` 方法扩容。

2. 更新 `_tail` 指针到下一个位置。

3. 更新 `_size`。

4. 更新 `_version`。

Dequeue 操作(O(1) 时间复杂度)

Dequeue 操作从队列头部移除一个项。实现细节如下:

1. 检查是否为空,若为空抛出异常。

2. 将 `_head` 指针移动到下一个位置,并将该位置的项设置为 null。

3. 更新 `_size` 和 `_version`。

4. 返回被移除的项。

Peek 操作(O(1) 时间复杂度)

Peek 操作允许开发者查看队列头部的项而不移除它。实现细节如下:

1. 检查是否为空,若为空抛出异常。

2. 返回 `_array[_size]` 中的项。

Contains 操作(O(n) 时间复杂度)

Contains 操作用于检查队列中是否存在指定的项。实现细节如下:

1. 从 `_head` 到 `_tail` 遍历所有项。

2. 使用 `EqualityComparer.Default` 比较项是否存在。

3. 返回 `true` 或 `false`。

Enumerator

Queue 提供一个枚举器,允许开发者遍历队列中的所有项。默认枚举器通过循环 `_array` 并从 `_head` 到 `_tail` 检查每个位置是否不为空来获取项。

通过调用 `GetEnumerator()` 方法可以获取枚举器实例。

转载地址:http://lcgfk.baihongyu.com/

你可能感兴趣的文章
MQ 重复消费如何解决?
查看>>
mqtt broker服务端
查看>>
MQTT 保留消息
查看>>
MQTT 持久会话与 Clean Session 详解
查看>>
MQTT工作笔记0007---剩余长度
查看>>
MQTT工作笔记0009---订阅主题和订阅确认
查看>>
Mqtt搭建代理服务器进行通信-浅析
查看>>
MS Edge浏览器“STATUS_INVALID_IMAGE_HASH“兼容性问题
查看>>
ms sql server 2008 sp2更新异常
查看>>
MS UC 2013-0-Prepare Tool
查看>>
MSBuild 教程(2)
查看>>
msbuild发布web应用程序
查看>>
MSB与LSB
查看>>
MSCRM调用外部JS文件
查看>>
MSCRM调用外部JS文件
查看>>
MSEdgeDriver (Chromium) 不适用于版本 >= 79.0.313 (Canary)
查看>>
MsEdgeTTS开源项目使用教程
查看>>
msf
查看>>
MSSQL数据库查询优化(一)
查看>>
MSSQL数据库迁移到Oracle(二)
查看>>