重生之数据结构与算法—-队列&栈

简介

上文说到,数据结构只有两种。其它的数据结构都是它的整花活


  1. 栈只能在表的一端(称为栈顶)进行插入和删除操作,遵循 “后进先出”(Last In First Out,LIFO)的原则。就像生活中的一摞盘子,最后放上去的盘子会最先被拿走

  2. 队列
    它只允许在表的一端进行插入操作(队尾),在另一端进行删除操作(队头),遵循 “先进先出”(First In First Out,FIFO)的原则。类似于生活中排队买票,先排队的人先买到票离开队列。

重生之数据结构与算法----队列&栈

用链表实现stack

    public class MyLinkedStack<T>()     {         public static void Run()         {             var stack = new MyLinkedStack<string>();              stack.Push("aaaa");             stack.Push("bbbb");             stack.Push("cccc");             stack.Push("dddd");              while (stack.Count > 0)             {                 Console.WriteLine(stack.Pop());             }                      }         private LinkedList<T> _linked = new LinkedList<T>();          /// <summary>         /// 入栈         /// O(1)         /// </summary>         /// <param name="item"></param>         public void Push(T item)         {             _linked.AddFirst(item);         }          /// <summary>         /// 出栈         /// O(1)         /// </summary>         /// <returns></returns>         public T Pop()         {             var first = _linked.First;             _linked.RemoveFirst();             return first.Value;         }         /// <summary>         /// 查看栈顶         /// </summary>         /// O(1)         /// <returns></returns>         public T Peek()         {             return _linked.First.Value;         }          public int Count { get { return _linked.Count; } }     } 

用链表实现queue

public class MyLinkedQueue<T> {     public static void Run()     {         var queue = new MyLinkedQueue<string>();           queue.Enqueue("aaa");         queue.Enqueue("bbb");         queue.Enqueue("ccc");         queue.Enqueue("ddd");          while (queue.Count > 0)         {             Console.WriteLine(queue.Dequeue());         }     }      private LinkedList<T> _linked = new LinkedList<T>();      /// <summary>     /// 入列     /// </summary>     /// <param name="item"></param>     public void Enqueue(T item)     {         _linked.AddFirst(item);     }      /// <summary>     /// 出列     /// </summary>     /// <returns></returns>     public T Dequeue()     {         var last= _linked.Last;         _linked.RemoveLast();         return last.Value;     }      /// <summary>     /// 查看队列顶     /// </summary>     /// <returns></returns>     public T Peek()     {         return _linked.First.Value;     }      public int Count { get { return _linked.Count; } } } 

用数组实现stack

    public class MyArrayStack<T>()     {         public static void Run()         {             var stack = new MyLinkedStack<string>();              stack.Push("aaaa");             stack.Push("bbbb");             stack.Push("cccc");             stack.Push("dddd");              while (stack.Count > 0)             {                 Console.WriteLine(stack.Pop());             }          }         private List<T> _list=new List<T>();          /// <summary>         /// 入栈         /// O(1)         /// </summary>         /// <param name="item"></param>         public void Push(T item)         {             _list.Add(item);         }          /// <summary>         /// 出栈         /// O(1)         /// </summary>         /// <returns></returns>         public T Pop()         {             var v = _list[_list.Count - 1];             _list.RemoveAt(_list.Count - 1);             return v;         }          /// <summary>         /// 查看栈顶         /// </summary>         /// O(1)         /// <returns></returns>         public T Peek()         {             return _list[_list.Count - 1];         }          public int Count { get { return _list.Count; } }     } 

用数组实现queue

由于queue先进先出的特性,list头部增删元素的复杂度是O(N),不符合性能要求,我们可以使用前文介绍的环形数组,来实现list头部增删的O(1)

public class MyArrayQueue<T> {     public static void Run()     {         var queue = new MyArrayQueue<string>();          queue.Push("aaaa");         queue.Push("bbbb");         queue.Push("cccc");         queue.Push("dddd");          while (queue.Count > 0)         {             Console.WriteLine(queue.Pop());         }      }     private CircularArray<T> _list = new CircularArray<T>();      /// <summary>     /// 入栈     /// O(1)     /// </summary>     /// <param name="item"></param>     public void Push(T item)     {         _list.AddFirst(item);     }      /// <summary>     /// 出栈     /// O(1)     /// </summary>     /// <returns></returns>     public T Pop()     {         var v = _list.GetLast();         _list.RemoveLast();         return v;     }      /// <summary>     /// 查看栈顶     /// </summary>     /// O(1)     /// <returns></returns>     public T Peek()     {         return _list.GetFirst();     }      public int Count { get { return _list.Count; } } } 

队列的变种:双端队列

所谓双端队列,主要是比普通队列,多一个出入口,可以从队列的两头进行插入,删除。但也破坏了先进先出的原则。
日常场景使用不多。只有 Python用得多一些,因为Python标准库没有提供内置的栈和队列,一般会用双端队列来模拟标准队列。

    public interface IMyQueue<T>     {         /// <summary>         /// 从头入列         /// </summary>         /// <param name="item"></param>         void EnqueueFirst(T item);         /// <summary>         /// 从头出列         /// </summary>         /// <param name="item"></param>         /// <returns></returns>         T DequeueFirst(T item);         /// <summary>         /// 从尾入列         /// </summary>         void EnqueueLast();         /// <summary>         /// 从头出列         /// </summary>         /// <returns></returns>         T DequeueLast();      } 

实现比较简单,不再重复,参考普通队列思路即可。链表/环形数组均可实现。

发表评论

评论已关闭。

相关文章