C#中Stack<T>类的使用及部分成员函数的源码分析

Stack<T>类

Stack<T> 作为数组来实现。 Stack<T> 的容量是 Stack<T>
可以包含的元素数。 当向 Stack<T> 中添加元素时,将通过重新分配内部数组来根据需要自动增大容量。 可通过调用 TrimExcess 来减少容量。 如果 Count 小于堆栈的容量,则 Push 的运算复杂度是 O(1)。 如果需要增加容量以容纳新元素,则 Push 的运算复杂度成为 O(n),其中 n 为 Count。 Pop 的运算复杂度为 O(1)。 Stack<T>
接受 null 作为引用类型的有效值并且允许有重复的元素。

命名控件:System.Collections.Generic

程序集:System(在System.dll中)

语法:public class Stack<T>:IEnumerable<T>, ICollection, IEnumerable

List<T>实现了IList<T>、 ICollection<T>、IEnumerable<T>、IList、ICollection、IEnumerable接口

因此可以看出与List1T>相比:

Stack<T>没有继承ICollection<T>接口,因为这个接口定义的Add()和Remove()方法不能用于栈;

Stack<T>没有继承IList<T>接口,所以不能使用索引器访问栈。

所以队列只允许在栈的顶部添加元素,删除元素。

常用的Stack<T>类的成员:

Count : 返回栈中元素的个数。

Push(): 在栈顶添加一个元素。

Pop() : 从栈顶删除一个元素。如果栈是空,就会抛出异常InvalidOperationException异常。

Peek(): 返回栈顶的元素,但不删除它。

Contains(): 确定某个元素是否在栈中,如果是,返回true。

/******************************************************************************************************************************/

常用Stack1T>类的成员函数的源码如下:

public bool Contains(T item)

{

int index = this._size;

EqualityComparer<T> comparer = EqualityComparer<T>.Default;

while (index-- > 0)

{

if (item == null)

{

if (this._array[index] == null)

{

return true;

}

}

else if ((this._array[index] != null) && comparer.Equals(this._array[index], item))

{

return true;

}

}

return false;

}

public T Peek()

{

if (this._size == 0)

{

ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EmptyStack);

}

return this._array[this._size - 1];

}

public T Pop()

{

if (this._size == 0)

{

ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EmptyStack);

}

this._version++;

T local = this._array[--this._size];

this._array[this._size] = default(T);

return local;

}

public void Push(T item)

{

if (this._size == this._array.Length)

{

T[] destinationArray = new T[(this._array.Length == 0) ? 4 : (2 * this._array.Length)];

Array.Copy(this._array, 0, destinationArray, 0, this._size);

this._array = destinationArray;

}

this._array[this._size++] = item;

this._version++;

}

/*****************************************************************************************************************************************/

下面的代码示例演示了 Stack 泛型类的几种方法。 此代码示例创建具有默认容量的字符串堆栈,并使用 Push 方法将五个字符串压入堆栈。 枚举堆栈的元素,这不会更改该堆栈的状态。 使用 Pop 方法将第一个字符串弹出堆栈。 使用 Peek 方法查看此堆栈中的下一个项,然后使用 Pop 方法将其弹出。

使用 ToArray 方法创建数组并将堆栈元素复制到其中,然后将数组传递给具有 IEnumerable 的 Stack 构造函数,以元素的反向顺序创建堆栈副本。 将显示副本的元素。

创建大小为堆栈大小两倍的数组,并使用 CopyTo 方法从数组的中间开始复制数组元素。 再次使用 Stack 构造函数以元素的反向顺序创建堆栈副本;这样,三个空元素就位于堆栈的底部。

使用 Contains 方法显示字符串“four”在第一个堆栈副本中,然后使用 Clear 方法清除该副本,并由 Count 属性显示此堆栈为空。

using System;

using System.Collections.Generic;

class Example

{

public static void Main()

{

Stack<string> numbers = new Stack<string>();

numbers.Push("one");

numbers.Push("two");

numbers.Push("three");

numbers.Push("four");

numbers.Push("five");

// A stack can be enumerated without disturbing its contents.

foreach( string number in numbers )

{

Console.WriteLine(number);

}

Console.WriteLine("\nPopping ‘{0}‘", numbers.Pop());

Console.WriteLine("Peek at next item to destack: {0}", numbers.Peek());

Console.WriteLine("Popping ‘{0}‘", numbers.Pop());

// Create a copy of the stack, using the ToArray method and the

// constructor that accepts an IEnumerable.

Stack stack2 = new Stack(numbers.ToArray());

Console.WriteLine("\nContents of the first copy:");

foreach( string number in stack2 )

{

Console.WriteLine(number);

}

// Create an array twice the size of the stack and copy the

// elements of the stack, starting at the middle of the

// array.

string[] array2 = new string[numbers.Count * 2];

numbers.CopyTo(array2, numbers.Count);

// Create a second stack, using the constructor that accepts an

// IEnumerable(Of T).

Stack stack3 = new Stack(array2);

Console.WriteLine("\nContents of the second copy, with duplicates and nulls:");

foreach( string number in stack3 )

{

Console.WriteLine(number);

}

Console.WriteLine("\nstack2.Contains(\"four\") = {0}",stack2.Contains("four"));

Console.WriteLine("\nstack2.Clear()");

stack2.Clear();

Console.WriteLine("\nstack2.Count = {0}", stack2.Count);

}

}

/* This code example produces the following output:

five

four

three

two

one

Popping ‘five‘

Peek at next item to destack: four

Popping ‘four‘

Contents of the first copy:

one

two

three

Contents of the second copy, with duplicates and nulls:

one

two

three

stack2.Contains("four") = False

stack2.Clear()

stack2.Count = 0

*/

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-01 02:35:55

C#中Stack<T>类的使用及部分成员函数的源码分析的相关文章

CloudStack核心类ApiServlet、ApiServer、ApiDispatcher、GenericDaoBase源码分析

ApiServlet 首先从整体上看下ApiServlet,Outline视图如下, 一.注意@Inject依赖的是javax.inject.jar,它和spring的@Autowired的区别在于使用它时变量不用生成相应的set方法. 二.CloudStack所有的请求都会被ApiSerlet拦截处理,进入到doGet()或者doPost()方法,然后统一交由processRequest()处理. 三.processRequestInContext()方法: 1.更多的是日志记录和异常信息处理

String源码分析之Java中的String为什么是不可变的以及replace方法源码分析

什么是不可变对象? 众所周知, 在Java中, String类是不可变的.那么到底什么是不可变的对象呢? 可以这样认为:如果一个对象,在它创建完成之后,不能再改变它的状态,那么这个对象就是不可变的.不能改变状态的意思是,不能改变对象内的成员变量,包括基本数据类型的值不能改变,引用类型的变量不能指向其他的对象,引用类型指向的对象的状态也不能改变. 区分对象和对象的引用 对于Java初学者, 对于String是不可变对象总是存有疑惑.看下面代码: String s = "ABCabc";

C#中Queue&lt;T&gt;类的使用以及部分方法的源码分析

Queue<T>类 表示对象的先进先出集合. 队列在按接收顺序存储消息方面非常有用,以便于进行顺序处理. 存储在 Queue,<T> 中的对象在一端插入,从另一端移除. Queue<T> 的容量是 Queue<T> 可以包含的元素数. 当向 Queue<T> 中添加元素时,将通过重新分配内部数组来根据需要自动增大容量. 可通过调用 TrimExcess 来减少容量. Queue<T> 接受 null 作为引用类型的有效值并且允许有重复

lodash源码分析之compact中的遍历

小时候, 乡愁是一枚小小的邮票, 我在这头, 母亲在那头. 长大后,乡愁是一张窄窄的船票, 我在这头, 新娘在那头. 后来啊, 乡愁是一方矮矮的坟墓, 我在外头, 母亲在里头. 而现在, 乡愁是一湾浅浅的海峡, 我在这头, 大陆在那头. --余光中<乡愁> 本文为读 lodash 源码的第三篇,后续文章会更新到这个仓库中,欢迎 star:pocket-lodash gitbook也会同步仓库的更新,gitbook地址:pocket-lodash 作用与用法 compact 函数用来去除数组中的

Cocos2dx-3.x 中CCCamera相机类详解及源码分析

Cocos2d-x 3.3版本中加入了相机这个类,该类在3D游戏中是必不可少的,在3D立体游戏中,往往需要视野角度的变化,通过相机的变换才能观察和体验整个游戏世界. CCCamera类基本使用 在游戏中一般有两种类型的相机:一种是透视相机,它在3D游戏中十分常见:另一种是正交相机,它没有透视相机的近大远小的效果而是相机内任何位置的物体大小比例都是一样的. 上图是透视相机的原理图,一般来说,我们通过以下代码创建: _camera = Camera::createPerspective(60, (G

关于java中ReentrantLock类的源码分析以及总结与例子

一,官方描述 关于ReentrantLock的官方描述,英文的就不贴出来了,这里我只贴出我自己翻译的描述: reentrant是一个跟synchronized具有相同行为和语义的持有锁来访问方法和语句的互斥锁,但是reentrant还拥有被扩展的能力. ReentrantLock会被线程拥有并且持续锁定,不会解锁.线程调用lock()方法返回后,则成功持有锁,否则这个锁正在被另一个线程所持有,只能等待另一个线程释放锁,如果当前线程拥有了锁,则调用lock()方法会立即返回,这个状态可以通过isH

JDK中String类的源码分析(二)

1.startsWith(String prefix, int toffset)方法 包括startsWith(*),endsWith(*)方法,都是调用上述一个方法 1 public boolean startsWith(String prefix, int toffset) { 2 char ta[] = value; 3 int to = toffset; 4 char pa[] = prefix.value; 5 int po = 0; 6 int pc = prefix.value.l

Vector和Stack源码分析/List集合的总结

序言 这篇文章算是在这list接口下的集合的最后一篇了,前面ArrayList.LinkedList都已经讲解完了,剩下就Vector和Vector的子类Stack啦.继续努力.一步一个脚印, --WH 扩展 学习vector,需要一些多线程的知识,这里比较杂,主要讲解一下等会会用到的 1.锁机制:对象锁.方法锁.类锁 对象锁就是方法锁:就是在一个类中的方法上加上synchronized关键字,这就是给这个方法加锁了. 类锁:锁的是整个类,当有多个线程来声明这个类的对象的时候将会被阻塞,直到拥有

Java集合之Stack 源码分析

1.简介 栈是数据结构中一种很重要的数据结构类型,因为栈的后进先出功能是实际的开发中有很多的应用场景.Java API中提供了栈(Stacck)的实现,简单使用如下所示 package com.test.collections; import java.util.Stack; public class StackTest { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated m