这阵子在重温数据结构的时候,顺便用ILSpy看了一些.NET类库的实现,发现一些基本的数据结构的实现方法也是挺有意思的,所以这里拿出来跟大家分享一下。这篇文章讨论的是Stack和Queue的泛型实现。
  Stack<T>的实现
  Stack(栈)是一种后进先出的数据结构,其中核心的两个方法分别为Push(入栈)和Pop(出栈)两个操作,那么.NET类库是如何实现这种数据结构呢?为了降低学习成本,这里将根据.NET源码的实现,结合其中的核心设计思想,得出一个简化版本的实现:
using System;
namespace OriginalCode
{
/// <summary>
/// 基于.NET源码的简化版实现
/// </summary>
public class Stack<T>
{
private const int _defaultCapacity = 4;
private T[] _array;
private int _size;
public Stack()
{
//默认初始化数组的数量为空
_array = new T[0];
//初始化数组的数量为0
_size = 0;
}
/// <summary>
/// 入栈
/// </summary>
/// <param name="item">入栈的元素</param>
public void Push(T item)
{
if (_size == _array.Length)
{
//数组存储已经满了,需重新分配数组大小
//分配的数组大小为原来的两倍
T[] array = new T[_array.Length == 0 ? _defaultCapacity : 2 * _array.Length];
//将原来的数组Copy到新数组中
Copy(_array, array);
//_array指向新数组
_array = array;
}
_array[_size] = item;
_size += 1;
}
/// <summary>
/// 出栈
/// </summary>
/// <returns>出栈的元素</returns>
public T Pop()
{
if (_size == 0)
{
throw new Exception("栈为空,当前不能执行出栈操作");
}
_size -= 1;
T result = _array[_size];
_array[_size] = default(T);
return result;
}
/// <summary>
/// 将旧数组赋值到新数组(这个方法是一个模拟实现,实际情况.NET源码底层用C++实现了更高效的复制)
/// </summary>
/// <param name="oldArray">旧数组</param>
/// <param name="newArray">新数组</param>
private void Copy(T[] oldArray, T[] newArray)
{
for (int i = 0; i < oldArray.Length; i++)
{
newArray[i] = oldArray[i];
}
}
}
}