亲自教你实现栈及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日

相关文章

  • SQL Server 2005 中使用 Try Catch 处理异常

    下面是详细讲解 SQL Server 2005 中使用 TryCatch 处理异常的完整攻略。 什么是 TryCatch TryCatch 是一种异常处理机制,可以在代码执行过程中捕获异常,并采取不同的措施对它们进行处理。在 SQL Server 中,TryCatch 可以用来处理 T-SQL 脚本中的异常。 使用 TryCatch 处理异常的基本格式 在 …

    C# 2023年5月15日
    00
  • asp.net生成缩略图实现代码

    生成缩略图是一个常见的需求,在asp.net中实现也比较简单。可以通过使用System.Drawing命名空间下的Image类来完成生成缩略图的功能。下面分步骤详细讲解如何实现: 步骤一:引用命名空间 using System.Drawing; using System.Drawing.Imaging; 步骤二:加载图片 首先需要对要生成缩略图的图片进行加载…

    C# 2023年5月31日
    00
  • C#用递归算法实现:一列数的规则如下: 1、1、2、3、5、8、13、21、34,求第30位数是多少

    针对这个问题,我们可以采用递归算法进行解决。首先,我们需要理解这个数列的规律,这是一个典型的斐波那契数列,数列从第三项开始,每一项都等于前两项之和,如下: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, … 根据这个规律,我们可以编写一个递归函数来计算斐波那契数列的任意一项,函数的形式如下: public static int Fib…

    C# 2023年6月8日
    00
  • asp.net(c#)开发中的文件上传组件uploadify的使用方法(带进度条)

    下面我将为您详细讲解asp.net(c#)开发中文件上传组件uploadify的使用方法(带进度条)的完整攻略。 一. 简介 uploadify是一款基于jQuery的文件上传插件,支持多文件上传,支持进度条显示。 二. 安装与引入 下载uploadify:在官网 https://www.uploadify.com/ 下载uploadify并解压文件。 引入…

    C# 2023年6月1日
    00
  • C#注释的一些使用方法浅谈

    C#注释的一些使用方法浅谈 简介 注释是一种解释源代码的方法,在C#中,注释可以分为两种类型:单行注释和多行注释。 单行注释 在代码行的后面以双斜杠 // 开头,这一行的内容就被视作注释,注释可以在同一行代码的下方,说明这一行代码的作用。 示例: int a = 1; // 定义变量a,赋值为1 多行注释 多行注释又称块注释,可以用用 /* 和 */ 包围一…

    C# 2023年5月15日
    00
  • SQL Server LocalDB 在 ASP.NET中的应用介绍

    SQL Server LocalDB是一种轻量级版本的SQL Server数据库引擎,它可以在本地计算机上运行,不需要安装完整的SQL Server数据库引擎。在ASP.NET应用程序中,可以使用SQL Server LocalDB来存储和管理数据。本文将介绍如何在ASP.NET中使用SQL Server LocalDB,包括创建数据库、创建表、插入数据、查…

    C# 2023年5月15日
    00
  • APS.NET MVC4生成二维码简单解析

    APS.NET MVC4生成二维码简单解析 本文将详细讲解如何使用ASP.NET MVC4框架生成二维码,并通过简单的解析步骤来读取其中的信息,以便在实际项目中更方便地实现一些功能。 首先,我们需要了解如何生成二维码。在ASP.NET MVC4中可以通过QRCoder库来快速简单地生成二维码。 QRCoder是一种基于C#的二维码生成库,可以将文本、网址等信…

    C# 2023年5月31日
    00
  • C#实现字符串倒序的写法

    以下是“C#实现字符串倒序的写法”的完整攻略: 1. 使用内置函数 C#已经为字符串倒序提供了一个内置函数——Reverse(),可以直接操作字符数组,实现字符串倒序。下面是示例代码: using System; class Program { static void Main() { string str = "Hello, world!&quo…

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