C#栈

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

  栈(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;
        }
    }
时间: 2024-10-12 21:14:30

C#栈的相关文章

七方件业金离以提领前群约会ODjdidtlwfWv

为了从不同环节,尤其与广大使用人群直接关系的环节反映质量状况,对共享自行车投放点.运营仓库.生产企业等不同环节的产品抽查,覆盖了共享自行车从成品出厂到待投放的关键环节. 该负责人称,根据新车投放情况,结合共享自行车行业市场占有分布特点,本次重点抽查了摩拜.ofo.Hellobike三个品牌的产品,占本次抽查批次总数的83.3%.其中,在天津.无锡.武汉.广州.深圳.东莞6个城市抽查了9批次摩拜产品,占产品抽查批次总数的37.5%,抽查批次合格率88.9%,抽查不合格的1批次产品为待投放于广州市的

“全栈”工程师 请不要随意去做

今天我来给大家说说 "全栈工程师" 的事儿. 写这篇文的背景原因: 很简单就是最近越来越多的人想做[全栈工程师],他们的目标就是全栈,他们才入行短短1-2年,甚至刚从培训班出来:我的目标是做全栈,我啥都要学会,啥都会写,这样我就是大牛了,可以挣大钱,就算创业,我也不用招那么多人,一个人搞定一个产品,融资上市 ,CEO白富美,balabala... 我给他的回复是: 去你xx的,你连JS 数组和对象用法都搞不清,抄几个效果,看几个视频教程摸索摸索就要做万能人了? "全栈&quo

15.1-全栈Java笔记:Java事件模型是什么?事件控制的过程有哪几步??

应用前边两节上一章节的内容,大家可以完成一个简单的界面,但是没有任何的功能,界面完全是静态的,如果要实现具体功能的话,必须要学习事件模型. 事件模型简介及常见事件模型 对于采用了图形用户界面的程序来说,事件控制是非常重要的. 一个源(事件源)产生一个事件并把它(事件对象)送到一个或多个监听器那里,监听器只是简单地等待,直到它收到一个事件,一旦事件被接收,监听器将处理这些事件. 一个事件源必须注册监听器以便监听器可以接收关于一个特定事件的通知. 每种类型的事件都有其自己的注册方法,一般形式为: v

链栈的实现

链栈即链式栈,也就是说我们不用再考虑空间的大小,可随心所欲的进行数据的插入/删除了.和顺序栈一样,仍然要保持其stack的特性,只在一端进行插入和删除,后进先出. 示例代码: #ifndef _LINKSTACK_H #define _LINKSTACK_H typedef int ElemType; typedef int Status; typedef struct linkStack { ElemType data; struct linkStack * top; }linkStack;

95后实习生的远程办公体验(asp.net mvc\C#技术栈)

这个月我们做了一件别人看起来很疯狂的事情,就是让一批95后的实习生实行远程办公,效果还不错,于是写此文总结一下. 其实认真算算,我自己的远程工作经验有十年了吧,在北京工作的时候天气不好就申请在家办公,在硅谷的时候每周有三天在家办公,两天去办公室办公.所以我也算得上是远程办公的老司机了吧. 不过,我之前都是对有多年工作经验的老司机才实行远程办公,还从来没有对还未毕业的实习生实行过.老实说,不敢啊,也不放心,况且我在cnblogs博客园呆了十年,还真没见过对还未毕业的实习生实行过远程办公的. 那为什

全栈必备Linux 基础

Linux 几乎无处不在,不论是服务器构建,还是客户端开发,操作系统的基础技能对全栈来说都是必备的. 系统的选择 Linux发行版本可以大体分为两类,一类是商业公司维护的发行版本,一类是社区组织维护的发行版本,前者以著名的Redhat(RHEL)为代表,后者以Debian为代表. Redhat,应该称为Redhat系列,包括RHEL.Fedora.CentOS(RHEL的社区克隆版本,免费).Ubuntu严格来说不能算一个独立的发行版本,Ubuntu是基于Debian加强而来,一个拥有Debia

JavaScript栈和堆内存,作用域

1.栈 stack"和"堆 heap": 简单的来讲,stack上分配的内存系统自动释放,heap上分配的内存,系统不释放,哪怕程序退出,那一块内存还是在那里.stack一般是静态分配内存,heap上一般是动态分配内存. 2.基本类型和引用类型: 基本类型:存放在栈内存中的简单数据段.数据大小确定,内存空间大小可以分配. 引用类型:存放在堆内存中的对象,变量中实际保存的是一个指针,这个指针指向另一个位置.每个空间大小不一样,要根据情况开进行特定的分配. 详见<Javas

AC日记——双栈排序 洛谷 P1155

双栈排序 思路: 二分图染+模拟: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 1005 #define maxm 2000005 int n,head[maxn],E[maxm],V[maxm],cnt,col[maxn]; int minn[maxn],ai[maxn],sta1[maxn],sta2[maxn],top1,top2; bool if_[maxn][maxn]; inline void in(

leetcode栈--5、valid-parentheses(有效括号)

题目描述 Given a string containing just the characters'(',')','{','}','['and']', determine if the input string is valid. The brackets must close in the correct order,"()"and"()[]{}"are all valid but"(]"and"([)]"are not.

栈的数据结构

package com.wwj.cn; public class SqStack { private final int MAXSIZE = 10; int[] data = new int[MAXSIZE]; int top;// 栈顶指针 }