3.Stack

3.简单数据结构类-Stack


3.1 知识点

Stack的本质

Stack(栈)是一个C#为我们封装好的类,它的本质也是object[]数组,只是封装了特殊的存储规则。

Stack是栈存储容器,栈是一种先进后出的数据结构,即先存入的数据后获取,后存入的数据先获取。

Stack的申明

需要引用命名空间 using System.Collections; 包含一些集合类。

Stack stack = new Stack();

Stack的增取查改和遍历

当前stack中的元素有:

{}

Push方法:压栈,把元素往栈中压。

stack.Push(1);
stack.Push("123");
stack.Push(true);
stack.Push(1.2f);
stack.Push(new Test());

增完之后stack中的元素有:

{ 1, 123, True, 1.2f, Lesson02_Stack.Test }

当前stack中的元素有:

{ 1, 123, True, 1.2f, Lesson02_Stack.Test }

栈中不存在删除的概念,只有取的概念。

Pop方法:弹栈,把元素从栈顶上弹出。

object v = stack.Pop();
Console.WriteLine(v); // Lesson02_Stack.Test
v = stack.Pop();
Console.WriteLine(v); // 1.2f

取完之后stack中的元素有:

{ 1, 123, True }

当前stack中的元素有:

{ 1, 123, True }

Peek方法:查看栈顶元素。栈无法查看指定位置的元素,只能查看栈顶元素。

// Peek方法只会查看栈顶元素,不会弹出栈顶元素
v = stack.Peek();
Console.WriteLine(v); // True

Contains方法:传入元素,查看元素是否存在于栈中。存在返回true,否则返回false

if (stack.Contains("123"))
{
    Console.WriteLine("存在123"); // 存在123
}

当前stack中的元素有:

{ 1, 123, True }

栈无法改变其中的元素,只能压(存)和弹(取)。如果实在要改,只有清空。

Clear方法:清空栈所有元素。

// stack.Clear(); // 会清空栈,为后面方便演示,注释

遍历

当前stack中的元素有:

{ 1, 123, True }

Count属性:返回栈的长度。

Console.WriteLine(stack.Count); // 3

foreach遍历栈

foreach遍历遍历出来的顺序也是从栈顶到栈底。栈不能直接通过for循环遍历,因为栈没有提供索引器通过[]访问。

foreach (object item in stack)
{
    Console.WriteLine(item);
    // 打印的顺序如下,栈顶到栈底
    // True
    // 123
    // 1
}

ToArray方法:将栈转换为object数组,再用for循环遍历。

// 遍历出来的顺序也是从栈顶到栈底
object[] stackToObjectArray = stack.ToArray();
for (int i = 0; i < stackToObjectArray.Length; i++)
{
    Console.WriteLine(stackToObjectArray[i]);
    // 打印的顺序如下,栈顶到栈底
    // True
    // 123
    // 1
}
Console.WriteLine(stack.Count); // 栈的长度仍然是3,不被影响

while循环弹栈:每次循环弹出栈顶元素。

while (stack.Count > 0)
{
    object o = stack.Pop();
    Console.WriteLine(o);
    // 打印的顺序如下,栈顶到栈底
    // True
    // 123
    // 1
}
Console.WriteLine(stack.Count); // 栈的长度变为0,栈空

Stack的装箱拆箱

由于用object来存储数据,自然存在装箱拆箱。当往其中进行值类型存储时就是在装箱,当将值类型对象取出来转换使用时,就存在拆箱。


3.2 知识点代码

using System;
using System.Collections;

namespace Lesson02_Stack
{
    class Test
    {

    }

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Stack");

            #region 知识点一 Stack的本质
            //Stack(栈)是一个C#为我们封装好的类
            //它的本质也是object[]数组,只是封装了特殊的存储规则

            //Stack是栈存储容器,栈是一种先进后出的数据结构
            //先存入的数据后获取,后存入的数据先获取
            //栈是先进后出
            #endregion

            //主函数内

            #region 知识点二 Stack的申明

            //需要引用命名空间using System.Collections; 包含一些集合类
            Stack stack = new Stack();

            #endregion

            #region 知识点三 Stack的增取查改和遍历

            #region 增

            //当前stack中的元素有
            //{}

            //Push方法 压栈 把元素往栈中压
            stack.Push(1);
            stack.Push("123");
            stack.Push(true);
            stack.Push(1.2f);
            stack.Push(new Test());

            //增完之后stack中的元素有
            //{ 1,123,True,1.2f,Lesson02_Stack.Test}

            #endregion

            #region 取

            //当前stack中的元素有
            //{ 1,123,True,1.2f,Lesson02_Stack.Test}

            //栈中不存在删除的概念
            //只有取的概念

            //Pop方法 弹栈 把元素冲栈顶上弹出
            object v = stack.Pop();
            Console.WriteLine(v);//Lesson02_Stack.Test
            v = stack.Pop();
            Console.WriteLine(v);//1.2f

            //取完之后stack中的元素有
            //{ 1,123,True}

            #endregion

            #region 查

            //当前stack中的元素有
            //{ 1,123,True}

            //Peek方法 查看栈顶元素
            //栈无法查看指定位置的元素 只能查看栈顶元素
            v = stack.Peek();
            Console.WriteLine(v);//True
            //Peek方法只会查看栈顶元素 不会弹出栈顶元素
            v = stack.Peek();
            Console.WriteLine(v);//True

            //Contains方法 传入元素 查看元素是否存在于栈中 存在返回true 否则返回false 
            if (stack.Contains("123"))
            {
                Console.WriteLine("存在123");//存在123
            }

            #endregion

            #region 改

            //当前stack中的元素有
            //{ 1,123,True}

            //栈无法改变其中的元素 只能压(存)和弹(取)实在要改 只有清空
            //Clear方法 清空栈所有元素
            //stack.Clear();//会清空栈 为后面方便演示 注释

            #endregion

            #region 遍历

            //当前stack中的元素有
            //{ 1,123,True}

            //1.Count属性 返回栈的长度
            Console.WriteLine(stack.Count);//3

            //2.foreach遍历栈
            //用foreach遍历遍历出来的顺序 也是从栈顶到栈底
            //栈不能直接通过for循环遍历 因为栈没有提供索引器通过[]访问
            foreach (object item in stack)
            {
                Console.WriteLine(item);
                //打印的顺序如下 栈顶到栈底
                //True
                //123
                //1
            }

            //3.ToArray方法 将栈转换为object数组 再用for循坏遍历
            //遍历出来的顺序 也是从栈顶到栈底
            object[] stackToObjectArray = stack.ToArray();
            for (int i = 0; i < stackToObjectArray.Length; i++)
            {
                Console.WriteLine(stackToObjectArray[i]);
                //打印的顺序如下 栈顶到栈底
                //True
                //123
                //1
            }

            Console.WriteLine(stack.Count);//栈的长度仍然是3 不被影响

            //4.while循环弹栈 每次循环弹出栈顶元素
            while (stack.Count > 0)
            {
                object o = stack.Pop();
                Console.WriteLine(o);
                //打印的顺序如下 栈顶到栈底
                //True
                //123
                //1
            }
            Console.WriteLine(stack.Count);//栈的长度变为0 栈空

            #endregion

            #endregion

            #region 知识点四 Stack的装箱拆箱
            //由于用万物之父来存储数据,自然存在装箱拆箱。
            //当往其中进行值类型存储时就是在装箱。
            //当将值类型对象取出来转换使用时,就存在拆箱。
            #endregion
        }
    }
}

3.3 练习题

请简述栈的存储规则

  • 栈是一种后进先出(LIFO,Last In First Out)的数据结构,即最后进入栈的元素最先被取出。
  • 栈的存储规则是先进后出,最新的元素总是在栈顶,而最旧的元素在栈底。

写一个方法计算任意一个数的二进制数,使用栈结构方式存储,之后打印出来

class语句块内,主函数外

// 计算十进制转二进制方法
static void CalculateDecimalToBinary(uint num)
{
    Console.Write("{0}的二进制是:");

    // 创建一个栈
    Stack stack = new Stack();

    // 循环遍历压栈
    while (true)
    {
        // 保存除2的余数
        stack.Push(num % 2);

        // 除2
        num /= 2;

        // 如果当前被除数是1的话 存了这个1就跳出while循环
        if (num == 1)
        {
            stack.Push(num);
            break;
        }
    }

    // 循环弹栈,打印转化后的2进制
    while (stack.Count > 0)
    {
        Console.Write(stack.Pop());
    }

    Console.WriteLine();

    //用例子模拟演算

    ////10
    //num = 10;
    //stack.Push(num % 2);//0
    //num /= 2;//5
    //stack.Push(num % 2);//1
    //num /= 2;//2
    //stack.Push(num % 2);//0
    //num /= 2;//1
    //if( num == 1 )
    //{
    //    stack.Push(num);//1
    //}
}

主函数内

// 调用示例
CalculateDecimalToBinary(10);  // 10的二进制是:1010
CalculateDecimalToBinary(2);   // 2的二进制是:10
CalculateDecimalToBinary(3);   // 3的二进制是:11
CalculateDecimalToBinary(8);   // 8的二进制是:1000
CalculateDecimalToBinary(16);  // 16的二进制是:10000

3.4 练习题代码

using System;
using System.Collections;

namespace Lesson02_练习题
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Stack练习题");
            #region 练习题一
            //请简述栈的存储规则
            //先进后出
            #endregion

            //主函数内

            #region 练习题二
            //写一个方法计算任意一个数的二进制数
            //使用栈结构方式存储,之后打印出来

            //首先要熟悉手算二进制的方法 除二取余法

            CalculateDecimalToBinary(10);//10的二进制是:1010
            CalculateDecimalToBinary(2);//2的二进制是:10
            CalculateDecimalToBinary(3);//3的二进制是:11
            CalculateDecimalToBinary(8);//8的二进制是:1000
            CalculateDecimalToBinary(16);//16的二进制是:10000


            #endregion
        }

        //class语句块内 主函数外

        #region 练习题二

        //计算十进制转二进制方法
        static void CalculateDecimalToBinary(uint num)
        {
            Console.Write("{0}的二进制是:", num);

            //new出一个栈
            Stack stack = new Stack();

            //while循环遍历压栈
            while (true)
            {
                //保存除2的余数
                stack.Push(num % 2);

                //除2
                num /= 2;

                //如果当前被除数是1的话 存了这个1就跳出while循环
                if (num == 1)
                {
                    stack.Push(num);
                    break;
                }
            }

            //循环弹栈 打印转化后的2进制
            while (stack.Count > 0)
            {
                Console.Write(stack.Pop());
            }

            Console.WriteLine();

            //用例子模拟演算

            ////10
            //num = 10;
            //stack.Push(num % 2);//0
            //num /= 2;//5
            //stack.Push(num % 2);//1
            //num /= 2;//2
            //stack.Push(num % 2);//0
            //num /= 2;//1
            //if( num == 1 )
            //{
            //    stack.Push(num);//1
            //}
        }

        #endregion
    }
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏