本文根据《大话数据结构》一书,实现了Java版的栈的顺序存储结构、两栈共享空间、栈的链式存储机构

:限定仅在表尾进行插入和删除操作的线性表。

栈的插入(进栈)和删除(出栈)操作如下图所示。

  

 

1.栈的顺序存储结构

  用数组存放数据,top变量来指示栈顶元素在数组中的位置(栈顶指针)。一个长度为5的栈的示意图如下:

  实现程序:

/**
* 栈的顺序储存结构
*
* 问题:构造器中,泛型数组创建是否有更好的方法?
* @author Yongh
*
*/
public class SqStack<E> {
private E[] data;
private int top; //栈顶指针,top=-1时为空栈
private int maxSize;
private static final int DEFAULT_SIZE= 10; public SqStack() {
this(DEFAULT_SIZE);
}
public SqStack(int maxSize) {
//无法创建泛型数组 data=new E[maxSize];
data=(E[]) new Object[maxSize];
top=-1;
this.maxSize=maxSize;
} public void push(E e) {
if(top==maxSize-1)
throw new RuntimeException("栈已满,无法进栈!");
top++;
data[top]=e;
} public E pop() {
if(top==-1)
throw new RuntimeException("空栈,无法出栈!");
E e=data[top];
top--;
return e;
} public void printStack() {
if(top==-1) {
System.out.println("空栈");
}else {
for(int i=0;i<=top;i++) {
System.out.println(data[i]);
}
}
}
}

  

  测试代码:

public class StackTest {
public static void main(String[] args) {
SqStack<Student> sqStack=new SqStack<Student>();
Student[] students= {new Student("小A",11),new Student("小B",12),new Student("小C",13),
new Student("小D",14),new Student("小E",151)};
for(int i=0;i<5;i++) {
sqStack.push(students[i]);
}
sqStack.printStack();
for(int i=0;i<5;i++) {
sqStack.pop();
}
sqStack.printStack();
}
} class Student{
public Student(String name, int age) {
this.name=name;
this.age=age;
}
String name;
int age;
public String toString() {
return name;
}
}

  

小A
小B
小C
小D
小E
空栈

StackTest

2.两栈共享空间

  通过一个数组存放两个栈,能较好地利用空间。用top1和top2变量表示栈1和栈2的栈顶指针,两个栈的栈底分别位于数组的头部和尾部。

  实现程序(在SqStack程序的基础上稍加改造即可):

/**
* 栈的顺序储存结构(两栈共享空间)
*
* 注意点:栈满条件为top1+1==top2
*
* @author Yongh
*
*/
public class SqDoubleStack<E> {
private E[] data;
private int top1; //栈1栈顶指针,top=-1时为空栈
private int top2; //栈2栈顶指针,top=maxSize-1时为空栈
private int maxSize;
private static final int DEFAULT_SIZE= 10; public SqDoubleStack() {
this(DEFAULT_SIZE);
}
public SqDoubleStack(int maxSize) {
//无法创建泛型数组 data=new E[maxSize];
data=(E[]) new Object[maxSize];
top1=-1;
top2=maxSize-1;
this.maxSize=maxSize;
} /*
* 进栈操作,stackNumber代表要进的栈号
*/
public void push(int stackNumber,E e) {
if(top1+1==top2)
throw new RuntimeException("栈已满,无法进栈!");
if(stackNumber==1) {
data[++top1]=e;
}else if(stackNumber==2) {
data[--top2]=e;
}else {
throw new RuntimeException("栈号错误!");
} } /*
* 出栈操作
*/
public E pop(int stackNumber) {
E e;
if(stackNumber==1){
if(top1==-1)
throw new RuntimeException("空栈1,无法出栈!");
e=data[top1--];
}else if(stackNumber==2) {
if(top2==maxSize-1)
throw new RuntimeException("空栈2,无法出栈!");
e=data[top2++];
}else {
throw new RuntimeException("栈号错误!");
}
return e;
}
}

  

3.栈的链式存储结构

  通过单向链表实现的栈,栈顶放在单链表的头部(注意进栈操作并不是往链表的后面插入,而是从头部插入)。

  链栈的示意图如下。

  插入与删除操作示意图:

  

  实现程序:

/**
*
* 栈的链式存储结构
*
* @author Yongh
*/
public class LinkStack<E> {
private StackNode<E> top;
private int count; private class StackNode<E>{
E data;
StackNode<E> next;
public StackNode(E data,StackNode<E> next) {
this.data=data;
this.next=next;
}
} public LinkStack() {
top=new StackNode<E>(null, null);
count=0;
} public void push(E e) {
StackNode<E> node=new StackNode<E>(e, top);
top=node;
count++;
} public E pop() {
if(count==0)
throw new RuntimeException("空栈,无法出栈!");
StackNode<E> node;
node=top;
top=top.next;
count--;
E e=node.data;
node=null;
return e;
} public void printStack() {
if(count==0) {
System.out.println("空栈");
}else {
StackNode<E> node=top;
for(int i=0;i<count;i++) {
System.out.println(node.data);
node=node.next;
}
}
} /*
* 测试代码
*/
public static void main(String[] args) {
LinkStack<Student> linkStack=new LinkStack<Student>();
Student[] students= {new Student("小A",11),new Student("小B",12),new Student("小C",13),
new Student("小D",14),new Student("小E",151)};
for(int i=0;i<5;i++) {
linkStack.push(students[i]);
}
linkStack.printStack();
System.out.println("----");
for(int i=0;i<5;i++) {
System.out.println(linkStack.pop());
}
linkStack.printStack();
}
}

  

小E
小D
小C
小B
小A
----
小E
小D
小C
小B
小A
空栈

LinkStack

 4.栈的应用

  (1)实现递归

    一些问题(如斐波那契数列的求解),可通过递归函数获得,而递归函数是由栈来实现的。

典型的斐波那契数列

  (2)四则运算表达式求值

    利用后缀表达式(逆波兰表示法)结合栈可以实现四则运算表达式的求解。而且通过栈,就可以把我们平时用的中缀表达式转化为后缀表达式。    

【Java】 大话数据结构(6) 栈的顺序与链式存储的更多相关文章

  1. 栈的顺序存储和链式存储c语言实现

    一. 栈 栈的定义:栈是只允许在一端进行插入或删除操作的线性表. 1.栈的顺序存储 栈顶指针:S.top,初始设为-1 栈顶元素:S.data[S.top] 进栈操作:栈不满时,栈顶指针先加1,再到栈 ...

  2. c数据结构 -- 线性表之 复杂的链式存储结构

    复杂的链式存储结构 循环链表 定义:是一种头尾相接的链表(即表中最后一个结点的指针域指向头结点,整个链表形成一个环) 优点:从表中任一节点出发均可找到表中其他结点 注意:涉及遍历操作时,终止条件是判断 ...

  3. [置顶] ※数据结构※→☆线性表结构(queue)☆============优先队列 链式存储结构(queue priority list)(十二)

    优先队列(priority queue) 普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除.在优先队列中,元素被赋予优先级.当访问元素时,具有最高优先级的元素最先删除.优先队列具有 ...

  4. java资料——顺序存储结构和链式存储结构(转)

    顺序存储结构 主要优点 节省存储空间,随机存取表中元素 缺    点 插入和删除操作需要移动元素 在计算机中用一组地址连续的存储单元依次存储线性表的各个数据元素,称作线性表的顺序存储结构. 顺序存储结 ...

  5. 数据结构----线性表顺序和链式结构的使用(c)

    PS:在学习数据结构之前,我相信很多博友也都学习过一些语言,比如说java,c语言,c++,web等,我们之前用的一些方法大都是封装好的,就java而言,里面使用了大量的封装好的方法,一些算法也大都写 ...

  6. C语言- 基础数据结构和算法 - 栈的链式存储

    听黑马程序员教程<基础数据结构和算法 (C版本)>, 照着老师所讲抄的, 视频地址https://www.bilibili.com/video/BV1vE411f7Jh?p=1 喜欢的朋友 ...

  7. javascript实现数据结构:线性表--线性链表(链式存储结构)

    上一节中, 线性表的顺序存储结构的特点是逻辑关系上相邻的两个元素在物理位置上也相邻,因此可以随机存取表中任一元素,它的存储位置可用一个简单,直观的公式来表示.然后,另一方面来看,这个特点也造成这种存储 ...

  8. Java实现链式存储的二叉树

    二叉树的定义: 二叉树(BinaryTree)是n(n≥0)个结点的有限集,它或者是空集(n=0),或者由一个根结点及两棵互不相交的.分别称作这个根的左子树和右子树的二叉树组成. 二叉树的遍历方式主要 ...

  9. C++编程练习(4)----“实现简单的栈的链式存储结构“

    如果栈的使用过程中元素数目变化不可预测,有时很小,有时很大,则最好使用链栈:反之,如果它的变化在可控范围内,使用顺序栈会好一些. 简单的栈的链式存储结构代码如下: /*LinkStack.h*/ #i ...

随机推荐

  1. 【BZOJ4444】国旗计划

    Description 题目链接 Solution 磕了3个半小时没做出来的题,就是全场崩. 首先对于一个人的答案是很好求的,显然是选择左端点在此人区间中,右端点最远(最靠右)的人作为下一个接棒人.因 ...

  2. Java实现的一个简单的模板渲染

    代码 package com.hdwang; import java.util.HashMap; import java.util.Map; /** * Created by hdwang on 20 ...

  3. 解题:SHOI2001 化工厂装箱员

    题面 题外话:从零开始的DP学习系列之壹(我真的不是在装弱,我DP真的就这么烂TAT) 从lyd那里学到了一点DP的小技巧,在设状态时可以先假装自己在做搜索,往一个函数里传了一些参数,然后把这些参数抓 ...

  4. eclipse java build path问题汇总

    背景:在项目开发过程中,很多应用都进行了模块划分,有的时候是jar包依赖,有的时候通过build path进行配置,搞清楚这部分有助于理解项目之间的关系. 1 tms项目开发 1.1 问题描述 项目结 ...

  5. 关于ehcache配置中timeToLiveSeconds和timeToIdleSeconds的区别

    在使用ehcache框架时,timeToLiveSeconds和timeToIdleSeconds这两个属性容易混淆,今天有空就记录一下,以防之后又忘记了. 首先来说明一下这两个属性分别有什么作用:( ...

  6. Openstack运维指南文档整理

    非常全面的运维指南整理http://zjzone.cc/index.php/2017/07/31/openstack-yun-wei-wen-dang-zheng-li/

  7. linux man命令

    http://note.youdao.com/noteshare?id=98878258c6453f92117355deba8b8439

  8. linux c 编程 ------ 串口编程

    http://blog.csdn.net/specialshoot/article/details/50707965 对于串口的打开操作,必须使用O_NOCTTY参数.O_NOCTTY如果路径名指向终 ...

  9. java基础基础总结----- Date

    前言:其实在学习这个的时候,自我感觉学到什么直接查询API就可以了,没有必要再去研究某个方法怎么使用, 重点学习一下经常用到的方法.感觉自己的写的博客,就跟自己的笔记一样,用的是时候,就能快速的查找 ...

  10. Hadoop基础-MapReduce的工作原理第二弹

    Hadoop基础-MapReduce的工作原理第二弹 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Split(切片)  1>.MapReduce处理的单位(切片) 想必 ...