找回密码
 立即注册
首页 业界区 业界 重生之数据结构与算法----队列&栈

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

呼延含玉 2025-6-4 22:21:18
简介

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


  • 栈只能在表的一端(称为栈顶)进行插入和删除操作,遵循 “后进先出”(Last In First Out,LIFO)的原则。就像生活中的一摞盘子,最后放上去的盘子会最先被拿走
  • 队列
    它只允许在表的一端进行插入操作(队尾),在另一端进行删除操作(队头),遵循 “先进先出”(First In First Out,FIFO)的原则。类似于生活中排队买票,先排队的人先买到票离开队列。
1.png

用链表实现stack
  1.     public class MyLinkedStack<T>()
  2.     {
  3.         public static void Run()
  4.         {
  5.             var stack = new MyLinkedStack<string>();
  6.             stack.Push("aaaa");
  7.             stack.Push("bbbb");
  8.             stack.Push("cccc");
  9.             stack.Push("dddd");
  10.             while (stack.Count > 0)
  11.             {
  12.                 Console.WriteLine(stack.Pop());
  13.             }
  14.             
  15.         }
  16.         private LinkedList<T> _linked = new LinkedList<T>();
  17.         /// <summary>
  18.         /// 入栈
  19.         /// O(1)
  20.         /// </summary>
  21.         /// <param name="item"></param>
  22.         public void Push(T item)
  23.         {
  24.             _linked.AddFirst(item);
  25.         }
  26.         /// <summary>
  27.         /// 出栈
  28.         /// O(1)
  29.         /// </summary>
  30.         /// <returns></returns>
  31.         public T Pop()
  32.         {
  33.             var first = _linked.First;
  34.             _linked.RemoveFirst();
  35.             return first.Value;
  36.         }
  37.         /// <summary>
  38.         /// 查看栈顶
  39.         /// </summary>
  40.         /// O(1)
  41.         /// <returns></returns>
  42.         public T Peek()
  43.         {
  44.             return _linked.First.Value;
  45.         }
  46.         public int Count { get { return _linked.Count; } }
  47.     }
复制代码
用链表实现queue
  1. public class MyLinkedQueue<T>
  2. {
  3.     public static void Run()
  4.     {
  5.         var queue = new MyLinkedQueue<string>();
  6.         queue.Enqueue("aaa");
  7.         queue.Enqueue("bbb");
  8.         queue.Enqueue("ccc");
  9.         queue.Enqueue("ddd");
  10.         while (queue.Count > 0)
  11.         {
  12.             Console.WriteLine(queue.Dequeue());
  13.         }
  14.     }
  15.     private LinkedList<T> _linked = new LinkedList<T>();
  16.     /// <summary>
  17.     /// 入列
  18.     /// </summary>
  19.     /// <param name="item"></param>
  20.     public void Enqueue(T item)
  21.     {
  22.         _linked.AddFirst(item);
  23.     }
  24.     /// <summary>
  25.     /// 出列
  26.     /// </summary>
  27.     /// <returns></returns>
  28.     public T Dequeue()
  29.     {
  30.         var last= _linked.Last;
  31.         _linked.RemoveLast();
  32.         return last.Value;
  33.     }
  34.     /// <summary>
  35.     /// 查看队列顶
  36.     /// </summary>
  37.     /// <returns></returns>
  38.     public T Peek()
  39.     {
  40.         return _linked.First.Value;
  41.     }
  42.     public int Count { get { return _linked.Count; } }
  43. }
复制代码
用数组实现stack
  1.     public class MyArrayStack<T>()
  2.     {
  3.         public static void Run()
  4.         {
  5.             var stack = new MyLinkedStack<string>();
  6.             stack.Push("aaaa");
  7.             stack.Push("bbbb");
  8.             stack.Push("cccc");
  9.             stack.Push("dddd");
  10.             while (stack.Count > 0)
  11.             {
  12.                 Console.WriteLine(stack.Pop());
  13.             }
  14.         }
  15.         private List<T> _list=new List<T>();
  16.         /// <summary>
  17.         /// 入栈
  18.         /// O(1)
  19.         /// </summary>
  20.         /// <param name="item"></param>
  21.         public void Push(T item)
  22.         {
  23.             _list.Add(item);
  24.         }
  25.         /// <summary>
  26.         /// 出栈
  27.         /// O(1)
  28.         /// </summary>
  29.         /// <returns></returns>
  30.         public T Pop()
  31.         {
  32.             var v = _list[_list.Count - 1];
  33.             _list.RemoveAt(_list.Count - 1);
  34.             return v;
  35.         }
  36.         /// <summary>
  37.         /// 查看栈顶
  38.         /// </summary>
  39.         /// O(1)
  40.         /// <returns></returns>
  41.         public T Peek()
  42.         {
  43.             return _list[_list.Count - 1];
  44.         }
  45.         public int Count { get { return _list.Count; } }
  46.     }
复制代码
用数组实现queue

由于queue先进先出的特性,list头部增删元素的复杂度是O(N),不符合性能要求,我们可以使用前文介绍的环形数组,来实现list头部增删的O(1)
  1. public class MyArrayQueue<T>
  2. {
  3.     public static void Run()
  4.     {
  5.         var queue = new MyArrayQueue<string>();
  6.         queue.Push("aaaa");
  7.         queue.Push("bbbb");
  8.         queue.Push("cccc");
  9.         queue.Push("dddd");
  10.         while (queue.Count > 0)
  11.         {
  12.             Console.WriteLine(queue.Pop());
  13.         }
  14.     }
  15.     private CircularArray<T> _list = new CircularArray<T>();
  16.     /// <summary>
  17.     /// 入栈
  18.     /// O(1)
  19.     /// </summary>
  20.     /// <param name="item"></param>
  21.     public void Push(T item)
  22.     {
  23.         _list.AddFirst(item);
  24.     }
  25.     /// <summary>
  26.     /// 出栈
  27.     /// O(1)
  28.     /// </summary>
  29.     /// <returns></returns>
  30.     public T Pop()
  31.     {
  32.         var v = _list.GetLast();
  33.         _list.RemoveLast();
  34.         return v;
  35.     }
  36.     /// <summary>
  37.     /// 查看栈顶
  38.     /// </summary>
  39.     /// O(1)
  40.     /// <returns></returns>
  41.     public T Peek()
  42.     {
  43.         return _list.GetFirst();
  44.     }
  45.     public int Count { get { return _list.Count; } }
  46. }
复制代码
队列的变种:双端队列

所谓双端队列,主要是比普通队列,多一个出入口,可以从队列的两头进行插入,删除。但也破坏了先进先出的原则。
日常场景使用不多。只有 Python用得多一些,因为Python标准库没有提供内置的栈和队列,一般会用双端队列来模拟标准队列。
  1.     public interface IMyQueue<T>
  2.     {
  3.         /// <summary>
  4.         /// 从头入列
  5.         /// </summary>
  6.         /// <param name="item"></param>
  7.         void EnqueueFirst(T item);
  8.         /// <summary>
  9.         /// 从头出列
  10.         /// </summary>
  11.         /// <param name="item"></param>
  12.         /// <returns></returns>
  13.         T DequeueFirst(T item);
  14.         /// <summary>
  15.         /// 从尾入列
  16.         /// </summary>
  17.         void EnqueueLast();
  18.         /// <summary>
  19.         /// 从头出列
  20.         /// </summary>
  21.         /// <returns></returns>
  22.         T DequeueLast();
  23.     }
复制代码
实现比较简单,不再重复,参考普通队列思路即可。链表/环形数组均可实现。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册