栈定义

栈(stack):是一种特殊的串行形式的数据结构,其特殊之处在于只允许在链接串行或者阵列的

一端进行插入、删除操作。其实现方式可以通过一维阵列和链接串行来实现。

Tips:简单的来说栈其实也是一种操作受限的线性表。是一种后进先出的数据结构可以使用数

组或者链表的形式来实现。

栈的操作表现形式:

栈实现

知道了栈的定义,我们来看看栈的实现吧。首先我们需要明白的的是栈具有哪些操作。

通过一个接口定义其操作。

  1. package com.kiritor;
  2. /**
  3. * 栈操作定义
  4. * @author Kiritor*/
  5. public interface Stack<T> {
  6. /*判空*/
  7. boolean isEmpty();
  8. /*清空栈*/
  9. void clear();
  10. /*弹栈*/
  11. T pop();
  12. /*入栈*/
  13. boolean push(T data);
  14. /*栈的长度*/
  15. int length();
  16. /*查看栈顶的元素,但不移除它*/
  17. T peek();
  18. /*返回对象在栈中的位置*/
  19. int search(T t);
  20. }

栈的数组实现

栈的数组实现,底层使用数组

  1. package com.kiritor;
  2. /**
  3. * 栈的数组实现
  4. * @author Kiritor*/
  5. public class ArrayStack<T> implements Stack<T>{
  6. private T[] t = (T[]) new Object[16];//栈空间默认为16
  7. private int size = 0;
  8. @Override
  9. public boolean isEmpty() {
  10. return size==0;
  11. }
  12. @Override
  13. public void clear() {
  14. for(int i = 0;i<t.length;i++)
  15. t[i]=null;//将其引用只为null,方便gc进行回收
  16. size = 0;//栈的大小置0
  17. }
  18. /*弹栈操作*/
  19. @Override
  20. public T pop() {
  21. if(size==0)
  22. return null;
  23. else
  24. {
  25. T tmp = t[size-1];
  26. t[size-1]=null;//便于gc回收
  27. size--;
  28. return tmp;
  29. }
  30. }
  31. @Override
  32. public boolean push(T data) {
  33. if(size>=t.length)
  34. {
  35. //栈空间已满,需要扩容
  36. resize();
  37. }
  38. t[size++]=data;
  39. return true;
  40. }
  41. public void resize()
  42. {
  43. T[] tmp = (T[]) new Object[t.length*2];
  44. for(int i = 0;i<t.length;i++){
  45. tmp[i]=t[i];
  46. t[i]=null;//便于gc处理
  47. }
  48. t = tmp;
  49. tmp = null;//便于gc处理,提高程序效率
  50. }
  51. @Override
  52. public int length() {
  53. return size;
  54. }
  55. /*查看栈顶元素,但是并不删除*/
  56. @Override
  57. public T peek() {
  58. if(size==0)
  59. return null;
  60. else
  61. {
  62. return t[size-1];
  63. }
  64. }
  65. /*下表从1开始*/
  66. @Override
  67. public int search(T t) {
  68. for(int i= 0;i<size;i++)
  69. if(t.equals(this.t[i]))
  70. return i+1;
  71. return 0;
  72. }
  73. @Override
  74. public String toString() {
  75. StringBuilder sb = new StringBuilder();
  76. sb.append("ArrayStack:\n[\n");
  77. for (int i = size-1; i >=0; i--) {
  78. sb.append("   "+t[i].toString());
  79. if (i != size + 1) {
  80. sb.append("\n");
  81. }
  82. }
  83. sb.append("]");
  84. return sb.toString();
  85. }
  86. }

测试代码:

  1. public static void main(String[] args) {
  2. ArrayStack<String> arrayStack = new ArrayStack<>();
  3. arrayStack.push("C语言");
  4. arrayStack.push("C++");
  5. arrayStack.push("JAVA");
  6. arrayStack.push("数据结构");
  7. arrayStack.pop();
  8. arrayStack.peek();
  9. arrayStack.pop();
  10. System.out.println(arrayStack.toString());
  11. }

输出结果:

栈的链表实现

  1. package com.kiritor;
  2. /**
  3. * 栈的链表实现
  4. * @author Kiritor*/
  5. public class LinkStack<T> implements Stack<T>{
  6. /*将数据封装成结点*/
  7. class Node
  8. {
  9. private Node pre;
  10. private T data;
  11. }
  12. /*栈顶指针*/
  13. private Node top;
  14. private int size;//栈的大小
  15. public LinkStack() {
  16. this.top = null;
  17. this.size = 0;
  18. }
  19. @Override
  20. public boolean isEmpty() {
  21. return size==0;
  22. }
  23. @Override
  24. public void clear() {
  25. top = null;
  26. size = 0;
  27. }
  28. @Override
  29. public T pop() {
  30. if (top != null) {
  31. T t = top.data;
  32. // 改变栈顶指针
  33. top = top.pre;
  34. size--;
  35. return t;
  36. }
  37. return null;
  38. }
  39. @Override
  40. public boolean push(T data) {
  41. Node node = new Node();
  42. node.data = data;
  43. node.pre = top;
  44. // 改变栈顶指针
  45. top = node;
  46. size++;
  47. return true;
  48. }
  49. @Override
  50. public int length() {
  51. return size;
  52. }
  53. @Override
  54. public T peek() {
  55. return top.data;
  56. }
  57. /*下表从1开始*/
  58. @Override
  59. public int search(T t) {
  60. int count=0;
  61. for(Node node= top;node.pre!=null;node = node.pre)
  62. {
  63. count++;
  64. if(t.equals(node.data))
  65. return size - count;
  66. }
  67. return 0;
  68. }
  69. @Override
  70. public String toString() {
  71. StringBuilder sb = new StringBuilder();
  72. sb.append("LinkStack:"+length()+"\n[\n");
  73. int count=0;
  74. for (Node node = top;node!=null;node=node.pre) {
  75. count++;
  76. sb.append("   "+node.data.toString());
  77. if (count != size + 1) {
  78. sb.append("\n");
  79. }
  80. }
  81. sb.append("]");
  82. System.out.println(count);
  83. return sb.toString();
  84. }
  85. }

测试代码:

  1. public static void main(String[] args) {
  2. LinkStack<String> arrayStack = new LinkStack<>();
  3. arrayStack.push("C语言");
  4. arrayStack.push("C++");
  5. arrayStack.push("JAVA");
  6. arrayStack.push("数据结构");
  7. System.out.println(arrayStack.toString());
  8. }

结果就不贴出了
                       因为栈操作的特殊性,一般来说以数组方式实现的栈的效率是要高于链表实现的,

原因在于:其一数组的访问更快。其二由于只在栈顶进行操作并未涉及太大的元素移动

但是使用链式实现将数据包装成Node,在从其中取数据,还的维护栈顶指针和前驱指针。

栈的实现(JAVA)的更多相关文章

  1. Java 堆内存与栈内存异同(Java Heap Memory vs Stack Memory Difference)

    --reference Java Heap Memory vs Stack Memory Difference 在数据结构中,堆和栈可以说是两种最基础的数据结构,而Java中的栈内存空间和堆内存空间有 ...

  2. 栈的实现Java

    package practice; import java.util.Iterator; //栈 public class MyStack<T> implements Iterable&l ...

  3. 剑指offer【05】- 用两个栈实现队列(java)

    题目:用两个栈实现队列 考点:栈和队列 题目描述:用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 解题思路:每次psuh是时先将stack2清空放入stck1(保 ...

  4. 栈的实现——java

    和C++一样,JDK包中也提供了"栈"的实现,它就是集合框架中的Stack类.关于Stack类的原理,在"Java 集合系列07之 Stack详细介绍(源码解析)和使用示 ...

  5. 数组、栈、堆(java基础知识五)

    1.数组概述.定义格式 * A:数组概念 数组是存储同一种数据类型多个元素的集合.也可以看成是一个容器. 数组既可以存储基本数据类型,也可以存储引用数据类型. * B:数组定义格式 格式1:数据类型[ ...

  6. java虚拟机栈(关于java虚拟机内存的那些事)

    <深入理解 java 虚拟机> 读书扩展 作者:淮左白衣 写于 2018年4月13日16:26:51 目录 文章目录 java虚拟机栈是什么 特点 栈帧 局部变量表 什么时候抛出 `Sta ...

  7. 05.用两个栈实现队列 Java

    题目描述 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 思路 进栈: 直接进stack1 出栈: 若stack2不为空,则出栈. 否则,当stack1不为空时, ...

  8. (超详细)动手编写 — 栈、队列 ( Java实现 )

    目录 前言 栈 概念 栈的设计 编码实现 小结 队列 概念 队列的设计 编码实现 双端队列 概念 设计 编码 循环队列 循环队列 循环双端队列 声明 前言 栈 概念 什么是栈? **栈 **:是一种特 ...

  9. 数据结构之链表、栈和队列 java代码实现

    定义抽象节点类Node: package cn.wzbrilliant.datastructure; /** * 节点 * @author ice * */ public abstract class ...

随机推荐

  1. 在office 2010中插入Mathtype出现ctrl+v不能复制的问题

    加载项中去掉command for那个即可 详细网址:http://heblue.blog.163.com/blog/static/96325568201375102628405/

  2. apparmor介绍

    AppArmor AppArmor 类似于selinux ,主要的作用是设置某个可执行程序的访问控制权限,主要区别就在于apparmor是以路径(path)为基础,而selinux以i节点(inode ...

  3. asp:DateDiff 函数

    DateDiff 函数 返回 Variant (Long) 的值,表示两个指定日期间的时间间隔数目. 语法 DateDiff(interval, date1, date2[, firstdayofwe ...

  4. IOS开发之KVC与KVO简述

    KVC:Key-Value Coding KVO:Key-Value Observing Person.m #import <Foundation/Foundation.h> @inter ...

  5. win8.1企业版更新到win10解决方案

    最近想把自己的win8.1更新成win10,发现月底就要免费更新了,由于我的电脑是企业版,官方不提供企业版的免费升级,所以用电脑管家或者360老是提示不对.我就百度了在注册表里面改成了专业版的,接着继 ...

  6. bzoj1697:[Usaco2007 Feb]Cow Sorting牛排序 & bzoj1119:[POI2009]SLO

    思路:以bzoj1119为例,题目已经给出了置换,而每一次交换的代价是交换二者的权值之和,而置换一定是会产生一些环的,这样就可以只用环内某一个元素去置换而使得其余所有元素均在正确的位置上,显然要选择环 ...

  7. mongodb 安装及,设置账户、主从

    我原来没用过mongodb ,在晚上查了查需要的命令,关于怎么mongodb怎么用,我就不知道了 官方网站: http://www.mongodb.org/ MongoDB 安裝,主从配置一 Mong ...

  8. ECMAScript一元操作符

    在ECMAScript中提供了一元操作符进行简单的运算,一元操作符是ECMAScript中最简单的操作符,它只能对一个值进行操作. 一元操作符有两种类型,一种是递增和递减操作符,一种是一元加和一元减操 ...

  9. nodejs -mysql模块链接数据库创建库创建表单。

    var mysql = require('mysql'); var connection= mysql.createConnection({ host:'localhost', user:'root' ...

  10. C# Thread多线程学习

    自我学习理解:一个程序中包括多个进程,每个进程包括多个线程,多个线程可同时做不同的事情(说是同时,但它是交换执行的,人感觉像是同时罢了). 优点:提高CPU的使用率. 线程同步:同步就是指一个线程要等 ...