【算法】JAVA刷算法必备数据结构


数组List

ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。
ArrayList 继承了 AbstractList ,并实现了 List 接口。
在这里插入图片描述
具体使用:
定义:

import java.util.*;
List<E> list = new ArrayList<>();

E: 泛型数据类型,用于设置 objectName 的数据类型,只能为引用数据类型

已经封装可以直接调用的方法:

  • 变量名.add(数据) :向尾部插入数据
  • 变量名.get(i) :通过下标访问数据
  • 变量名.set(i, 数据):第一个参数为索引位置,第二个为要修改的值
  • 变量名.remove(i) :删除下标为i的数据
  • 变量名.size() :返回容器元素个数
  • Collections.sort(变量名) :排序
  • contains():判断元素是否在 arraylist
  • isEmpty():判断 arraylist 是否为空
  • subList():截取部分 arraylist 的元素
import java.util.*;

/**
 * @ClassName Main
 * @Description TODO
 * @Author 小何
 * @Date 2024/9/23 22:46
 **/
public class Main {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        // 添加数据
        list.add(3);
        list.add(4);
        list.add(1);
        list.add(2);
        list.add(6);
        System.out.println(list.toString()); // [3, 4, 1, 2, 6]
        // 修改数据
        list.set(2, 7);
        System.out.println(list.toString()); // [3, 4, 7, 2, 6]
        // 删除数据
        list.remove(list.size() -1);
        System.out.println(list.toString()); // [3, 4, 7, 2]
        // 反转
        Collections.reverse(list);
        System.out.println(list.toString()); // [2, 7, 4, 3]
        // 排序
        Collections.sort(list);
        System.out.println(list.toString()); // [2, 3, 4, 7]
        // 排序 大-》小
        Collections.sort(list, Collections.reverseOrder());
        System.out.println(list.toString()); // [7, 4, 3, 2]
        list.add(9);
        Collections.sort(list, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });
        System.out.println(list.toString()); // [9, 7, 4, 3, 2]

        // 是否包含某个元素
        System.out.println(list.contains(8)); // false
        // 截取
        List<Integer> subList = list.subList(1, 3);
        System.out.println(subList.toString());// [7, 4]

    }
}


队列和栈

队列:先进先出
栈:先进后出
LinkedList 实现了 Queue 接口等,可作为队列使用,也可以当作栈使用。
在这里插入图片描述
具体使用:

import java.util.LinkedList;
LinkedList<E> list = new LinkedList<>();

已经封装可以直接调用的方法:

  • 添加元素add
  • 尾部添加元素addLast
  • 头部添加元素addFirst
  • 移除头部元素removeFirst
  • 移除尾部元素removeLast
  • 获取头部元素getFirst
  • 获取元素 iget(i)

具体队列很栈的实现:

import java.util.*;

/**
 * @ClassName Main
 * @Description TODO
 * @Author 小何
 * @Date 2024/9/23 22:46
 **/
public class Main {
    public static void main(String[] args) {
        LinkedList<Integer> list = new LinkedList<>();
        list.add(4);
        list.add(1);
        list.add(3);
        list.add(6);
        list.add(2);
        System.out.println(list.toString());
        // 在尾部添加元素
        list.addLast(8);
        // 在头部添加元素
        list.addFirst(9);
        System.out.println(list.toString()); //[9, 4, 1, 3, 6, 2, 8]
        // 移除头部元素
        list.removeFirst();
        System.out.println(list.toString()); // [4, 1, 3, 6, 2, 8]
        // 移除尾部元素
        list.removeLast();
        System.out.println(list.toString()); // [4, 1, 3, 6, 2]
        // 获取头部元素
        System.out.println(list.getFirst()); // 4
        // 获取尾部元素
        System.out.println(list.getLast()); // 2
        // 获取元素 i
        System.out.println(list.get(2)); // 3

        // 队列 queue 先进先出
        LinkedList<Integer> queue = new LinkedList<>();
        // 入队
        queue.add(1);
        queue.add(2);
        queue.add(3);
        System.out.println(queue.toString()); // [1, 2, 3]
        // 出队
        queue.removeFirst();
        System.out.println(queue.toString()); // [2, 3]
        // 访问队首元素
        System.out.println(queue.getFirst()); // 2
        // 访问队尾元素
        System.out.println(queue.getLast()); // 3
        // 队列元素
        System.out.println(queue.size()); // 2

        // 栈 stack 先进后出
        LinkedList<Integer> stack = new LinkedList<>();
        // 入栈
        stack.add(4);
        stack.add(6);
        stack.add(2);
        stack.add(1);
        stack.add(3);
        stack.add(5);
        System.out.println(stack.toString()); // [4, 6, 2, 1, 3]
        // 出栈
        stack.removeLast();
        System.out.println(stack.toString()); // [4, 6, 2, 1, 3]
        // 访问栈顶
        System.out.println(stack.getLast());// 3
        // 栈元素个数
        System.out.println(stack.size()); // 5

    }
}

同时JAVA提供了专门的栈实现Stack类:

public class Main {
    public static void main(String[] args) {
        Stack<Integer> stack = new Stack<>();
        stack.push(1);
        stack.push(2);
        stack.push(3);
        stack.push(4);
        System.out.println(stack);
        System.out.println(stack.peek()); // 4 栈顶
        System.out.println(stack.pop()); // 4 出栈
        System.out.println(stack.peek()); // 3
        System.out.println(stack.size()); // 3


    }
}


栈的应用:表达式求值

对于中缀表达式求值,需要定义两个栈:数字栈和符号栈,顾名思义分别存放数字和符号。

  1. 遇到数字,直接入数字栈,需要注意并不是只有个位数,还是需要一定的处理,详情见代码。
  2. 遇到符号,有三种情况:
  • 左括号(:直接入符号栈。
  • 右括号):取两个数字栈的数据,取一个符号栈的数据,计算结果放入数字栈,循环直到符号栈中取出(结束。
  • ±*/运算符:符号栈为空,直接入符号栈,不为空则需要比较当前的运算符和符号栈栈顶元素的优先级,当栈顶元素优先级大于等于当前的运算符,符号栈出栈,取两个数字栈元素进行计算,结果放入数字栈,循环,将所有大于等于当前的运算符的全部出栈为止。
  1. 最后的计算结果为数字栈的栈顶元素。

提前使用map集合定义好优先级:

import java.util.HashMap;
import java.util.Map;
import java.util.Stack;

public class Main {
    public static void main(String[] args) {
        String str = "2*(3+5)+7/1-4"; // 中缀表达式
        Stack<Integer> nums = new Stack<>(); // 数字栈
        Stack<Character> ops = new Stack<>(); // 符号栈

        // 符号优先级
        Map<Character, Integer> map = new HashMap<>();
        map.put('+', 1);
        map.put('-', 1);
        map.put('*', 2);
        map.put('/', 2);
        map.put('(', 0);

        char[] array = str.toCharArray();
        int i = 0;

        while (i < array.length) {
            // 遇到数字 直接入栈
            if (Character.isDigit(array[i])) {
                int sum = 0;
                while (i < array.length && Character.isDigit(array[i])) {
                    sum = sum * 10 + (array[i] - '0');
                    i++;
                }
                nums.push(sum);
                continue; // 继续到下一个字符
            }

            // 遇到符号
            if (array[i] == '(') {
                ops.push(array[i]);
            } else if (array[i] == ')') {
                // 出栈直到遇到左括号
                while (ops.peek() != '(') {
                    performOperation(nums, ops);
                }
                ops.pop(); // 弹出左括号
            } else {
                // 运算符:比较优先级
                while (!ops.isEmpty() && map.get(ops.peek()) >= map.get(array[i])) {
                    performOperation(nums, ops);
                }
                ops.push(array[i]);
            }
            i++;
        }

        // 处理剩余的运算符
        while (!ops.isEmpty()) {
            performOperation(nums, ops);
        }

        System.out.println(nums.pop());
    }

    private static void performOperation(Stack<Integer> nums, Stack<Character> ops) {
        int b = nums.pop();
        int a = nums.pop();
        char op = ops.pop();
        switch (op) {
            case '+': nums.push(a + b); break;
            case '-': nums.push(a - b); break;
            case '*': nums.push(a * b); break;
            case '/':
                // 注意:除以零的情况
                if (b == 0) throw new ArithmeticException("Division by zero");
                nums.push(a / b); break;
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值