C#初识栈(stack)和队列(queue)

目录

      • 队列
        • 图示入队出队
        • 代码演示
        • 图示入栈出栈
        • 代码展示
      • 列表、栈、队列

队列

队列很像列表(List),只不过不能按照任意索引来访问或删除指定的项。向队列里增加一个对象时,需要使用enqueue进行队。它会把最新入队的放入队尾。出队时使用dequeue,它会返回队头的对象,同时把它从队伍里面移出,此时队头会变为它之后的一项。

图示入队出队

  1. 入队
    C#初识栈(stack)和队列(queue)_第1张图片

  2. 出队

    C#初识栈(stack)和队列(queue)_第2张图片

代码演示

  1. 核心代码
 class QueueAndStact{
     Queue<string> myQueue;
     public void OptionQueue()
             {
                 myQueue = new Queue<string>();//创建队列对象
                 //【入队enqueue】添加队列内容像队列增加四项。
                 myQueue.Enqueue("First Line");
                 myQueue.Enqueue("Second Line");
                 myQueue.Enqueue("Third Line");
                 myQueue.Enqueue("Last Line");
                 //查看队列第一项内容,但不从队列移出
                 string myLook = myQueue.Peek();
                 //查看队列有几项
                 int FHowMany = myQueue.Count;
                 //【出队dequeue】按照先进先出的规则进行出队
                 string firstOut = myQueue.Dequeue();
                 string secondOut = myQueue.Dequeue();
                 string thirdOut = myQueue.Dequeue();
                 //查看队列有几项
                 int LHowMany = myQueue.Count;
                 //清空队列
                 myQueue.Clear();
                 //查看清空后的队列有几项
                 int AfterClearHowMany = myQueue.Count;
 			   	//进行结果输出
                 Console.WriteLine("查看队列第一项:{0}", myLook);
                 Console.WriteLine("查看此时队列有几项:{0}", FHowMany);
                 Console.WriteLine("出队列第一项:{0}", firstOut);
                 Console.WriteLine("出队列第二项:{0}", secondOut);
                 Console.WriteLine("出队列第三项:{0}", thirdOut);
                 Console.WriteLine("查看此时队列有几项:{0}", LHowMany);
                 Console.WriteLine("查看清空后队列有几项:{0}", AfterClearHowMany);
             }
 }
  1. 结果

    C#初识栈(stack)和队列(queue)_第3张图片

栈与队列非常相似,但是有一个非常大的区别。每个项都要压入(Push)栈,要从栈中取出一项时只能从栈顶弹(Pop)出最新压入的一项。就像你把一打羽毛球放入球筒里,需要拿时就会取出最后一个放进去的。(按照常理,你要非要从另一头取我也没办法。)

图示入栈出栈

C#初识栈(stack)和队列(queue)_第4张图片

代码展示

  1. 核心代码
   class QueueAndStack{
       Stack<string> myStack;//声明栈引用
       public void OptionStack()
           {
               myStack = new Stack<string>();//创建栈对象
               //【压栈Push】向栈压入四项。
               myStack.Push("First Line");
               myStack.Push("Second Line");
               myStack.Push("Third Line");
               myStack.Push("Last Line");
               //查看栈顶内容,但不出栈
               string myLook = myStack.Peek();
               //查看现在栈里有几项
               int FHowMany = myStack.Count;
               //【出栈Pop】弹出栈顶的内容
               string firstOut = myStack.Pop();
               string secondeOut = myStack.Pop();
               string thirdOut = myStack.Pop();
               //查看现在栈里有几项
               int LHowMany = myStack.Count;
               //清空栈
               myStack.Clear();
               //查看现在栈里有几项
               int afterClearStack = myStack.Count;
               //输出结果
               Console.WriteLine("查看栈顶:{0}", myLook);
               Console.WriteLine("查看栈里有几项:{0}", FHowMany);
               Console.WriteLine("第一个出栈:{0}", firstOut);
               Console.WriteLine("第二个出栈:{0}", secondeOut);
               Console.WriteLine("第三个出栈:{0}", thirdOut);
               Console.WriteLine("查看此时栈里有几项:{0}", LHowMany);
               Console.WriteLine("查看清空后栈里有几项:{0}", afterClearStack);
           }
   }
  1. 结果展示

    C#初识栈(stack)和队列(queue)_第5张图片

列表、栈、队列

列表比较适合在需要随时取出数据和对数据操作的的情况下使用。比如一场淘汰赛,会淘汰分数最低的玩家。

队列比较适合有排队等待规则的情况下使用,先来先服务。比如,超市收银台排队。

栈比较适合随时使用最新的数据情况下使用。比如,一落凳子,你肯定会拿取最上面的一个。

你可能会觉得,栈和队列都可以使用列表实现,而Stack和Queue只是让你少写了几行代码。确实,我都这样感觉的。我觉得队列就想我当时学C时链表的尾加法,而栈像是头加法。

在C#中由于List、Queue、Stack都实现了IEnumerable接口,因而他们可以互相转换。

当你在创建他们时,把你需要转换的对象作为参数传入他们的构造函数中,就会获得一摸一样的数据,不过这时你创建的是一个副本,也就是说你会创建一个新的对象。当你修改和操作原始对象时不会对其他对象产生影响。如下代码展示。

public void tarnListQueueStack()
        {
            myStack = new Stack<string>();//创建栈对象
            //【压栈Push】向栈压入四项。
            myStack.Push("First Line");
            myStack.Push("Second Line");
            myStack.Push("Third Line");
            myStack.Push("Last Line");

            List<string> myList = new List<string>(myStack);//将mystack复制到myList
            myQueue = new Queue<string>(myStack);//将myStack复制到myQueue
            Stack<string> atherStack = new Stack<string>(myStack);//将myStack复制到新的atherStack
        
            int FirstStackCount = myStack.Count;//查看执行pop前原始栈有几项
            //对myStack操作,验证会不会对其他复制的对象产生影响
            string myStackPop = myStack.Pop();
            int stackCount = myStack.Count;//查看一次出栈后的mystack的栈里还有几项
            int listCount = myList.Count;//查看list长度
            int queueCount = myQueue.Count;//查看queue长度
            int atherStackCount = atherStack.Count;//查看新的栈有几项

            Console.WriteLine("原始栈执行出栈操作前栈有{0}项", FirstStackCount);
            Console.WriteLine("一次出栈后的mystack的栈里还有{0}项", stackCount);
            Console.WriteLine("list里还有{0}项", listCount);
            Console.WriteLine("queue里还有{0}项", queueCount);
            Console.WriteLine("新的栈有{0}项", atherStackCount);


        }

C#初识栈(stack)和队列(queue)_第6张图片

从输出结果可以看出,对原始的栈myStack进行一次出栈操作后不会影响到其他对象。这时候可能还有一个疑虑,就是以它为参数复制的对象里面项的顺序是怎么存的。是否还会按照每个类型的特点读取之后在写入。下面上代码测试

 public void tarnListQueueStack()
        {
            myStack = new Stack<string>();//创建栈对象
            //【压栈Push】向栈压入四项。
            myStack.Push("First Line");
            myStack.Push("Second Line");
            myStack.Push("Third Line");
            myStack.Push("Last Line");

            List<string> myList = new List<string>(myStack);//将mystack复制到myList
            myQueue = new Queue<string>(myStack);//将myStack复制到myQueue
            Stack<string> atherStack = new Stack<string>(myStack);//将myStack复制到新的atherStack
        
            int FirstStackCount = myStack.Count;//查看执行pop前原始栈有几项
            //对myStack操作,验证会不会对其他复制的对象产生影响
            //string myStackPop = myStack.Pop();
            int stackCount = myStack.Count;//查看一次出栈后的mystack的栈里还有几项
            int listCount = myList.Count;//查看list长度
            int queueCount = myQueue.Count;//查看queue长度
            int atherStackCount = atherStack.Count;//查看新的栈有几项

            /*Console.WriteLine("原始栈执行出栈操作前栈有{0}项", FirstStackCount);
            Console.WriteLine("一次出栈后的mystack的栈里还有{0}项", stackCount);
            Console.WriteLine("list里还有{0}项", listCount);
            Console.WriteLine("queue里还有{0}项", queueCount);
            Console.WriteLine("新的栈有{0}项", atherStackCount);*/

            Console.WriteLine("开始输出myStack:");
            OutputContent(myStack);
            Console.WriteLine("");

            Console.WriteLine("开始输出myList:");
            OutputContent(myList);
            Console.WriteLine("");

            Console.WriteLine("开始输出myQueue:");
            OutputContent(myQueue);
            Console.WriteLine("");

            Console.WriteLine("开始输出atherStack:");
            OutputContent(atherStack);
            Console.WriteLine("");


        }

        public void OutputContent(IEnumerable<string> enumerable)
        {
            int count = 1;
            foreach(string str in enumerable)
            {
                Console.WriteLine("第{0}项:{1}",count, str);
                count++;
            }
            Console.WriteLine("集合输出结束");
        }

输出结果是

C#初识栈(stack)和队列(queue)_第7张图片

可以看出就算是复制也需要遵循每个类型的规则。List列表和Queue队列,进行循环时都是先入先出。然鹅输出和myStack内容一样,说明myStack作为参数时,还是会按照栈的先入后出的规则来读取,然后转换为指定的类型。从ahterStack和myStack结果相反进一步验证了进行foreach循环时还是要先入后出。从代码里也可以看出用他们都实现的IEnumerable接口做参数,可以轻易的让们都能使用这个函数进行循环输出。

根据这个信息在往后推下,如果需要将一个List列表反序除了使用Reverse()方法外还可以使用栈来实现。如下代码

Console.WriteLine("反序前的myList:");
OutputContent(myList);
Console.WriteLine("");

Stack<string> temp = new Stack<string>(myList);
myList = new List<string>(temp);

Console.WriteLine("反序后的myList:");
OutputContent(myList);
Console.WriteLine("");

输出结果
C#初识栈(stack)和队列(queue)_第8张图片
-------------------------------------------------------------------------------------------
最后修改于2020/04/16
每天进步一点点!
C#初识栈(stack)和队列(queue)_第9张图片

你可能感兴趣的:(C#笔记)