五、堆栈、和队列

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
        }
      
    }
}
View Code

 下面是模拟进行撤销操作的代码:

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
}
View Code

 

 

通过自己封装栈的操作类,可以学习到如下:

1.如何给数组自动扩容

2.如何编写一个能支持foreach的类

posted @ 2016-04-15 16:44  HUCEMAIL  阅读(84)  评论(0)    收藏  举报