(摘录加总结)------

栈和队列不属于基础的数据结构,它们都属于线性表。

一、栈

对于栈存储操作元素只能在栈结构的一端进行元素的插入和删除,是一种性质上的线性表结构。按照“先进后出”的原则进行存储数据。先进的元素在栈底,后进的元素在栈顶。需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)。比较常规的说明是:栈底固定,而栈顶浮动;栈中元素个数为零时称为空栈。插入一般称为进栈(PUSH),删除则称为退栈(POP)。

栈的实现结构包括顺序结构实现和链式结构实现。前者依据的是数组,后者是链表。

(1)利用数组实现栈

下面这个是一个基本的实现:①在Stack底层设置了一个int数组,当然可以使用泛型来指代不同的数据类型。最大容量和栈顶位置。特别需要注意的是在初始化时也看出来,一般在初始化的时候top位置设置为-1,这是利于后面在压入数据的时候数组的第一位是array[0],并且maxSize最大容量和数组的length是一致的。②top表示这个数组的当前的没有被设置元素的第一个位置的标志位是多少,首先要判断是否小于maxSize-1,因为是从-1开始的,并且每次判断都是++top,是先自增的处理,示意如下,假如初始化了一个容量为3的数组:

③当压栈完成的时候自然top的索引值已经变成了数组最高项的值的大小,在进行pop弹栈操作的时候自然已经是完成了压栈操作的,此时的top的值是最大位置处,所以return array[top--]就完成了弹出最大的那个元素,并且将索引top值在弹栈之后再减一。④判断是否空栈是通过top == -1来判断的,即初始化的情况。

public class MyStack {

private int[] array;

private int maxSize;

private int top;

public MyStack(int size){

this.maxSize = size;

array = new int[size];

top = -1;

}

//压入数据

public void push(int value){

if(top < maxSize-1){

array[++top] = value;

}

}

//弹出栈顶数据

public int pop(){

return array[top--];

}

//访问栈顶数据

public int peek(){

return array[top];

}

//判断栈是否为空

public boolean isEmpty(){

return (top == -1);

}

//判断栈是否满了

public boolean isFull(){

return (top == maxSize-1);

}

}

(2)利用栈的后进先出的特性可以很容易的实现逆序的操作,比如下面这个利用栈实现字符串的输入的逆序:这里使用一个用Object类型数组来接收数据,并且加入了判断是否扩容的ArrayStack类来进行测试,实现字符串的逆序输出:

package stack.test;

import java.util.Arrays;

import java.util.EmptyStackException;

public class ArrayStack {

// 存储元素的数组,声明为Object类型能存储任意类型的数据

private Object[] elementData;

// 指向栈顶的指针

private int top;

// 栈的总容量

private int size;

// 默认构造一个容量为10的栈

public ArrayStack() {

this.elementData = new Object[10];

this.top = -1;

this.size = 10;

}

public ArrayStack(int initialCapacity) {

if (initialCapacity < 0) {

throw new IllegalArgumentException("栈初始容量不能小于0: " + initialCapacity);

}

this.elementData = new Object[initialCapacity];

this.top = -1;

this.size = initialCapacity;

}

// 压入元素

public Object push(Object item) {

// 是否需要扩容

isGrow(top + 1);

elementData[++top] = item;

return item;

}

// 弹出栈顶元素

public Object pop() {

Object obj = peek();

remove(top);

return obj;

}

// 获取栈顶元素

public Object peek() {

if (top == -1) {

throw new EmptyStackException();

}

return elementData[top];

}

// 判断栈是否为空

public boolean isEmpty() {

return (top == -1);

}

// 删除栈顶元素

public void remove(int top) {

// 栈顶元素置为null

elementData[top] = null;

this.top--;

}

/**

* 是否需要扩容,如果需要,则扩大一倍并返回true,不需要则返回false

*

* @param minCapacity

* @return

*/

public boolean isGrow(int minCapacity) {

int oldCapacity = size;

// 如果当前元素压入栈之后总容量大于前面定义的容量,则需要扩容

if (minCapacity >= oldCapacity) {

// 定义扩大之后栈的总容量

int newCapacity = 0;

// 栈容量扩大两倍(左移一位)看是否超过int类型所表示的最大范围

if ((oldCapacity << 1) - Integer.MAX_VALUE > 0) {

newCapacity = Integer.MAX_VALUE;

} else {

newCapacity = (oldCapacity << 1);// 左移一位,相当于*2

}

this.size = newCapacity;

elementData = Arrays.copyOf(elementData, size);

return true;

} else {

return false;

}

}

//测试字符串输入“drive”

public static void main(String[] args) {

String testString = "drive";

ArrayStack stack = new ArrayStack(10);

char[] cc = testString.toCharArray();

for (char c : cc) {

stack.push(c);

}

while (!stack.isEmpty()) {

System.out.print(stack.pop());

}

}

}

运行结果:

(3)这里在记录一个利用栈的原理来进行分隔符匹配:(摘录)

//分隔符匹配

//遇到左边分隔符了就push进栈,遇到右边分隔符了就pop出栈,看出栈的分隔符是否和这个有分隔符匹配

@Test

public void testMatch(){

ArrayStack stack = new ArrayStack(3);

String str = "12";

char[] cha = str.toCharArray();

for(char c : cha){

switch (c) {

case '{':

case '[':

case '

stack.push(c);

break;

case '}':

case ']':

case '>':

if(!stack.isEmpty()){

char ch = stack.pop().toString().toCharArray()[0];

if(c=='}' && ch != '{'

|| c==']' && ch != '['

|| c==')' && ch != '('){

System.out.println("Error:"+ch+"-"+c);

}

}

break;

default:

break;

}

}

}

栈操作所耗的时间不依赖栈中数据项的个数。

二、队列

队列区别于栈的最主要的特性就是“先进先出”。队列只允许在队列的前端(front)进行删除操作,即队头进行删除,在队列的后端(rear)进行插入操作,即队尾进行插入操作。这样子理解其实就类似于排队一样和名字一样,从队尾插入的数据是最先进入的,所以会一直“排”到队头的位置去,而删除操作是从队头的位置开始删除的,所以满足先进先出,示意:

队列的分类也有两种:单向队列(Queue)和双向队列(Deque):主要是操作插入元素和删除元素的位置的不同导致的。实现方式也包括数组实现和链表实现。

(1)单向队列实现---(摘录和总结)

与栈不同的是,队列中的数据不总是从数组的0下标开始的,移除一些队头front的数据后,队头指针会指向一个较高的下标位置。也就是说与初始化的整体容量相比没有完全满溢的情况下,会出现下图所示的情况。一般队头指针在删除掉元素之后会向上移动,队尾指针在插入元素之后也会向上移动,这样子如果在删除掉一些队头元素之后再插入元素就会出现容量溢出的情况,这样子是不好的。

所以为了解决队列不满而不能插入新的元素所以引入了“循环队列”的概念。即让队尾指针绕到队头的位置。

具体实现:

public class MyQueue {

private Object[] queArray;

//队列总大小

private int maxSize;

//前端

private int front;

//后端

private int rear;

//队列中元素的实际数目

private int nItems;

public MyQueue(int s){

maxSize = s;

queArray = new Object[maxSize];

front = 0;

rear = -1;

nItems = 0;

}

//队列中新增数据

public void insert (int value) {

if (!isfull()) {

if (rear == maxsize - 1) {

rear = -1;

}

quearray[++rear] = value;

items++;

}

else

System.out.println("队列已经满了.");

}

//移除数据

public Object remove(){

Object removeValue = null ;

if(!isEmpty()){

removeValue = queArray[front];

queArray[front] = null;

front++;

if(front == maxSize){

front = 0;

}

nItems--;

return removeValue;

}

return removeValue;

}

//查看队头数据

public Object peekFront(){

return queArray[front];

}

//判断队列是否满了

public boolean isFull(){

return (nItems == maxSize);

}

//判断队列是否为空

public boolean isEmpty(){

return (nItems ==0);

}

//返回队列的大小

public int getSize(){

return nItems;

}

}

(2)优先级队列(专用数据结构)

在优先级队列中,数据项按照关键字进行排序,关键字最小(或者最大)的数据项往往在队列的最前面,而数据项在插入的时候都会插入到合适的位置以确保队列的有序。每个元素都有一个优先权。

处理方法:一般情况下,①查找操作用来搜索优先权最大的元素,②删除操作用来删除该元素 。③对于优先权相同的元素,可按先进先出次序处理或按任意优先权进行。

可用数组来实现优先级队列也可以用堆来实现,速度更快。数组实现优先级队列,声明为int类型的数组,关键字是数组里面的元素,在插入的时候按照从大到小的顺序排列,也就是越小的元素优先级越高。

同理nItems表示当前队列里面已经插入好了的元素,当然按照插入原则这nItems个元素在队列中肯定是按照从大到小的顺序插入的。

public class PriorityQue {

private int maxSize;

private int[] priQueArray;

private int nItems;

public PriorityQue(int s){

maxSize = s;

priQueArray = new int[maxSize];

nItems = 0;

}

//插入数据

public void insert(int value){

int j;

if(nItems == 0){

priQueArray[nItems++] = value;

}else{

j = nItems -1;

//选择的排序方法是插入排序,按照从大到小的顺序排列,越小的越在队列的顶端

while(j >=0 && value > priQueArray[j]){

priQueArray[j+1] = priQueArray[j];

j--;

}

priQueArray[j+1] = value;

nItems++;

}

}

//移除数据,由于是按照大小排序的,所以移除数据我们指针向下移动

//被移除的地方由于是int类型的,不能设置为null,这里的做法是设置为 -1

public int remove(){

int k = nItems -1;

int value = priQueArray[k];

priQueArray[k] = -1;//-1表示这个位置的数据被移除了

nItems--;

return value;

}

//查看优先级最高的元素

public int peekMin(){

return priQueArray[nItems-1];

}

//判断是否为空

public boolean isEmpty(){

return (nItems == 0);

}

//判断是否满了

public boolean isFull(){

return (nItems == maxSize);

}

}

insert() 方法,先检查队列中是否有数据项,如果没有,则直接插入到下标为0的单元里,否则,从数组顶部开始比较,找到比插入值小的位置进行插入,并把 nItems 加1。remove 方法直接获取顶部元素。优先级队列此处的优先级的体现是元素的大小的顺序,大的元素的优先级别更高,主要是在插入元素的时候体现的。

java判断栈中元素数目_Java数据结构与算法-栈和队列相关推荐

  1. java stack 从1.5开始?_java数据结构与算法之栈(Stack)设计与实现

    本篇是java数据结构与算法的第4篇,从本篇开始我们将来了解栈的设计与实现,以下是本篇的相关知识点: 栈的抽象数据类型 栈是一种用于存储数据的简单数据结构,有点类似链表或者顺序表(统称线性表),栈与线 ...

  2. jquery删除数组中的某个元素下标越界_Java数据结构和算法(二)—数组

    目录 1.Java数组介绍 2.用类封装数组实现数据结构 3.分析数组的局限性 上篇博客我们简单介绍了数据结构和算法的概念,对此模糊很正常,后面会慢慢通过具体的实例来介绍.本篇博客我们介绍数据结构的鼻 ...

  3. java递归单链表查找中间元素_《数据结构与算法——C语言描述》答案 3.11 查找单链表中的特定元素(递归)...

    转载请注明出处:http://blog.csdn.net/xdz78 #include #include //查找单链表中的特定元素,<数据结构与算法--c语言描述> 3.11 答案 in ...

  4. char栈java,Java数据结构与算法-栈和队列(示例代码)

    (摘录加总结)------ 栈和队列不属于基础的数据结构,它们都属于线性表. 一.栈 对于栈存储操作元素只能在栈结构的一端进行元素的插入和删除,是一种性质上的线性表结构.按照"先进后出&qu ...

  5. java数据结构 队列_Java数据结构与算法[原创]——队列

    声明:码字不易,转载请注明出处,欢迎文章下方讨论交流. 前言:Java数据结构与算法专题会不定时更新,欢迎各位读者监督.本文介绍数据结构中的队列(queue)的概念.存储结构.队列的特点,文末给出ja ...

  6. java查询数组中元素的索引

    java查询数组中元素的索引 /*** java查询数组中元素的索引*/ public class Test03 {public static void main(String[] args) {in ...

  7. 编写一个程序实现顺序栈(假设栈中元素类型为char)的各种基本运算

    编写一个程序实现顺序栈(假设栈中元素类型为char)的各种基本运算,并在此基础上设计一个主程序完成如下功能: (1)初始化顺序栈S; (2)判断顺序栈S是否为空: (3)依次进栈元素a,b,c,d,e ...

  8. java 包含汉字,【转载】Java判断字符串中是不是包含汉字

    [转载]Java判断字符串中是否包含汉字 import java.util.regex.Matcher; import java.util.regex.Pattern; public class If ...

  9. java 包含汉字,java判断字符串中是否包含汉字

    java判断字符串中是否包含汉字 package com.zuidaima.util; /** [email protected] www.zuidaima.com **/ public class ...

最新文章

  1. 【错误记录】Flutter 界面跳转报错 ( Navigator operation requested with a context that does not include a Naviga )
  2. 【SpringMVC】登录状态验证
  3. 【OS学习笔记】三十六 保护模式十:通过中断发起任务切换----中断任务
  4. CVPR 2021 |针对强时序依赖,即插即用、混合注意力机制的 ACTION 模块
  5. graphpad多条不同的曲线_应用Graphpad Prism制作多组ROC曲线图
  6. 在远程桌面连接中使用命令行参数
  7. decimal转换为int_FPGA基础知识极简教程(10)二进制到BCD转换算法
  8. Silverlight实现强壮、可复用的拖放行为
  9. c语言编程流水灯与交通灯实验,C51单片机实验报告流水灯交通灯定时器双机交互时钟(10页)-原创力文档...
  10. 下标要求数组或指针类型_C语言,数组循环哪家好,指针or下标?
  11. mysql使用sql脚本建立数据库
  12. pnp型三极管 饱和 截至_截至2013年核心Java帖子
  13. Go (Golang) 工具之单元测试 go-junit-report | go的单元测试
  14. android 离线地图 开源,android osmdroid 加载常用离线地图格式(开源的在线地图)...
  15. Android 仿朋友圈单张图片限定宽高超出时按比例缩放效果实现
  16. 南京大学软件学院 西交计算机,2021届薪酬最高的十大本科专业,前三名都是计算机和相关专业...
  17. LAMP网站架构的介绍和搭建
  18. 前端必备,5大mock省时提效小tips,用了提前下班一小时
  19. 京东一面+京东物流二面+京东秋招一二面
  20. ABP官方文档(四十五)【集成Hangfire】

热门文章

  1. do matlab的 while循环_PHP while和do while循环
  2. predict函数 R_R包randomForest的随机森林回归模型以及对重要变量的选择
  3. 【论文写作】在线考试系统的设计原理如何写
  4. 计算机毕业设计中用java/php/net/pythont物流配送中心管理系统设计
  5. 打开html文件图片为什么没有_提高网站打开速度秘诀:压缩html,Javascript和CSS文件...
  6. c++头文件被c语言调用需要注意什么_嵌入式C语言之模块化编程
  7. 计算机中专自考,中专怎么自考大专
  8. jsp页面 字体颜色 白色_电商美工不会优化页面?试试这6招
  9. fiddler模拟服务器响应,fiddler模拟返回响应数据
  10. arcgisserver修改服务器地址,ArcGIS 10.1 for Server入门(7-6)ArcGIS for Server 10.1 服务迁移与恢复--多台服务器...