Stack 在System.dll中,Stack在mscorlib 330行
但是我只考虑泛型所以需要调试System.dll
在调试符号中选择添加System.dll 符号,即可进入调试,太方便了,我爱vs
就这一点,我爱你ide
看来以后选ide的标准要换了,唯一标准是能否方便的调试代码
Stack内部
同样的动态数组
int _size; //控制数组中指针,他是一个索引啊,指向栈顶
T[] _array; //以当前长度的2倍增长
int _num;
int _defaultCapacity 4;
static T[] _emptyArray=new T[0]; //这就是类型变量的用法
int _version; //每次T[]中的数据改变了才递增
ctor
1. public Stack<T>(){}// _array=_emptyArray;
2. public Stack<T>(int capacity){} // _array=new T[capacity];
3. public Stack<T>(IEnumerable<T> collections){} //1.get count,then array.copyto 2.foreach
Push(T item) O(1)
public void Push(T item){
if(_size == array.Length){ //扩容操作
T[] newArray=new T[(_array.Length==0)?_defaultCapacity:2*_array.Length];
Array.Copy(_array,0,newArray,0,_size);// 所以动态数组扩容也就是一个Array.Copy()而已,简单
_array = newArray;
}
_array[_size++]=item; //简单的设置值
_version++;//这里也是一个聪明的举动,只需要4个字节,就保证了foreach的时候可以判断错误,用小代价完成大问题
}
Pop() O(1)
public T Pop(){
if (_size == 0){
throw new empty stack exception;
}
version ++;
T item = _array[--size]; //倒过来从后面访问
_array[_size] = default(T);
return item;
}
Peek() O(1)
public T Peek() {
if(_size==0){
throw new empty stack exception;
}
return _array[_size-1];
//不需要对size处理,不需要对version处理
}
Contains(T item) O(n)
一般对比都需要EqualityComparer.Default<T>
然后就是区分null
不是null就用Equals方法
就是一个遍历
Queue 内部 471行
为什么一直在求%,是怕超出范围
使用数组和两个指针,头尾各一个,然后都向后移动
T[] _array;
int _head;
int _tail;
int _size;
const int _DefaultCapacity = 4;
static T[] _emptyArray = new T[0];
ctor
public Queue(){} // _empty=_emptyArray;
public Queue(int capacity){} // _array=new T[capacity];
public Queue(IEnumerable<T> collection){} //_array=new T[_DefaultCapacity], foreach {Enqueue(item);}
Enqueue(T item) O(1)
1. 判断空Queue 抛异常
2. 扩容 SetCapacity(int newCapacity)
3. _tail=(_tail+1)%_array.Length;
简单理解就是tail++
4. _size++;
5. version++;
Dequeue() O(1)
1. 判断空Queue 抛异常
2. remove=_array[head];
3. _array[head++]=null;
4. size--;
5. version++;
Peek() O(1)
1. 判断空Queue 抛异常
2. return _array[size];
contains O(n)
head->tail 之间遍历
Enumerator
new Enumerator(this);