数据结构# 笔记【栈&队列】@Gray

一.栈

1.1 简述

栈是一种后进先出的数据结构
Last in First Out(LIFO)

栈(Stack)又名堆栈,线性数据结构,它是一种重要的数据结构。从数据结构角度看,栈也是线性表,其特殊性在于栈的基本操作是线性表操作的子集,它是操作受限的线性表,因此,可称为限定性的数据结构。限定它仅在表尾进行插入或删除操作。表尾称为栈顶,相应地,表头称为栈底。栈的基本操作除了在栈顶进行插入和删除外,还有栈的初始化,判空以及取栈顶元素等。

  • 栈内存内存图
    在这里插入图片描述

在 LIFO 数据结构中,将首先处理添加到队列中的最新元素。
与队列不同,栈是一个 LIFO 数据结构。通常,插入操作在栈中被称作入栈 push 。与队列类似,总是在堆栈的末尾添加一个新元素。但是,删除操作,弹栈 pop ,将始终删除队列中相对于它的最后一个元素。

1.2 构造方法

Constructor描述
Stack​()创建一个空堆栈。
  • 常用方法

    Modifier and Type方法描述
    booleanempty()测试此堆栈是否为空。
    Epeek()查看此堆栈顶部的对象,而不从堆栈中删除它。
    Epop()删除此堆栈顶部的对象,并将该对象作为此函数的值返回。
    Epush(E item)将项目推送到此堆栈的顶部。
    intsearch(Object o)返回一个对象在此堆栈上的基于1的位置。
  • 代码示例

package com.Gray.DemoStack;

import java.util.Iterator;
import java.util.Stack;

public class PracticeStack {
    public static void main(String[] args) {
        //创建栈对象
        Stack<String> sta = new Stack<>();
        //向栈中添加数据
        sta.push("明里紬");
        sta.push("大桥未久");
        sta.push("三上悠亚");
        System.out.println(sta+" -->栈顶位置");
        System.out.println("------增强for遍历-----");
        for (String s : sta) {
            System.out.println(s);
        }
        System.out.println("------迭代器遍历------");
        Iterator<String> iterator = sta.iterator();
        while (iterator.hasNext()) {
            String next = iterator.next();
            System.out.println(next);
        }
        //找到元素的索引   最先加入的元素是最大索引
        int search = sta.search("明里紬");
        System.out.println(search);

        //拿到栈顶元素并删除
        String pop = sta.pop();
        System.out.println(pop);
        System.out.println(sta+" -->栈顶位置");

        //拿到栈顶元素不删除
        String peek = sta.peek();
        System.out.println(peek);
        System.out.println(sta+" -->栈顶位置");

        //判断栈是否为空
        boolean empty = sta.isEmpty();
        System.out.println(empty);


        //add方法是继承自stack的父类Vector中的方法,有线程安全问题,不用他
        sta.add("奥利给");
        System.out.println(sta+" -->栈顶位置");
    }
}


运行截图:
在这里插入图片描述

1.3 应用

  • Undo操作(撤销)-编辑器
  • 程序调用系统栈-操作系统
  • 括号匹配-编译器

实践案例:

  • LeetCode括号匹配问题
package com.Gray.Stack括号匹配;

import java.util.Stack;

public class Solution {
    public static void main(String[] args) {
        System.out.println(isValid("{}"));
        System.out.println(isValid("{}()[]"));
        System.out.println(isValid("{[{}]"));
    }

    public static boolean isValid(String s) {
        //创建栈
        Stack<Character> stack = new Stack<>();
        //遍历字符串
        for (int i = 0; i < s.length(); i++) {
            //拿到每一个字符
            char c = s.charAt(i);
            //如果他是[{(的其中一个,就把他放入栈中
            if (c == '(' || c == '{' || c == '[') {
                stack.push(c);//压入栈中
            }
            if (stack.isEmpty()) {//如果栈是空的,返回false
                return false;
            } else {
                if (c == ')' && stack.pop() != '(') {//跟栈顶元素进行比较
                    return false;
                } else if (c == '}' && stack.pop() != '{') {
                    return false;
                } else if (c == ']' && stack.pop() != '[') {
                    return false;
                }
            }
        }
        return stack.isEmpty();//最后如果栈为空,返回true
    }
}

1.4 栈的实现

  • 利用动态数组实现栈结构:
package com.Gray.Demo栈;
@SuppressWarnings("all")
public class Array<E> {
    private E[] data; //创建静态数组
    private int size;//数组的实际存入元素个数

    //有参构造 用户传进来数组需要多大容量capacity
    public Array(int capacity) {
        data = (E[]) new Object[capacity];//赋给原数组
        size = 0;
    }

    //默认的构造方法,默认数组的容量是 capacity = 10
    public Array() {
        this(10);//调用有参构造传入10
    }

    //获取元素个数
    public int getSize() {
        return size;
    }

    //获取数组的容量
    public int getCapacity() {
        return data.length;
    }

    //判断数组是否为空
    public boolean isEmpty() {
        return size == 0;
    }

    //向所有元素后添加一个新的元素
    public void addLast(E e) {
        add(size, e);
    }

    //在数组0的位置添加一个元素
    public void addfirst(E e) {
        add(0, e);
    }

    //在第一个index个位置插入一个新的元素e
    public void add(int index, E e) {
        if (size == data.length) {
            throw new IllegalArgumentException("Add failed. Array is full!");
        } else if (index < 0 || index > size) {
            throw new IllegalArgumentException("Add failed. Require index >=0 Array is full.");
        } else {

            for (int i = size - 1; i >= index; i--) {
                data[i + 1] = data[i];
            }

            data[index]= e;
            size++;
        }
    }

    //获取index索引位置的元素
    public E get(int index) {
        if (index < 0 || index > size) {
            throw new IllegalArgumentException("get failed. Index is illegal");
        }
        return data[index];
    }

    public E getLast(){
        return get(size-1);
    }

    public E getFirst(){
        return get(0);
    }


        //更改index索引位置的元素
    void set(int index, E e) {
        if (index < 0 || index >= size) {
            throw new IllegalArgumentException("set failed. Index is illegal.");
        }
        data[index] = e;
    }

    //查找数组中是否有元素e
    public boolean contians(E e) {
        for (int i = 0; i < size; i++) {
            if (data[i].equals(e)) {
                return true;
            }
        }
        return false;
    }

    //查找该元素的索引,找不到返回-1 元素不存在
    public int find(E e) {
        for (int i = 0; i < size; i++) {
            if (data[i].equals(e)) {
                return i;
            }
        }
        return -1;
    }

    //删除元素方法 删除返回被删除的元素
    public E remove(int index) {
        if (index < 0 || index >= size) {
            throw new IllegalArgumentException("remove failed. Index is illegal.");
        }
        E ret = data[index];//被删除的元素
        for (int i = index + 1; i < size; i++) {//将删除元素 后边的所有元素前移
            data[i - 1] = data[i];
        }
        size--;
        data[size] = null;
        return ret;
    }

    //删除首尾元素
    public E removeFirst() {
        return remove(0);
    }

    //删除末位元素
    public E removeLast() {
        return remove(size - 1);
    }

    //删除某个元素
    public void removeElement(E e) {
        int i = find(e);
        if (i != -1) {
            remove(i);
        }
    }

    @Override
    public String toString() {
        StringBuilder res = new StringBuilder();
        res.append(String.format("Array:size = %d,capacity = %d\n", size, data.length));
        res.append('[');
        for (int i = 0; i < size; i++) {
            res.append(data[i]);
            if (i != size - 1) {
                res.append(", ");
            }
        }
        res.append(']');
        return res.toString();
    }
}

  • stack接口
package com.Gray.Demo栈;
public interface Stack<E> {
    int getSize();
    boolean isEmpty();
    void push(E e);
    E pop();
    E peek();
}
  • stack实现类
package com.Gray.Demo栈;
/**
 * 栈是一种后进先出的数据结构
 * Last in First Out(LIFO)
 */

public class ArrayStack<E> implements Stack<E> {

    Array<E> array;

    public ArrayStack(){
        array = new Array<>();
    }

    @Override
    public int getSize() {
        return array.getSize();
    }

    @Override
    public boolean isEmpty() {
        return array.isEmpty();
    }

    @Override
    public void push(E e) {
        array.addLast(e);
    }

    @Override
    public E pop() {
        return array.removeLast();
    }

    @Override
    public E peek() {
        return array.getLast();
    }
    public int getCapacity(){
        return array.getCapacity();
    }

    @Override
    public String toString() {
        return "ArrayStack{" +
                "array=" + array +
                '}';
    }
}

  • 测试类
package com.Gray.Demo栈;

public class TestStack {
    public static void main(String[] args) {

        StackImpl<Integer> stack = new StackImpl<>();
        for (int i = 0; i < 5; i++) {
            stack.push(i);
            System.out.println(stack);
        }
        stack.pop();
        System.out.println(stack);
    }
}

二.队列

2.1 简述

队列(Queue)是一种先进先出(FIFO,First-In-First-Out)的线性表。
在具体应用中通常用链表或者数组来实现。 线性数据结构
队列只允许在后端(称为 rear)进行插入操作,在前端(称为 front)进行删除操作。
队列的操作方式和堆栈类似,唯一的区别在于队列只允许新数据在后端进行添加。
队列常用的方法有:add、remove、element、offer、poll、peek、put、take。

  • 队列内存图
    在这里插入图片描述
    在 FIFO 数据结构中,将首先处理添加到队列中的第一个元素。
    如上图所示,队列是典型的FIFO 数据结构。插入(insert)操作也称作入队(enqueue),新元素始终被添加在队列的末尾。 删除(delete)操作也被称为出队(dequeue)。 你只能移除第一个元素

2.2 常用方法

Modifier and Type方法描述
booleanadd​(E e)将指定的元素插入到此队列中,如果可以立即执行此操作而不违反容量限制, true成功返回 true ,如果当前没有可用的空间,则抛出 IllegalStateException 。
Eelement​()检索,但不删除,这个队列的头。
booleanoffer​(E e)如果在不违反容量限制的情况下立即执行,则将指定的元素插入到此队列中。
Epeek​()检索但不删除此队列的头,如果此队列为空,则返回 null 。
Epoll​()检索并删除此队列的头部,如果此队列为空,则返回 null 。
Eremove​()检索并删除此队列的头。

add 增加一个元素 如果队列已满,则抛出一个IIIegaISlabEepeplian异常
remove 移除并返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常
element 返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常
offer 添加一个元素并返回true 如果队列已满,则返回false
poll 移除并返问队列头部的元素 如果队列为空,则返回null
peek 返回队列头部的元素 如果队列为空,则返回null
put 添加一个元素 如果队列满,则阻塞
take 移除并返回队列头部的元素 如果队列为空,则阻塞

  • 代码案例
package com.Gray.DemoQueue;

import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;

public class TestQueue {
    public static void main(String[] args) {
        //设置队列容量
        final int capacity = 1000;
        //创建队列数组
        Queue<String> que = new ArrayBlockingQueue<>(capacity);
        //添加元素
        que.add("波多野结衣");
        que.add("上原结衣");
        que.add("吉泽明步");
        //遍历
        System.out.println("------遍历------");
        for (String s : que) {
            System.out.println(s);
        }
        //看一眼队首元素
        System.out.println("-------查看队首元素------");
        String peek = que.peek();
        System.out.println("查看了:"+peek);
        System.out.println("队首"+que+"队尾");

        //删除队首元素
        System.out.println("-------删除队首元素-------");
        String poll = que.poll();
        System.out.println("删除了:"+poll);
        System.out.println("队首"+que+"队尾");
    }
}

运行截图
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值