数据结构(java)之栈

Posted hsiaolung

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构(java)之栈相关的知识,希望对你有一定的参考价值。

1.        栈的逻辑结构

a)       定义:只允许在表的一端进行插入和删除操作的线性表,只允许操作的一段称为栈顶,另一端称为栈尾

b)       特征:先进后出

c)        抽象数据类型

                     i.            数据元素:任意属于同一类的数据元素

                     i.            数据结构:线性关系,除第一个元素外,每个元素都有唯一的直接前驱元素,除最后一个元素外,每个元素都有唯一后继元素

                    ii.            数据操作:定义在IStack接口中,代码如下

publicinterface IStack <E>{

  E push(E e);

  E pop();

  E peek();

  int size();

  boolean empty();

}

2.        栈实现之线性栈

a)       顺序栈的存储结构:用一维数组从下标为1开始连续存放栈内元素,栈空时,top0

b)       顺序栈的基本操作

                     i.            初始化顺序栈:为栈申请存储大小为maxsize的空间用来存储连续的数据,并将栈顶top设置为0

                    ii.            入栈:入栈使top自增,并将入栈元素存储在自增后的top位置

                  iii.            出栈:出栈先返回下标为top的元素,并使top自减。

c)        代码实现

publicclass MySquenceStack <E>implements IStack<E> {

  private E[] data;

  privateinttop;

 

  public MySquenceStack(intmaxsize) {

     super();

     this.data=(E[])new Object[maxsize];

     this.top = 0;

  }

 

  @Override

  public E push(E e) {

     if(!this.isFull()) {

         this.top++;

         this.data[this.top]=e;

         returne;

     }

     returnnull;

  }

 

  @Override

  public E pop() {

     E e=this.data[this.top];

     this.top--;

     returne;

  }

 

  @Override

  public E peek() {

     if(!this.empty()) {

         E e=this.data[this.top];

         returne;

     }

     returnnull;

  }

 

  @Override

  publicint size() {

    

     returnthis.top;

  }

 

  @Override

  publicboolean empty() {

     if(this.top==0)

         returntrue;

     returnfalse;

  }

 

  publicboolean isFull() {

     if(this.top>=this.data.length-1)

         returntrue;

     returnfalse;

  }

}

3.        栈实现之链栈

a)       链栈的存储结构:链栈由一个个链栈节点组成,每个链栈节点包含数据和指向下一个节点的next元素,通过next将一个个节点连接起来

b)       链栈的基本操作

                     i.            初始化链栈:为链栈申请一个链栈节点toptop的数据元素和next均为null,链栈的长度size0

                    ii.            入栈:当栈为空栈时,将元素存储在top的数据元素中,当链栈不为空时,先申请一个链栈节点,将数据元素存储在链栈节点的数据元素中,将节点的next指向top节点,并将新申请的节点赋值给top

                  iii.            出栈:将链栈的top节点的next指向的节点赋值给top

c)        代码实现

class LSNode<E>{

  private E e;

  private LSNode<E> next;

  public LSNode(E e, LSNode<E> next) {

     super();

     this.e = e;

     this.next = next;

  }

  public E getE() {

     returne;

  }

  publicvoid setE(E e) {

     this.e = e;

  }

  public LSNode<E> getNext() {

     returnnext;

  }

  publicvoid setNext(LSNode<E> next) {

     this.next = next;

  }

 

}

 

publicclass MyLinkStack<E> implements IStack<E> {

  private LSNode<E> top;

  privateintsize;

 

  public MyLinkStack() {

     super();

     this.top= new LSNode<E>(null,null);

     this.size= 0;

  }

 

  @Override

  public E push(E e) {

     if(this.empty()) {

         this.top.setE(e);

         this.size++;

         returne;

     }

     LSNode <E> node=new LSNode(e, this.top);

     this.top=node;

     this.size++;

     returne;

  }

 

  @Override

  public E pop() {

     if(!this.empty()) {

         LSNode<E> temp=this.top;

         E e=this.top.getE();

         this.top=temp.getNext();

         this.size--;

         returne;

     }

     returnnull;

  }

 

  @Override

  public E peek() {

     returnthis.top.getE();

  }

 

  @Override

  publicint size() {

     returnthis.size;

  }

 

  @Override

  publicboolean empty() {

     if(this.size==0)

         returntrue;

     returnfalse;

  }

}

4.        应用:迷宫

假设一个迷宫如下,其中0表示障碍,1表示通路,入口为左上角,出口为右下角

      

1

1

0

1

1

1

0

1

1

1

0

1

1

1

0

1

1

1

1

1

0

0

1

1

1

0

0

0

1

1

1

1

1

1

1

0

1

1

1

1

1

0

1

1

1

0

1

1

1

0

0

0

1

0

0

1

0

1

1

1

1

1

1

1

       为了简化问题,将迷宫最外圈都设为0,这样迷宫就成了10*10的矩阵,入口在(11),出口在(88),假设搜索方向为沿正东顺时针搜索,用0123表示,方向分别为(01)、(10)、(0-1)、(-10)。

       搜索方式为:首先将入口(11)压进栈,表示移动到入口,并将入口的值设为-1,然后按照0123方向搜索下一个点,若搜索到下一个点的值为1,则将下一个点压入栈并移动到下一个点,将下一个点设为-1,若是搜索该点的所以方向的下一个点的值都不为1,则将该点出栈,表示将点移动上上一个点,直到点移动到出口坐标表示找到路径,反之没找到。

代码实现:

publicclass MiGong {

  privateintmaze[][];

  private IStack<Point> stack;

  private Point[] move= {new Point(0,1),new Point(1,0),new Point(0,-1),new Point(-1,0)};

  privateintcol;

 

  //初始化迷宫,传入一个正方形迷宫和一个用来保存点的栈  

  public MiGong(int[][] maze, IStack<Point> stack) {

     super();

     this.col=maze.length+2;

     this.maze = newint[this.col][this.col]; //迷宫必须为正方形的

     for(inti=1;i<this.col-1;i++) {

         for(intj=1;j<this.col-1;j++) {

            this.maze[i][j]=maze[i-1][j-1];

         }

     }

     this.stack = stack;

  }

 

  //创建节点类

  publicclass Point{

     privateintx;

     privateinty;

     public Point(intx, inty) {

         super();

         this.x = x;

         this.y = y;

     }

      publicint getX() {

         returnx;

     }

     publicvoid setX(intx) {

         this.x = x;

     }

     publicint getY() {

         returny;

     }

     publicvoid setY(inty) {

         this.y = y;

     }

     @Override

     public String toString() {

         return"("+x+","+y+")";

     }  

  }

 

  //寻找路径    

  publicboolean findPath() {

     intx,y,i,j;

     Point temp=new Point(1, 1);

     stack.push(temp);

     while(!stack.empty()) {

         intd=0;

         booleanflag=false;

         x=temp.getX();

         y=temp.getY();

         if(x==this.col-2&&y==this.col-2)

            returntrue;

         this.maze[x][y]=-1;

         while(d<4) {

            i=x+move[d].getX();

            j=y+move[d].getY();

            if(this.maze[i][j]==1) {

                flag=true;

                temp=new Point(i,j);

                break;

            }

            d++;

         }

         if(flag) {

            stack.push(temp);

         }

         else {

            stack.pop();

            temp=stack.peek();

         }

     }

     returnfalse;

  }

 

  //返回路径

  public Point[] getPath() {

     if (this.findPath()) {

         Point[] point=new Point[this.stack.size()];

         for(inti=point.length-1;i>=0;i--) {

            point[i]=this.stack.pop();

         }

         returnpoint;

     }

     returnnull;

  }

 

  //返回迷宫

  publicint[][] getMaze() {

     returnthis.maze;

  }

 

  //返回迷宫的边长

  publicint getCol() {

     returncol;

  }

}

5.        Java类库的栈

 

a)       顺序栈:java.util.Stack

1.        栈的逻辑结构

a)       定义:只允许在表的一端进行插入和删除操作的线性表,只允许操作的一段称为栈顶,另一端称为栈尾

b)       特征:先进后出

c)        抽象数据类型

                     i.            数据元素:任意属于同一类的数据元素

                     i.            数据结构:线性关系,除第一个元素外,每个元素都有唯一的直接前驱元素,除最后一个元素外,每个元素都有唯一后继元素

                    ii.            数据操作:定义在IStack接口中,代码如下

publicinterface IStack <E>{

  E push(E e);

  E pop();

  E peek();

  int size();

  boolean empty();

}

2.        栈实现之线性栈

a)       顺序栈的存储结构:用一维数组从下标为1开始连续存放栈内元素,栈空时,top0

b)       顺序栈的基本操作

                     i.            初始化顺序栈:为栈申请存储大小为maxsize的空间用来存储连续的数据,并将栈顶top设置为0

                    ii.            入栈:入栈使top自增,并将入栈元素存储在自增后的top位置

                  iii.            出栈:出栈先返回下标为top的元素,并使top自减。

c)        代码实现

publicclass MySquenceStack <E>implements IStack<E> {

  private E[] data;

  privateinttop;

 

  public MySquenceStack(intmaxsize) {

     super();

     this.data=(E[])new Object[maxsize];

     this.top = 0;

  }

 

  @Override

  public E push(E e) {

     if(!this.isFull()) {

         this.top++;

         this.data[this.top]=e;

         returne;

     }

     returnnull;

  }

 

  @Override

  public E pop() {

     E e=this.data[this.top];

     this.top--;

     returne;

  }

 

  @Override

  public E peek() {

     if(!this.empty()) {

         E e=this.data[this.top];

         returne;

     }

     returnnull;

  }

 

  @Override

  publicint size() {

    

     returnthis.top;

  }

 

  @Override

  publicboolean empty() {

     if(this.top==0)

         returntrue;

     returnfalse;

  }

 

  publicboolean isFull() {

     if(this.top>=this.data.length-1)

         returntrue;

     returnfalse;

  }

}

3.        栈实现之链栈

a)       链栈的存储结构:链栈由一个个链栈节点组成,每个链栈节点包含数据和指向下一个节点的next元素,通过next将一个个节点连接起来

b)       链栈的基本操作

                     i.            初始化链栈:为链栈申请一个链栈节点toptop的数据元素和next均为null,链栈的长度size0

                    ii.            入栈:当栈为空栈时,将元素存储在top的数据元素中,当链栈不为空时,先申请一个链栈节点,将数据元素存储在链栈节点的数据元素中,将节点的next指向top节点,并将新申请的节点赋值给top

                  iii.            出栈:将链栈的top节点的next指向的节点赋值给top

c)        代码实现

class LSNode<E>{

  private E e;

  private LSNode<E> next;

  public LSNode(E e, LSNode<E> next) {

     super();

     this.e = e;

     this.next = next;

  }

  public E getE() {

     returne;

  }

  publicvoid setE(E e) {

     this.e = e;

  }

  public LSNode<E> getNext() {

     returnnext;

  }

  publicvoid setNext(LSNode<E> next) {

     this.next = next;

  }

 

}

 

publicclass MyLinkStack<E> implements IStack<E> {

  private LSNode<E> top;

  privateintsize;

 

  public MyLinkStack() {

     super();

     this.top= new LSNode<E>(null,null);

     this.size= 0;

  }

 

  @Override

  public E push(E e) {

     if(this.empty()) {

         this.top.setE(e);

         this.size++;

         returne;

     }

     LSNode <E> node=new LSNode(e, this.top);

     this.top=node;

     this.size++;

     returne;

  }

 

  @Override

  public E pop() {

     if(!this.empty()) {

         LSNode<E> temp=this.top;

         E e=this.top.getE();

         this.top=temp.getNext();

         this.size--;

         returne;

     }

     returnnull;

  }

 

  @Override

  public E peek() {

     returnthis.top.getE();

  }

 

  @Override

  publicint size() {

     returnthis.size;

  }

 

  @Override

  publicboolean empty() {

     if(this.size==0)

         returntrue;

     returnfalse;

  }

}

4.        应用:迷宫

假设一个迷宫如下,其中0表示障碍,1表示通路,入口为左上角,出口为右下角

      

1

1

0

1

1

1

0

1

1

1

0

1

1

1

0

1

1

1

1

1

0

0

1

1

1

0

0

0

1

1

1

1

1

1

1

0

1

1

1

1

1

0

1

1

1

0

1

1

1

0

0

0

1

0

0

1

0

1

1

1

1

1

1

1

       为了简化问题,将迷宫最外圈都设为0,这样迷宫就成了10*10的矩阵,入口在(11),出口在(88),假设搜索方向为沿正东顺时针搜索,用0123表示,方向分别为(01)、(10)、(0-1)、(-10)。

       搜索方式为:首先将入口(11)压进栈,表示移动到入口,并将入口的值设为-1,然后按照0123方向搜索下一个点,若搜索到下一个点的值为1,则将下一个点压入栈并移动到下一个点,将下一个点设为-1,若是搜索该点的所以方向的下一个点的值都不为1,则将该点出栈,表示将点移动上上一个点,直到点移动到出口坐标表示找到路径,反之没找到。

代码实现:

publicclass MiGong {

  privateintmaze[][];

  private IStack<Point> stack;

  private Point[] move= {new Point(0,1),new Point(1,0),new Point(0,-1),new Point(-1,0)};

  privateintcol;

 

  //初始化迷宫,传入一个正方形迷宫和一个用来保存点的栈  

  public MiGong(int[][] maze, IStack<Point> stack) {

     super();

     this.col=maze.length+2;

     this.maze = newint[this.col][this.col];//迷宫必须为正方形的

     for(inti=1;i<this.col-1;i++) {

         for(intj=1;j<this.col-1;j++) {

            this.maze[i][j]=maze[i-1][j-1];

         }

     }

     this.stack = stack;

  }

 

  //创建节点类

  publicclass Point{

     privateintx;

     privateinty;

     public Point(intx, inty) {

         super();

         this.x = x;

         this.y = y;

     }

      publicint getX() {

         returnx;

     }

     publicvoid setX(intx) {

         this.x = x;

     }

     publicint getY() {

         returny;

     }

     publicvoid setY(inty) {

         this.y = y;

     }

     @Override

     public String toString() {

         return"("+x+","+y+")";

     }  

  }

 

  //寻找路径    

  publicboolean findPath() {

     intx,y,i,j;

     Point temp=new Point(1, 1);

     stack.push(temp);

     while(!stack.empty()) {

         intd=0;

         booleanflag=false;

         x=temp.getX();

         y=temp.getY();

         if(x==this.col-2&&y==this.col-2)

            returntrue;

         this.maze[x][y]=-1;

         while(d<4) {

            i=x+move[d].getX();

            j=y+move[d].getY();

            if(this.maze[i][j]==1) {

                flag=true;

                temp=new Point(i,j);

                break;

            }

            d++;

         }

         if(flag) {

            stack.push(temp);

         }

         else {

            stack.pop();

            temp=stack.peek();

         }

     }

     returnfalse;

  }

 

  //返回路径

  public Point[] getPath() {

     if (this.findPath()) {

         Point[] point=new Point[this.stack.size()];

         for(inti=point.length-1;i>=0;i--) {

            point[i]=this.stack.pop();

         }

         returnpoint;

     }

     returnnull;

  }

 

  //返回迷宫

  publicint[][] getMaze() {

     returnthis.maze;

  }

 

  //返回迷宫的边长

  publicint getCol() {

     returncol;

  }

}

5.        Java类库的栈

a)       顺序栈:java.util.Stack

 

以上是关于数据结构(java)之栈的主要内容,如果未能解决你的问题,请参考以下文章

数据结构(java)之栈

Java 大话数据结构 线性表之栈

数据结构之栈和队列及其Java实现

JAVA 数据结构之栈实现

java数据结构与算法之栈(Stack)设计与实现

JAVA数据结构与算法之栈~ 中缀表达式转换为后缀表达式