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

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

一、栈

对于栈存储操作元素只能在栈结构的一端进行元素的插入和删除,是一种性质上的线性表结构。按照“先进后出”的原则进行存储数据。先进的元素在栈底,后进的元素在栈顶。需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)。比较常规的说明是:栈底固定,而栈顶浮动;栈中元素个数为零时称为空栈。插入一般称为进栈(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 方法直接获取顶部元素。优先级队列此处的优先级的体现是元素的大小的顺序,大的元素的优先级别更高,主要是在插入元素的时候体现的。

char栈java,Java数据结构与算法-栈和队列(示例代码)相关推荐

  1. 数据结构与算法-栈与队列

    数据结构与算法-栈与队列 栈 基本概念 简单表述就是仅在表尾进行插入和删除操作的线性表. 常见操作 入栈和出栈, 均在线性表的尾部进行. 基本原则就是, 先入后出. 队列 基本概念 和栈不同的是,队列 ...

  2. 给定一个n节点的二叉树,写出一个O(n)时间非递归过程,将该树每个节点关键字输出,可以使用一个栈作为辅助数据结构(算法导论第十章10.4-3)

    给定一个n节点的二叉树,写出一个O(n)时间非递归过程,将该树每个节点关键字输出,可以使用一个栈作为辅助数据结构 (算法导论第十章10.4-3) template<typename T> ...

  3. Java版数据结构之数组模拟环形队列demo

    Java版数据结构之数组模拟环形队列demo 我的代码仓库:https://github.com/zhuangbinan/datastructure 类 CircleArray package clu ...

  4. 数据结构与算法必备的 50 个代码实现

    点击上方"AI有道",选择"置顶"公众号 重磅干货,第一时间送达 数据结构和算法是程序员的内功心法和基本功.无论是人工智能还是其它计算机科学领域,掌握扎实的数据 ...

  5. Java Singleton类中的线程安全性的示例代码

    Java Singleton类中的线程安全性的示例代码 Singleton是最广泛使用的创建设计模式之一,用于限制应用程序创建对象.在实际应用程序中,数据库连接或企业信息系统(EIS)等资源是有限的, ...

  6. 数据结构与算法之循环队列的操作

    数据结构与算法之循环队列的操作 /* 循环队列的入队和出队算法设计 初始化循环队列 .打印队列.插入元素到循环队列.获取循环队列的首元素,元素不出队.出队.获取循环队列元素个数.判断循环队列的空和满. ...

  7. python 熊猫钓鱼_Python数据结构与算法之使用队列解决小猫钓鱼问题

    本文实例讲述了Python数据结构与算法之使用队列解决小猫钓鱼问题.分享给大家供大家参考,具体如下: 按照<啊哈>里的思路实现这道题目,但是和结果不一样,我自己用一幅牌试了一下,发现是我的 ...

  8. 纯java pdf转换成html,JAVA实现PDF转HTML文档的示例代码

    本文是基于PDF文档转PNG图片,然后进行图片拼接,拼接后的图片转为base64字符串,然后拼接html文档写入html文件实现PDF文档转HTML文档. 引入Maven依赖 org.apache.p ...

  9. java判断栈中元素数目_Java数据结构与算法-栈和队列

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

最新文章

  1. TensorFlow产品总监:机器学习进步让AI应用成可能
  2. Windows7中Prefetch预读文件技术详解
  3. 新闻上的文本分类:机器学习大乱斗 王岳王院长 王岳王院长 5 个月前 目标 从头开始实践中文短文本分类,记录一下实验流程与遇到的坑 运用多种机器学习(深度学习 + 传统机器学习)方法比较短文本分类处
  4. mysql 热切换_热备服务器中,切换master中切换SQL
  5. [USACO] Beef McNuggets
  6. 创业成功需早起?看看IT大佬们的作息时间
  7. 计算机知识竞赛决赛流程,计算机知识竞赛决赛圆满结束!还不快戳?!
  8. spring mvc 总体概况
  9. python开发网络小工具_Python 实现简单网络应用程序开发
  10. 为什么setTimeout(fn,0)有时有用?
  11. Spring boot 日志框架
  12. Codeforces Round #378 (Div. 2) D. Kostya the Sculptor 分组 + 贪心
  13. 无法启动此程序 因为计算机中丢失 msvcp71.dll,msvcp71.dll丢失怎样修复?计算机中丢失msvcp71.dll文件的解决方法...
  14. 实现类似黑客帝国的字符流特效屏保
  15. 翁恺老师的c语言学习笔记
  16. j2000 经度_j2000坐标系转换WGS84坐标,看不太懂
  17. 【读论文】基于深度学习的铁路道岔转辙机故障诊断(3DESIGN)
  18. python代码中 from . import ××× 是什么意思?
  19. 与同事协作一起维护发布同一个npm包,报错You do not have permission to publish
  20. 高中计算机教师证试题,2020下高中信息技术教师资格证面试试题及答案【1月10日下午】...

热门文章

  1. jdk安装和环境变量的配置
  2. 【论文笔记】CNN for NLP
  3. JavaScript面向对象精要(一)
  4. 前台获取后台数据写法%#%..
  5. java中的与运算符
  6. 容器(一)剖析面试最常见问题之 Java 集合框架
  7. Tensorflow实例:(卷积神经网络)LeNet-5模型
  8. AI人工智能工程师 学习大纲
  9. 微软推出新逆天开源语言Bosque,告别 for 循环,提高开发效率!
  10. 初识压缩感知 compressive sensing