数据结构与算法—栈

什么是栈

百度百科上,栈是这么定义的:

  • 栈(stack)又名堆栈,它是一种运算受限线性表。限定仅在表尾进行插入删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。

稍微介绍一下关键名词:

  • 运算受限:也就是这个表你不能随便的删除插入。只能按照它的规则进行插入删除。比如栈就只能在一端就行插入和删除。同样,队列也是运算受限,只能在两天操作。
  • 线性表:栈也是一种线性表,前面详细介绍过线性表,它表达的是一种数据的逻辑关系。也就是在栈内各个元素是相邻的。当然在具体实现上也分数组和链表实现,他们的物理存储结构不同。但是逻辑结构(实现的目的)相同。
  • 栈顶栈底: 这个描述是偏向于逻辑上的内容,因为大家知道数组在末尾插入删除更容易,而单链表通常在头插入删除更容易。所以数组可以用末尾做栈顶,而链表可以头做栈顶。

栈的应用:

  • 栈的应用广泛,比如你的程序执行查看调用堆栈、加减运算、甚至在搜索算法中dfs,替代递归等等。所以栈也是必须掌握的一门数据结构。很多规范也是栈,比如上图放书拿书一样!

设计与介绍

这里我们介绍数组实现的栈和链表实现的栈。

数组实现

结构设计

  • 对于数组来说,我们模拟栈的过程很简单,因为栈是后进先出,我们很容易在数组的末尾进行插入和删除。所以我们选定末尾为栈顶。所以对于一个栈所需要的基础元素是 一个data数组和一个top(int)表示栈顶位置。
  • 那么初始话以及构造的函数代码为:
private T data[];
private int top;
public seqStack() {
	data=(T[]) new Object[10];
	top=-1;
}
public seqStack(int maxsize)
{
	data=(T[]) new Object[maxsize];
	top=-1;
}

push插入

栈的核心操作之一push:入栈操作。

  • 如果top<数组长度-1。入栈。top++;a[top]=value;
  • 如果top==数组长度-1;栈满。

pop弹出并返回首位

  • 如果top>=0,栈不为空,可以弹出。return data[top--];
  • 如下图,本来栈为1,2,3,4(栈顶),执行pop操作。top变为3的位置并且返回4;

其他操作

  • 其他例如peek操作时返回栈顶不弹出.所以只需满足题意时候return data[top]即可。

链表实现

有数组实现,链表当然也能实现。对于栈的运算。大致可以分为两种思路:

  • 像数组那样在尾部插入删除。大家都知道链表效率低在查询。而查询到尾部效率很低。而我们就算用了尾指针,可以解决尾部插入效率。但是依然无法解决删除效率(删除需要找到前节点).还需要双向链表。前面虽然详细介绍过双向链表,但是这样未免太复杂!
  • 所以我们采用带头节点的单链表在头部插入删除,把头部当中栈顶,这样精了很多。插入直接在头节点后插入。而删除也直接删除头节点后第一个元素即可。

结构设计

长话短说,短话不说。直接上代码就懂。 链表的节点:

static class node<T>
{
	T data;
	node next;
	public node() {
	}
	public node(T value)
	{
		this.data=value;
	}
}

基本结构:

public class lisStack <T>{
	int length;
    node<T> head;//头节点
    public lisStack() {
		head=new node<>();
		length=0;
	}
	//其他方法
}

push插入

与单链表头插入一致,如果不太了解请先看笔者队线性表介绍的。

和数组形成的栈有个区别。就是理论上栈没有大小限制(不突破内存系统限制)。不需要考虑是否越界。

  • 节点team入栈
  • 空链表入栈head.next=team;
  • 非空入栈team.next=head.next;head.next=team;

pop弹出

与单链表头删除一致,如果不太了解请先看笔者队线性表介绍的。

和数组同样需要判断是否为空。

  • 节点team出栈
  • head指向team后驱节点。不需要考虑链表是否为1个节点。如果为1个节点,team.next=null.执行完毕head.next=null。变为空,满足条件。

其他操作

  • 其他例如peek操作时返回栈顶不弹出.所以只需判空满足题意时候return head.next.data即可。而length你可以遍历链表返回长度,也可以动态设置(本文采取)跟随栈长变化。其他操作直接看api。

实现代码

数组实现

package 队栈;

public class seqStack<T> {

    private T data[];
    private int top;
    public seqStack() {
        data=(T[]) new Object[10];
        top=-1;
    }
    public seqStack(int maxsize)
    {
        data=(T[]) new Object[maxsize];
        top=-1;
    }
    boolean isEmpty()
    {
        return top==-1;
    }
    int length()
    {
        return top+1;
    }

    boolean push(T value) throws Exception//压入栈
    {
        if(top+1>data.length-1)
        {
            throw new Exception("栈已满");
        }
        else {
            data[++top]=value;
            return true;
        }
    }
    T peek() throws Exception//返回栈顶元素不移除
    {
        if(!isEmpty())
        {
            return data[top];
        }
        else {
            throw new Exception("栈为空");
        }
    }
    T pop() throws Exception
    {
        if(isEmpty())
        {
            throw new Exception("栈为空");
        }
        else {
           return data[top--];
        }
    }
    public String toString()
    {
        if(top==-1)
        {
            return "";
        }
        else {
            String va="";
            for(int i=top;i>=0;i--)
            {
                va+=data[i]+"  ";
            }
            return va;
        }
    }
}

链表实现

package 队栈;

public class lisStack <T>{
    static class node<T>
    {
        T data;
        node next;
        public node() {
        }
        public node(T value)
        {
            this.data=value;
        }
    }
    int length;
    node<T> head;//头节点
    public lisStack() {
        head=new node<>();
        length=0;
    }
    boolean isEmpty()
    {
        return head.next==null;
    }
    int length()
    {
        return length;
    }
    public void push(T value) {//近栈
       node<T> team=new node<T>(value);
       if(length==0)
       {
           head.next=team;
       }
       else {
        team.next=head.next;
        head.next=team;}
       length++;
    }
    public T peek() throws Exception {
        if(length==0) {throw new Exception("链表为空");}
        else {//删除
            return (T) head.next.data;
        }
  }
    public T pop() throws Exception {//出栈
          if(length==0) {throw new Exception("链表为空");}
          else {//删除
            T value=(T) head.next.data;
            head.next=head.next.next;//va.next
            length--;
            return value;

        }
    }
    public String toString(){
        if(length==0) {return "";}
        else {
            String va="";
            node team=head.next;
            while(team!=null)
            {
                va+=team.data+" ";
                team=team.next;
            }
            return va;
        }

    }
}

测试

总结

  • 栈的逻辑比较简单。很容易理解,实现起来也相对容易。但是要注意数组情况的界限问题。
  • 后面将介绍队列,相比栈,队列内容更丰富一些。难度也稍大一些。
  • 如果有不好需要改进还请指出
  • 最后,喜欢的话可以关注公众号:bigsai 持续分享(回复 数据结构 获得精心准备资料一份!)

原文地址:https://www.cnblogs.com/bigsai/p/11357229.html

时间: 2024-11-02 02:43:24

数据结构与算法—栈的相关文章

数据结构与算法--栈、队列(队列)

Hello,everybody.我们又见面了.今天我们来学习一下队列这个数据结构,let's Go,开始我们的征程吧. 首先,举两个生活中的常见例子.相信大家,在用电脑工作娱乐时,都会碰到这样的现象.当我们点击程序或进行其他操作时,电脑处于死机状态.正当我们准备Reset时,它突然像打了鸡血似的,突然把刚才我们的操作,按顺序执行了一遍.之所以会出现这个现象,是因为操作系统的多个程序,需要通过一个管道输出,而按先后顺序排队造成的. 还有有个例子,在我们打客服热线时,有时会出现等待的现象.当其他客户

JavaScript数据结构和算法----栈

前言 栈是一种遵循后进先出(LIFO)原则的有序集合,新添加的或待删除的元素都保存在栈的末尾,称作栈顶,另外一端就叫栈底.在栈里,新元素都靠近栈顶,旧元素都接近栈底.可以想象桌上的一叠书,或者厨房里的堆放的盘子. 一.栈的创建 可以创建一个类来表示栈 //1.创建一种数据结构来保存栈里面的数据,这里选择数组 //2.声明一些栈的方法 // push(element(s)) : 添加一个或一些元素到栈顶 // pop() : 移除栈顶的元素,同时返回被移除的元素. // peek() : 返回栈顶

javascript数据结构与算法---栈

在上一遍博客介绍了下列表,列表是最简单的一种结构,但是如果要处理一些比较复杂的结构,列表显得太简陋了,所以我们需要某种和列表类似但是更复杂的数据结构---栈.栈是一种高效的数据结构,因为数据只能在栈顶添加或删除,所以这样操作很快,而且容易实现. 一:对栈的操作. 栈是一种特殊的列表,栈内的元素只能通过列表的一端访问,这一端陈为栈顶.比如餐馆里面洗盘子,只能先洗最上面的盘子,盘子洗完后,也只能螺到这一摞盘子的最上面.栈被称为 "后入先出"(LIFO)的数据结构. 由于栈具有后入先出的特点

javascript数据结构与算法——栈

前言: 栈就是和列表类似的一种数据结构,不过栈的特点是'后人先出'.栈是一种高效的数据结构,因为数据只能在栈顶添加或删除,所以这样操作很快,而且容易实现. 1. 栈的介绍: 栈是一种特殊的列表,栈内的元素只能通过列表的一端访问,这一端被称为栈顶,另一端称为栈底.比如饭店罗盘子,只能从最上面取盘子,盘子洗干净后,也只能罗在做上面.栈被称为一种先入后出的(LIFO)的数据结构. 示意图:

python数据结构与算法——栈

# 栈# 其实python里面的list就可以当栈使用啦,用collections.deque也可以# 1. 入栈 list.append(item)# 2. 出栈 item = list.pop()# 3. 对于首元素出栈,还可以 item = list.pop(0) 和队列概念一样# 4. 其实还可以任意元素出栈 item = list.pop(i) 相当于删除第i个元素# 注意3,4是很耗时间的 栈可以方便用来判断一个字符串是否回文,但是要在一个长字符串中找到最大的回文一般用的数据结构是后

15. C#数据结构与算法 -- 栈

这节我们讨论了两种好玩的数据结构,栈和队列. 什么是栈, 所谓的栈是栈(Stack)是操作限定在表的尾端进行的线性表.表尾由于要进行插入.删除等操作,所以,它具有特殊的含义,把表尾称为栈顶(Top) ,另一端是固定的,叫栈底(Bottom) .当栈中没有数据元素时叫空栈(Empty Stack).这个类似于送饭的饭盒子,上层放的是红烧肉,中层放的水煮鱼,下层放的鸡腿.你要把这些菜取出来,这就引出来了栈的特点先进后出(First in last out).   具体叙述,加下图: 栈通常记为:S=

数据结构与算法-栈和队列

一.简介 众所周知,线性表是数据结构的基础,通常有两种实现方式:数组和链表.栈和队列是最常用的数据结构,它们基于线性表实现. 二.栈 定义:栈是限定仅在表尾进行插入和删除操作的线性表,即FILO. 栈被经常类比于弹夹,即先被压如弹夹的子弹最后被打出.根据线性表的实现方式得知,栈的实现方式有两种:数组实现和链表实现. 栈的数组实现: package basic.data_structure.cha01; /** * 栈:先进后出(FILO),只允许在栈顶操作元素 * 栈的基本操作: * 初始化栈.

数据结构和算法-栈

栈可以分为 顺序栈: 数组实现 链式栈: 链表实现 空间复杂度 栈的空间复杂度: 有一个n个元素的栈, 在入栈和出栈过程中, 只需要存储一个临时变量存储空间, 所以空间复杂度是O(1) 并不是说栈有n个元素, 空间复杂度就是O(n), 而是指除了原本的空间外, 算法需要的额外空间 栈要满足后进先出(LIFO)的特性, 栈有以下几种方法 判断为空isEmpty 入栈push 出栈pop 返回栈顶元素peek 返回栈大小size 是否是空isEmpty 以下是使用列表来模拟栈的操作 # coding

Java数据结构与算法-栈和队列

(摘录加总结)------ 栈和队列不属于基础的数据结构,它们都属于线性表. 一.栈 对于栈存储操作元素只能在栈结构的一端进行元素的插入和删除,是一种性质上的线性表结构.按照“先进后出”的原则进行存储数据.先进的元素在栈底,后进的元素在栈顶.需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来).比较常规的说明是:栈底固定,而栈顶浮动:栈中元素个数为零时称为空栈.插入一般称为进栈(PUSH),删除则称为退栈(POP). 栈的实现结构包括顺序结构实现和链式结构实现.前者依据的是数组,后者