数据结构(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开始连续存放栈内元素,栈空时,top为0
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. 初始化链栈:为链栈申请一个链栈节点top,top的数据元素和next均为null,链栈的长度size为0
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的矩阵,入口在(1,1),出口在(8,8),假设搜索方向为沿正东顺时针搜索,用0,1,2,3表示,方向分别为(0,1)、(1,0)、(0,-1)、(-1,0)。
搜索方式为:首先将入口(1,1)压进栈,表示移动到入口,并将入口的值设为-1,然后按照0,1,2,3方向搜索下一个点,若搜索到下一个点的值为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开始连续存放栈内元素,栈空时,top为0
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. 初始化链栈:为链栈申请一个链栈节点top,top的数据元素和next均为null,链栈的长度size为0
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的矩阵,入口在(1,1),出口在(8,8),假设搜索方向为沿正东顺时针搜索,用0,1,2,3表示,方向分别为(0,1)、(1,0)、(0,-1)、(-1,0)。
搜索方式为:首先将入口(1,1)压进栈,表示移动到入口,并将入口的值设为-1,然后按照0,1,2,3方向搜索下一个点,若搜索到下一个点的值为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)之栈的主要内容,如果未能解决你的问题,请参考以下文章