亲自教你实现栈及C#中Stack源码分析

亲自教你实现栈及C#中Stack源码分析

栈的定义

栈是一种具有特殊行为的线性数据结构,栈中的元素遵循 LIFO(Last In First Out) 原则:

  • 入栈(Push):在栈的顶部添加一个元素;
  • 出栈(Pop):从栈的顶部移除一个元素;
  • 取顶(Peek):获取栈顶元素,但不对栈进行操作;
  • 判空(IsEmpty):判断栈中是否有元素。

栈的实现方式有两种:数组和链表。

数组实现栈

数组实现栈思路比较简单,基本原理就是使用数组来存储栈中的元素。具体实现方式请参考以下代码:

class ArrayStack<T>
{
    private T[] stack;
    private int top = -1;

    public ArrayStack(int capacity)
    {
        stack = new T[capacity];
    }

    public void Push(T item)
    {
        if (top == stack.Length - 1)
        {
            throw new StackOverflowException("stack overflow");
        }
        stack[++top] = item;
    }

    public T Pop()
    {
        if (top == -1)
        {
            throw new InvalidOperationException("stack is empty");
        }
        return stack[top--];
    }

    public T Peek()
    {
        if (top == -1)
        {
            throw new InvalidOperationException("stack is empty");
        }
        return stack[top];
    }

    public bool IsEmpty()
    {
        return top == -1;
    }
}

以上代码展示了如何使用数组实现栈类,其支持Push、Pop、Peek和IsEmpty操作。在创建ArrayStack对象时,需要传入一个整数参数capacity,表示栈的最大容量。在Push操作中,如果栈已满,则会抛出StackOverflowException异常,在Pop和Peek操作中,如果栈为空,则会抛出InvalidOperationException异常。示例代码:

static void Main(string[] args)
{
    var stack = new ArrayStack<int>(10);
    stack.Push(1);
    int item = stack.Pop(); // item = 1
    Console.WriteLine(item);
}

链表实现栈

链表实现栈的原理比数组方式更加简单,正是由于链表的“可增长性”,其可以实现 really dynamic stack,而数组实现的最大容量(capacity)是一开始就定好了的。

链表实现栈的具体实现方式请参考以下代码:

class LinkedListStack<T>
{
    private class Node
    {
        public T item;
        public Node next;
    }

    private Node top;

    public void Push(T item)
    {
        Node oldTop = top;
        top = new Node();
        top.item = item;
        top.next = oldTop;
    }

    public T Pop()
    {
        if (top == null)
        {
            throw new InvalidOperationException("stack is empty");
        }
        T item = top.item;
        top = top.next;
        return item;
    }

    public T Peek()
    {
        if (top == null)
        {
            throw new InvalidOperationException("stack is empty");
        }
        return top.item;
    }

    public bool IsEmpty()
    {
        return top == null;
    }
}

在链表实现栈代码中,我们在Push操作中,首先创建一个新的Node实例,并将其设置为top节点,然后将旧的top节点设置为新的top节点的next属性。示例代码:

static void Main(string[] args)
{
    var stack = new LinkedListStack<int>();
    stack.Push(1);
    int item = stack.Pop(); // item = 1
    Console.WriteLine(item);
}

C#中Stack源码分析

Stack是C#内置的一种数据结构,具有Push、Pop、Peek和Count等方法,以支持类似于数组的行为。但是,与数组不同的是,它是一种动态数据结构。以下是Stack的最简示例代码:

Stack<int> stack = new Stack<int>();
stack.Push(1);
int item = stack.Pop(); // item = 1
Console.WriteLine(item);

在源代码中,Stack类是使用动态数组实现的。这意味着,在执行Push操作时,如果已经达到了动态数组的最大容量,则新的容量将是原始容量的两倍。同时,在Pop操作中,如果容量减小到堆栈元素数的四分之一,则Stack将减小其容量到原始容量的一半。

自C#2.0以来,Stack类实现了IEnumerable接口,以支持枚举。如果您希望对Stack中的元素进行枚举,则可以使用foreach循环,如以下示例代码所示:

foreach (int i in stack)
{
    Console.Write(i + " ");
}

示例说明

以下是两个示例程序,在例子1中我们使用的是链表实现,而在例子2中我们使用的是C#内置的Stack数据结构。

示例1

class Program
{
    static void Main(string[] args)
    {
        LinkedListStack<int> stack = new LinkedListStack<int>();
        stack.Push(1);
        stack.Push(2);
        stack.Push(3);

        Console.WriteLine(stack.Pop()); // 输出3
        Console.WriteLine(stack.Pop()); // 输出2
        Console.WriteLine(stack.Pop()); // 输出1
    }
}

以上示例演示了如何使用LinkedListStack实现栈。

示例2

class Program
{
    static void Main(string[] args)
    {
        Stack<int> stack = new Stack<int>();
        stack.Push(1);
        stack.Push(2);
        stack.Push(3);

        Console.WriteLine(stack.Pop()); // 输出3
        Console.WriteLine(stack.Pop()); // 输出2
        Console.WriteLine(stack.Pop()); // 输出1
    }
}

以上示例演示了如何使用C#内置的Stack类实现栈。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:亲自教你实现栈及C#中Stack源码分析 - Python技术站

(0)
上一篇 2023年6月1日
下一篇 2023年6月1日

相关文章

  • 解析C#面向对象编程中方法(method)的使用

    解析C#面向对象编程中方法的使用 C#中的方法是一种封装了代码的基本单元,其中包含了一系列的语句,并可以接收参数、执行操作,并返回值。 方法的定义 在C#中,方法必须定义在类中。其定义的语法如下: [访问修饰符] [修饰符] 返回类型 方法名称([参数列表]) { // 方法体 } 其中,访问修饰符和修饰符是可选的。返回类型可以是任何有效的数据类型或者voi…

    C# 2023年5月15日
    00
  • C#实现加密的几种方法介绍

    C#实现加密的几种方法介绍 在C#中实现加密的方法有很多,本文将介绍其中的几种常用方法。 1. 对称加密算法 对称加密算法是指加密和解密使用同一密钥的加密算法。常用的对称加密算法有DES、3DES、AES等。 1.1 DES加密算法 using System.Security.Cryptography; using System.Text; public s…

    C# 2023年6月6日
    00
  • C#中字符串与字节数组的转换方式

    C# 中字符串和字节数组是非常常见的数据类型,字符串和字节数组可以相互转换。在某些场景下,需要在两种类型的数据之间进行转换。因此,了解如何在 C# 中转换字符串和字节数组是非常必要的。 字符串到字节数组的转换 在 C# 中,字符串转换为字节数组需要使用 System.Text.Encoding 类。Encoding 类是 .NET Framework 中存储…

    C# 2023年6月7日
    00
  • (asp.net c#)DropDownList绑定后显示对应的项的两种方法

    下面是详细讲解“(asp.net c#)DropDownList绑定后显示对应的项的两种方法”的攻略: 1. 根据绑定的值选中对应的项 如果绑定的是数据源,可以在数据绑定完成后,通过设置DropDownList的SelectedItem属性,来实现选中对应的项。 “`csharp // 获取数据源 List data = new List{“apple”,…

    C# 2023年5月31日
    00
  • C#设计模式之Builder生成器模式解决带老婆配置电脑问题实例

    下面我将详细讲解C#设计模式之Builder生成器模式解决带老婆配置电脑问题实例的完整攻略。 什么是Builder生成器模式 Builder生成器模式是一种创建型设计模式,它将对象的构建和表示分离,使得同样的构建过程可以创建不同的表示,这样可以使得对象的构建更加灵活。Builder生成器模式一般涉及如下几个角色: Builder:抽象生成器,用于定义创建一个…

    C# 2023年6月1日
    00
  • 利用C#代码将html样式文件与Word文档互换的方法

    利用C#代码将html样式文件与Word文档互换,可以实现在Word文档中添加html样式,同时也可以将Word文档转化为html样式文件,实现两者之间的互相转换。下面提供两个示例说明: 示例1:将html样式添加到Word文档中 1. 引入Word文档COM组件 在C#代码中,首先需要引入Word文档的COM组件。可以在程序的引用中找到 Microsoft…

    C# 2023年5月31日
    00
  • C# 向二进制文件进行读写的操作方法

    C# 向二进制文件进行读写的操作方法 在 C# 中,我们可以通过 FileStream 和 BinaryWriter/BinaryReader 类来进行二进制文件的读写操作。 1. 二进制文件写入操作示例 string fileName = "test.dat"; using (FileStream fs = new FileStream…

    C# 2023年6月1日
    00
  • C#中DataTable 转实体实例详解

    下面是关于“C#中DataTable 转实体实例详解”的完整攻略: 1. 为什么需要将DataTable转为实体实例 在C#中,DataTable是一种非常常见的数据类型。在我们进行数据查询、统计和展示时,经常使用DataTable来存储数据。而在使用DataTable时,我们通常需要将DataTable中的数据转化为我们自定义的实体类型,利用实体的属性和方…

    C# 2023年5月31日
    00
合作推广
合作推广
分享本页
返回顶部