五、堆栈、和队列
1、堆栈(Stack)
堆栈是顺序存储结构,内存容量不固定,可以动态增加。它只能在表的某一端进行增加和移除操作,是一种典型的 LIFO(后进先出) 集合。
一般用在undo(撤销)、redo(重做)的应用场景中。
Stack提供了如下方法和属性:
Count:获取栈中包含的元素数
Peek():返回位于顶部的对象,不将其移除
pop():移除并返回位于顶部的对象
push():将对象插入到顶部
Contains():确定某元素是否在其中
ConpyTo():从指定数组索引处开始从集合中复制到一维数组Array
ToArray():将集合复制到新的数组中
Clear():移除所有对象
使用方法:
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Text.RegularExpressions; namespace ConsoleApplication9 { class Program { static void Main(string[] args) { Stack<String> stack = new Stack<String>(); Console.WriteLine(stack.Count); //output 0 stack.Push("Hello"); stack.Push("World"); stack.Push("Remove"); Console.WriteLine(stack.Count);//output 3 Console.WriteLine(stack.Peek());//output Remove Console.WriteLine(stack.Count);//output 3 Console.WriteLine(stack.Pop());//output Remove Console.WriteLine(stack.Count);//output 2 Console.WriteLine(stack.Peek());//output World Console.WriteLine(stack.Contains("World"));//output True //foreach foreach (String item in stack) { Console.WriteLine(item);//output world hello } //copyto string[] array=new string[3]; stack.CopyTo(array, 1); foreach (String item in array) { Console.WriteLine(item);//out null string world hello } //ToArray string[] array2 = stack.ToArray(); foreach (String item in array2) { Console.WriteLine(item);//out world hello } //clear stack.Clear(); Console.WriteLine(stack.Count);//out 0 } } }
下面是模拟进行撤销操作的代码:
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Text.RegularExpressions; namespace ConsoleApplication9 { class Program { static void Main(string[] args) { Stack<String> stack = new Stack<String>(); string str = string.Empty; while (true) { Console.WriteLine("Plase enter a string.(input 'undo' withdrawal,'quit' exit.):"); str = Console.ReadLine(); if ("undo".Equals(str)) stack.Pop(); else if ("exit".Equals(str)) break; else { stack.Push(str); } foreach (String item in stack) { Console.Write(item); } Console.WriteLine(); } Console.WriteLine("Program quit,thank you."); } } }
知道如何使用Stack集合外,来模仿一个自己的Stack,结构如:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication9 { public class MyStack<T> { public int Count { get { return 0; } } public void Push(T item) { } public T Pop() { return default(T); } public T Peek() { return default(T); } public Boolean Contains(T item) { return false; } public void CopyTo(T[] array, int arrayIndex) { } public T[] ToArray() { return default(T[]); } public void Clear() { } } }
具体实现代码如下,为了支持foreach,需要继承IEnumerable<T>并且实现GetEnumertor方法
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication9 { /// <summary> /// 封装栈, /// (支持foreach必须继承IEnumerable<T>,IEnumerable<T>又继承与IEnumerable,所以需要实现返回值不同的GetEnumerator方法) /// </summary> /// <typeparam name="T"></typeparam> public class MyStack<T>:IEnumerable<T> { private T[] _array = null; private int _size; private const int _defaultCapacity=4;//默认容量 public MyStack() { _array = new T[0]; _size = 0; } public int Count { get { return _size; } } public void Push(T item) { if (_size == _array.Length) { T[] newarray = new T[(_size == 0) ? _defaultCapacity : 2 * _array.Length];//如果当前容量已满,则成倍数增长 Array.Copy(_array, 0, newarray, 0, _size); _array = newarray; } _array[_size++] = item; } public T Pop() { if (_size == 0) throw new InvalidOperationException("无效的操作:空栈."); T item = _array[--_size]; //当前游标-1 _array[_size] = default(T); return item; } public T Peek() { if (_size == 0) throw new InvalidOperationException("无效的操作:空栈."); return _array[_size-1];//Peek不移除顶部元素 } public Boolean Contains(T item) { int count = _size; EqualityComparer<T> c = EqualityComparer<T>.Default; while (count-->0) { if (item == null && _array[count] == null) return true; else if (_array[count] != null && c.Equals(_array[count], item)) return true; } return false; } public void CopyTo(T[] array, int arrayIndex) { if (array == null) throw new ArgumentNullException("参数array不能为null"); if (arrayIndex < 0 || arrayIndex > array.Length) throw new ArgumentOutOfRangeException("索引小于0"); if (array.Length - arrayIndex < _size) throw new ArgumentException("偏移量长度超越了数组界限,或者计数大于从索引到源集合结尾处的数量."); Array.Copy(_array, 0, array, arrayIndex, _size); Array.Reverse(array, arrayIndex, _size);//翻转 } public T[] ToArray() { T[] objArray = new T[_size]; int i = 0; while (i<_size) { objArray[i] = _array[_size-1-i]; i++; } return objArray; } public void Clear() { Array.Clear(_array, 0, _size); _size = 0; } IEnumerator<T> IEnumerable<T>.GetEnumerator() { return new Enumberator(this); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return new Enumberator(this); } public class Enumberator : IEnumerator<T> { private MyStack<T> _stack; private int _index; private T currentElement; public Enumberator(MyStack<T> statck) { this._stack = statck; this._index = -2; this.currentElement=default(T); } T IEnumerator<T>.Current { get { if (_index == -2) throw new Exception("栈没有开始"); if (_index == -1) throw new Exception("栈没有结束"); return currentElement; } } void IDisposable.Dispose() { _index = -1; } object IEnumerator.Current { get { if (_index == -2) throw new Exception("栈没有开始"); if (_index == -1) throw new Exception("栈没有结束"); return currentElement; } } bool IEnumerator.MoveNext() { bool retval; if (_index==-2)//刚开始遍历 { _index = _stack._size - 1; retval = (_index >= 0); if (retval) currentElement=_stack._array[_index]; return true; } if (_index == -1) return false; retval = (--_index >= 0); if (retval) currentElement = _stack._array[_index]; else currentElement = default(T); return retval; } void IEnumerator.Reset() { _index = -2; currentElement = default(T); } } } //http://www.cnblogs.com/gsk99/archive/2011/05/20/1904552.html }
通过自己封装栈的操作类,可以学习到如下:
1.如何给数组自动扩容
2.如何编写一个能支持foreach的类

浙公网安备 33010602011771号