从数据结构的角度来看,其实栈也是线性表。特殊性在于栈和队列的基本操作是线性表操作的子集,栈是操作受限制的线性表。

栈的定义

栈是限定仅在表尾进行插入或者删除操作的线性表。对于一个栈来说,表尾端有着特殊的含义,称为栈顶,表头端称为栈底,不含元素的空表称之为空栈,栈又称为后进先出的线性表,简称 LIFO(Last In First Out)结构。也就是说后存放的先取,先存放的后取,这就类似于我们要在取放在箱子底部的东西(放进去比较早的物体),我们首先要移开压在它上面的物体(放进去比较晚的物体)。

和线性表类似,栈已有两种存储表示方法,分别称之为顺序栈和链栈。

顺序栈的实现:

顺序栈是指利用顺序存储结构实现的栈,即利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素,同时附设top指示栈顶元素在顺序栈中的位置。

实现栈功能的泛型类:

package 顺序栈;

import java.lang.reflect.Array;
import java.util.Arrays; public abstract class OrderStack<T> { private int maxSize;
protected T arr[];
private int top; public OrderStack(Class<T> componentType) {
this.maxSize = 1024;
this.arr = (T[]) Array.newInstance(componentType, this.maxSize);
this.top = 0;
} public OrderStack(Class<T> componentType, int maxSize) {
this.maxSize = maxSize;
} public int getSize() {
return top;
} public int getMaxSize() {
return maxSize;
} public void expandMaxSize(int maxSize) {
Arrays.copyOf(arr, this.maxSize + maxSize);
this.maxSize += maxSize;
} public void push(T data) {
if(this.top > this.maxSize) {
throw new IllegalArgumentException("new element will be out of limits.");
}
arr[this.top] = data;
this.top++;
} public T pop() {
if(this.top == 0) {
throw new IllegalArgumentException("this stack is already empty");
}
this.top--;
return arr[this.top];
} public T peek() {
if(this.top == 0) {
throw new IllegalArgumentException("this stack is already empty");
}
return arr[this.top - 1];
} public boolean isEmpty() {
return this.top == 0 ? true : false;
} public boolean isFull() {
return this.top == this.maxSize ? true : false;
} }

Integer实现类:

package 顺序栈;

public class IntegerStack extends OrderStack<Integer> {

	public IntegerStack() {
super(Integer.class);
// TODO Auto-generated constructor stub
} public IntegerStack(int maxSize) {
super(Integer.class, maxSize);
} public void print() {
System.out.println("top");
System.out.println("------");
for (int i = this.getSize() - 1; i >= 0; i--) {
System.out.println(arr[i]);
}
System.out.println("------");
System.out.println("bottom");
} }

测试类:

package 顺序栈;

public class IntegerStackDemo {

	public static void main(String[] args) {
IntegerStack test = new IntegerStack();
System.out.println("size is: " + test.getSize());
System.out.println("is empty: " + test.isEmpty());
test.print(); System.out.println("==============="); test.push(2);
test.push(5);
test.push(7);
test.push(8); System.out.println("size is: " + test.getSize());
System.out.println("is empty: " + test.isEmpty());
test.print(); System.out.println("================"); System.out.println("first element is: " + test.peek());
test.pop();
System.out.println("first element is: " + test.peek());
System.out.println("size is: " + test.getSize());
test.print(); System.out.println("================");
}
}

链栈的实现

链栈是采用链式存储结构实现的栈,通常链栈采用单链表来实现,由于栈的主要操作是在栈顶进行插入和删除,所以以链表的头部作为栈顶最为方便,且没必要向单链表那样为了操作方便而加一个头结点

链栈类代码:

package 链栈;

public class LinkStack {

	private Element top;
private Element base; class Element {
public Object data;
public Element next; public Element() {
this.data = null;
this.next = null;
} public Element(Object data, Element next) {
this.data = data;
this.next = next;
}
} public void initStack() {
top = new Element();
base = new Element();
top.next = base;
} public void push(Object e) {
Element ele = new Element(e, null);
ele.next = top.next;
top.next = ele;
} public void pop() {
if(top.next == base) {
System.out.println("栈中没有元素");
}
else {
Element e = top.next;
System.out.println("出栈操作:" + e.data);
top.next = top.next.next;
e = null;
}
} public Object getTop() {
if(top.next == base) System.out.println("栈中没有元素");
return top.next.data;
} public boolean isEmpty() {
return top.next == base ? true : false;
} public void printStack() {
System.out.println("打印栈");
Element ele = top;
while(ele.next != base) {
System.out.println(ele.next.data);
ele = ele.next;
}
} }

链栈测试类代码:

package 链栈;

public class LinkStackDemo {

	public static void main(String[] args) {
LinkStack lStack = new LinkStack();
lStack.initStack();
lStack.pop();
lStack.push(1);
lStack.push(2);
lStack.push(3);
lStack.push(4);
lStack.printStack(); lStack.pop();
lStack.pop();
lStack.printStack(); lStack.pop();
lStack.pop();
lStack.printStack();
lStack.pop();
}
}

栈与递归(栈的应用)

所谓递归就是在一个函数、过程或者数据结构定义的内部又出现定义本身的应用,那么我们称它们是递归的或者是递归定义的。

递归的基本思想就是将一个较大的问题分解为若干个规模较小解法相同或相似的问题去解决,每一个较小的问题又可以分解成规模更小的子问题去解决。可以说,递归问题的解决就是多个有依赖关系问题的解决。

函数的广义递归和狭义递归

从函数调用的层次看,函数的调用关系就是一个广义递归的过程:

public class Test {

	void function_a() {
function_b();
} void function_b() {
function_c();
} void function_c() {
return;
}
}

函数a调用函数b,函数b中调用函数c,函数c返回,函数b返回,函数a返回,这种递归调用的并不是自身,所以成为广义递归。

相反的,这就是产生了狭义的“递归函数“,即函数内又调用函数自身。

递归过程与递归工作栈

一个递归函数,在函数的执行过程中,需要多次进行自我调用,在高级语言编制的程序中,调用函数和被调用函数之间的链接及信息交换需要通过栈来进行实现。

当程序执行到某个函数时,将这个函数进行入栈操作,在入栈之前,通常需要完成三件事。

  1、将所有的实参、返回地址等信息传递给被调函数保存。

  2、为被调函数的局部变量分配存储区。

  3、将控制转移到北调函数入口。

当一个函数完成之后会进行出栈操作,出栈之前同样要完成三件事。

  1、保存被调函数的计算结果。

  2、释放被调函数的数据区。

  3、依照被调函数保存的返回地址将控制转移到调用函数。

上述操作必须通过栈来实现,即将整个程序的运行空间安排在一个栈中。每当运行一个函数时,就在栈顶分配空间,函数退出后,释放这块空间。所以当前运行的函数一定在栈顶。

注:出自严蔚敏等人的数据结构c语言第二版

栈的理解和代码实现(java)的更多相关文章

  1. 栈和队列的面试题Java实现【重要】

    栈和队列: 面试的时候,栈和队列经常会成对出现来考察.本文包含栈和队列的如下考试内容: (1)栈的创建 (2)队列的创建 (3)两个栈实现一个队列 (4)两个队列实现一个栈 (5)设计含最小函数min ...

  2. 栈和队列的面试题Java

    栈和队列: 面试的时候,栈和队列经常会成对出现来考察.本文包含栈和队列的如下考试内容: (1)栈的创建 (2)队列的创建 (3)两个栈实现一个队列 (4)两个队列实现一个栈 (5)设计含最小函数min ...

  3. 栈和队列的面试题Java实现

    栈和队列: 面试的时候,栈和队列经常会成对出现来考察.本文包含栈和队列的如下考试内容: (1)栈的创建 (2)队列的创建 (3)两个栈实现一个队列 (4)两个队列实现一个栈 (5)设计含最小函数min ...

  4. Github即将破百万的PDF:编写高质量代码改善JAVA程序的151个建议

    在通往"Java技术殿堂"的路上,本书将为你指点迷津!内容全部由Java编码的最佳 实践组成,从语法.程序设计和架构.工具和框架.编码风格和编程思想等五大方面,对 Java程序员遇 ...

  5. 利用栈实现算术表达式求值(Java语言描述)

    利用栈实现算术表达式求值(Java语言描述) 算术表达式求值是栈的典型应用,自己写栈,实现Java栈算术表达式求值,涉及栈,编译原理方面的知识.声明:部分代码参考自茫茫大海的专栏. 链栈的实现: pa ...

  6. 堆&栈的理解(转)

    (摘自:http://www.cnblogs.com/likwo/archive/2010/12/20/1911026.html) C++中堆和栈的理解 内存分配方面: 堆: 操作系统有一个记录空闲内 ...

  7. 编写高质量代码:改善Java程序的151个建议 --[117~128]

    编写高质量代码:改善Java程序的151个建议 --[117~128] Thread 不推荐覆写start方法 先看下Thread源码: public synchronized void start( ...

  8. 编写高质量代码:改善Java程序的151个建议 --[106~117]

    编写高质量代码:改善Java程序的151个建议 --[106~117] 动态代理可以使代理模式更加灵活 interface Subject { // 定义一个方法 public void reques ...

  9. 编写高质量代码:改善Java程序的151个建议 --[52~64]

    编写高质量代码:改善Java程序的151个建议 --[52~64] 推荐使用String直接量赋值 Java为了避免在一个系统中大量产生String对象(为什么会大量产生,因为String字符串是程序 ...

随机推荐

  1. setitemdata 32位 or 64位

    我用SetItemData 和GetItemData把数据库一条数据导入到CListctrl 32位下 程序都可以跑 GetItemData能得到自定义类数据 可以64位得不到?

  2. windows平台使用spark-submit以client方式提交spark应用到standalone集群

    1.spark应用打包,我喜欢打带依赖的,这样省事. 2.使用spark-submit.bat 提交应用,代码如下: for /f "tokens=1,2 delims==" %% ...

  3. 机器学习—K近邻

    一.算法原理 还是图片格式~ 二.sklearn实现 import pandas as pd import numpy as np import matplotlib.pyplot as plt im ...

  4. Oracle电子商务套件版本12.1.3自述文件 (Doc ID 1534411.1)

    文档内容 用途 适用范围 详细信息   应用版本更新包   更新后的步骤   包含的修补程序列表   变更记录   文档可访问性 参考 适用于: Oracle Applications DBA - 版 ...

  5. linux 进程通信之 管道和FIFO

    进程间通信:IPC概念 IPC:Interprocess Communication,通过内核提供的缓冲区进行数据交换的机制. IPC通信的方式: pipe:管道(最简单) fifo:有名管道 mma ...

  6. linux下强行umount卸载设备

    卸载NFS,结果出现无法卸载的情况 umount /mnt/umount: /mnt: device is busy使用umount -f,问题依旧umount -f /mnt/umount2: De ...

  7. 经典的兔子生兔子问题(C#递归解法)

    古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 思路:先求出每个月新增的兔子,再用循环求和即可算出这个月 ...

  8. BitAdminCore框架更新日志20180524

    20180524更新内容 本次更新两个内容,一是增加windows service,二是增加邮件发送功能. windows service windows service用于定期跑服务,网上有一些提供 ...

  9. JgrId 无数据返回设置

    在addJSONData方法中 while (i < len) { 前增加以下代码 ) { rowData.push('<tr role="row" id=" ...

  10. cesium随笔 — 获取当前鼠标的经度、纬度、高度

    代码: function getPosition() { //得到当前三维场景 var scene = viewer.scene; //得到当前三维场景的椭球体 var ellipsoid = sce ...