线性表、栈和队列这三种数据结构的数据元素以及数据元素间的逻辑关系完全相同,差别是线性表的操作不受限制,而栈和队列的操作受到限制。栈的操作只能在表的一端进行, 队列的插入操作在表的一端进行而其它操作在表的另一端进行,所以,把栈和队列称为操作受限的线性表。

  栈(Stack)是操作限定在表的尾端进行的线性表。表尾由于要进行插入、删除等操作,所以,它具有特殊的含义,把表尾称为栈顶(Top) ,另一端是固定的,叫栈底(Bottom) 。当栈中没有数据元素时叫空栈(Empty Stack)。栈通常记为:S= (a 1 ,a 2 ,…,a n ),S是英文单词stack的第 1 个字母。a 1 为栈底元素,a n 为栈顶元素。这n个数据元素按照a 1 ,a 2 ,…,a n 的顺序依次入栈,而出栈的次序相反,a n 第一个出栈,a 1 最后一个出栈。所以,栈的操作是按照后进先出(Last In First Out,简称LIFO)或先进后出(First In Last Out,简称FILO)的原则进行的, 因此, 栈又称为LIFO表或FILO表。

  栈的操作示意图如图所示。

栈的形式化定义为:栈(Stack)简记为 S,是一个二元组,

S = (D, R)

其中: D 是数据元素的有限集合;

R 是数据元素之间关系的有限集合。

  由于栈只能在栈顶进行操作, 所以栈不能在栈的任意一个元素处插入或删除元素。因此,栈的操作是线性表操作的一个子集。栈的操作主要包括在栈顶插入元素和删除元素、取栈顶元素和判断栈是否为空等。与线性表一样,栈的运算是定义在逻辑结构层次上的,而运算的具体实现是建立在物理存储结构层次上的。因此,把栈的操作作为逻辑结构的一部分,而每个操作的具体实现只有在确定了栈的存储结构之后才能完成。

  栈的接口定义如下所示。

public interface IStack<T>//栈的接口定义
    {
        int GetLength(); //求栈的长度
        bool IsEmpty(); //判断栈是否为空
        void Clear(); //清空操作
        void Push(T item); //入栈操作
        T Pop(); //出栈操作
        T GetTop(); //取栈顶元素
    }

  用一片连续的存储空间来存储栈中的数据元素,这样的栈称为顺序栈(Sequence Stack)。类似于顺序表,用一维数组来存放顺序栈中的数据元素。

  顺序栈类 SeqStack<T>的实现说明如下所示。

public class SeqStack<T> : IStack<T>//顺序栈类
    {
        private int max;        //顺序栈的容量
        private int top;        //指示顺序栈的栈顶
        private T[] data;       //数组,用于存储顺序栈中的数据元素

        public int Max
        {
            get { return max; }
            set { max = value; }
        }
        public int Top
        {
            get { return top; }
        }
        public T this[int index]
        {
            get { return data[index]; }
            set { data[index] = value; }
        }
        public SeqStack(int size)
        {
            data = new T[size];
            max = size;
            top = -1;
        }
        public int GetLength()
        {
            return top + 1;
        }

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

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

        public void Clear()
        {
            top = -1;
        }

        public void Push(T item)
        {
            if (IsFull())
            {
                Console.WriteLine("Stack is full");
                return;
            }
            data[++top] = item;
        }

        public T Pop()
        {
            T tmp = default(T);
            if (IsEmpty())
            {
                Console.WriteLine("Stack is empty");
                return tmp;
            }
            tmp = data[top--];
            return tmp;
        }

        public T GetTop()
        {
            if (IsEmpty())
            {
                Console.WriteLine("Stack is empty");
                return default(T);
            }
            return data[top];
        }
    }

  栈的另外一种存储方式是链式存储,这样的栈称为链栈(Linked Stack)。链栈通常用单链表来表示,它的实现是单链表的简化。所以,链栈结点的结构与单链表结点的结构一样,如图所示。由于链栈的操作只是在一端进行,为了操作方便,把栈顶设在链表的头部,并且不需要头结点。

  把链栈看作一个泛型类,类名为 LinkStack<T>。LinkStack<T>类中有一个字段 top 表示栈顶指示器。由于栈只能访问栈顶的数据元素,而链栈的栈顶指示器又不能指示栈的数据元素的个数。所以,求链栈的长度时,必须把栈中的数据元素一个个出栈,每出栈一个数据元素,计数器就增加 1,但这样会破坏栈的结构。为保留栈中的数据元素, 需把出栈的数据元素先压入另外一个栈, 计算完长度后,再把数据元素压入原来的栈。但这种算法的空间复杂度和时间复杂度都很高,所以, 以上两种算法都不是理想的解决方法。 理想的解决方法是 LinkStack<T>类增设一个字段 num 表示链栈中结点的个数。

  链栈类 LinkStack<T>的实现说明如下所示。

public class Node<T>//链栈结点类
    {
        private T data;
        private Node<T> next;

        public T Data
        {
            get { return data; }
            set { data = value; }
        }
        public Node<T> Next
        {
            get { return next; }
            set { next = value; }
        }

        public Node(T val, Node<T> node)
        {
            data = val;
            next = node;
        }
        public Node(T val)
        {
            data = val;
            next = null;
        }
        public Node(Node<T> node)
        {
            data = default(T);
            next = node;
        }
        public Node()
        {
            data = default(T);
            next = null;
        }
    }
    public class LinkStack<T> : IStack<T>  //链栈类的实现
    {
        private Node<T> top;    //栈顶指示器
        private int num;        //栈中结点的个数

        public Node<T> Top
        {
            get { return top; }
            set { top = value; }
        }
        public int Num
        {
            get { return num; }
            set { num = value; }
        }

        public LinkStack()
        {
            top = null;
            num = 0;
        }

        public int GetLength()
        {
            return num;
        }

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

        public void Clear()
        {
            top = null;
            num = 0;
        }

        public void Push(T item)
        {
            Node<T> node = new Node<T>(item);
            if (top == null)
            {
                top = node;
            }
            else
            {
                top.Next = node;
                top = node;
            }
            ++num;
        }

        public T Pop()
        {
            if (IsEmpty())
            {
                Console.WriteLine("Stack is empty!");
                return default(T);
            }
            Node<T> p = top;
            top = top.Next;
            return p.Data;
        }

        public T GetTop()
        {
            if (IsEmpty())
            {
                Console.WriteLine("Stack is empty!");
                return default(T);
            }
            return top.Data;
        }
    }

C#栈的更多相关文章

  1. 通往全栈工程师的捷径 —— react

    腾讯Bugly特约作者: 左明 首先,我们来看看 React 在世界范围的热度趋势,下图是关键词“房价”和 “React” 在 Google Trends 上的搜索量对比,蓝色的是 React,红色的 ...

  2. Java 堆内存与栈内存异同(Java Heap Memory vs Stack Memory Difference)

    --reference Java Heap Memory vs Stack Memory Difference 在数据结构中,堆和栈可以说是两种最基础的数据结构,而Java中的栈内存空间和堆内存空间有 ...

  3. duang~免费的学习视频来啦:学霸君之全栈测试

    学霸君向童鞋们推荐一款 同名学霸学习 视频教程 重点是完全免费收看学习噢!!! 今天 学霸君推荐腾讯课堂的学霸君之全栈测试 复制下方链接至腾讯课堂中报名学习 https://ke.qq.com/cou ...

  4. [数据结构]——链表(list)、队列(queue)和栈(stack)

    在前面几篇博文中曾经提到链表(list).队列(queue)和(stack),为了更加系统化,这里统一介绍着三种数据结构及相应实现. 1)链表 首先回想一下基本的数据类型,当需要存储多个相同类型的数据 ...

  5. BZOJ1012: [JSOI2008]最大数maxnumber [线段树 | 单调栈+二分]

    1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 8748  Solved: 3835[Submi ...

  6. BZOJ 4453: cys就是要拿英魂![后缀数组 ST表 单调栈类似物]

    4453: cys就是要拿英魂! Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 90  Solved: 46[Submit][Status][Discu ...

  7. BZOJ 3238: [Ahoi2013]差异 [后缀数组 单调栈]

    3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2326  Solved: 1054[Submit][Status ...

  8. .NET全栈开发工程师学习路径

    PS:最近一直反复地看博客园以前发布的一条.NET全栈开发工程师的招聘启事,觉得这是我看过最有创意也最朴实的一个招聘启事,更为重要的是它更像是一个技术提纲,能够指引我们的学习和提升,现在转载过来与各位 ...

  9. Nodejs之MEAN栈开发(八)---- 用户认证与会话管理详解

    用户认证与会话管理基本上是每个网站必备的一个功能.在Asp.net下做的比较多,大体的思路都是先根据用户提供的用户名和密码到数据库找到用户信息,然后校验,校验成功之后记住用户的姓名和相关信息,这个信息 ...

  10. 匹夫细说C#:不是“栈类型”的值类型,从生命周期聊存储位置

    0x00 前言: 匹夫在日常和别人交流的时候,常常会发现一旦讨论涉及到“类型”,话题的热度就会立马升温,因为很多似是而非.或者片面的概念常常被人们当做是全面和正确的答案.加之最近在园子看到有人翻译的& ...

随机推荐

  1. shell算数运算

    ((i=$j+$k))    等价于 i=`expr $j + $k`((i=$j-$k))     等价于   i=`expr $j -$k`((i=$j*$k))     等价于   i=`exp ...

  2. 一个网络传输框架——zeroMQ 调研笔记

    一.它是什么 zeroMQ,一个处理消息传输的库,重点在传输上,看起来它像是在socket上面封装了一层,让我们可以很容易的利用它来做N对M的数据传输,在分布式系统中很方便,在接收端它有round-r ...

  3. redis命令全集(自用)

    1.连接操作相关的命令 quit:关闭连接(connection) auth:简单密码认证 2.对value操作的命令 exists(key):确认一个key是否存在 del(key):删除一个key ...

  4. ADO.NET学习

    ADO.NET重要的类 在.NET访问MySql数据库时的几点经验! string connstr=Setting.Instance().GetConnectionString("MySql ...

  5. mongodb 使用场景和不使用场景

    1.mongodb介绍 MongoDB (名称来自"humongous") 是一个可扩展的高性能,开源,模式自由,面向文档的数据库.它使用C++编写.MongoDB特点: a.面向 ...

  6. spark发行版笔记4Spark Streaming事务处理彻底掌握

    Spark Streaming事务处理彻底掌握 感谢DT大数据梦工厂支持提供以下内容,DT大数据梦工厂专注于Spark发行版定制. 内容概括: 1Exactly once 2 输出不重复 1 正如银行 ...

  7. 通过npm安装 Cordova

    通过npm安装 Cordova 首先请确保你在本地已经安装了NodeJS(可以调用npm命令), 并且是联网状态的.如果不知道如何安装NodeJS, 请参考 ”四步完成NodeJS安装,配置和测试”. ...

  8. eclipse 启动失败(找不到jvm)

    今天启动eclipse时提示了一个错误 在网上找到的解决方法是在eclipse的快捷方式中加入Java的JVM的路径,方法如下: 右键eclipse快捷方式 ->属性 在目标中  如果只有 D: ...

  9. jQuery LigerUI V1.2.2 (包括API和全部源码) 发布

    前言 这次版本主要对树进行了加载性能上面的优化,并解决了部分兼容性的问题,添加了几个功能点. 欢迎使用反馈. 相关链接 API:         http://api.ligerui.com/ 演示地 ...

  10. 在CDH5.5.0上安装Kudu6.0

    1. 下载安装文件: a. CSD文件:KUDU-0.6.0.jar b. kudu parcel:KUDU-0.6.0-1.kudu0.6.0.p0.334-el6.parcel和manifest. ...