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

  栈(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. JS数组方法汇总 array数组元素的添加和删除

    js数组元素的添加和删除一直比较迷惑,今天终于找到详细说明的资料了,先给个我测试的代码^-^ var arr = new Array(); arr[0] = "aaa"; arr[ ...

  2. js判断是否是微信浏览器

    <script type="text/javascript"> window.onload = function(){ if(isWeiXin()){ var p = ...

  3. web移动端资源整(1)

    meta基础知识 H5页面窗口自动调整到设备宽度,并禁止用户缩放页面 <meta name="viewport" content="width=device-wid ...

  4. D. Game with Strings

    http://codeforces.com/contest/355/problem/D 这道题问了一下学妹,难道说哥已经老了!!! 首先题意理解上有些问题 比如说 a   b    c b   d   ...

  5. HDU 4951 Multiplication table(2014 Multi-University Training Contest 8)

    思路   如果进制为p    那么当x<p时 (p-1)*(p-x)=(p-(x+1))  *p +x     因为x<p  所以没有进位  所以高位上的数字为    p-(x+1). 根 ...

  6. C++小项目:directx11图形程序(五):shadersclass

    这个类是用来创建着色器并设置输入布局的. 这个类比较特殊,它创建的着色器与Effect文件有关,effect文件是用高级着色语言(hlsl)编写的. shadersclass.h #pragma on ...

  7. C++小项目:directx11图形程序(三):graphicsclass

    这是框架的第三层graphicsclass,这个类才真正可以说是整个程序的框架,因为它组织了后面所有的成员. 代码: graphicsclass.h #pragma once #include< ...

  8. Spark机器学习读书笔记-CH03

    3.1.获取数据: wget http://files.grouplens.org/datasets/movielens/ml-100k.zip 3.2.探索与可视化数据: In [3]: user_ ...

  9. .NET C# 将 mdb 中数据读为 list<string[]> 其中 path 为数据库地址 ,sql 为查询语句

    using System.Data; using System.Data.OleDb; public static List<string[]> select_list(string pa ...

  10. SQLServer存储过程和触发器学习记录及简单例子

     一.存储过程 存储过程即为能完成特定功能的一组SQL语句集.如果需要对查出的多条数据进行操作的话,这里需要理解游标(CURSOR)的概念,对于oracle有for each row命令,可以不用游标 ...