Java实现数据结构——顺序表

目录

一、前言

二、实现

2.1 增

2.2 删

2.3 查 

 2.4 改

 2.5 销毁顺序表

三、Arraylist

3.1 构造方法

 3.2 常用操作

3.3 ArrayList遍历

四、 ArrayList具体使用  

4.1 杨辉三角

4.2 简单洗牌算法


一、前言

笔者在以前的文章中实现过顺序表

本文在理论上不会有太详细的讲述

如有需要可以翻看笔者之前的文章

http://t.csdnimg.cn/G5TpF


Java 中已经封装好了顺序表的类

但在使用之前

先自己实现一遍 

二、实现

将顺序表作为一个类进行实现

public class MyArrayList {
    private int[] array ;//以整形数组示例
    private static int defaultspace = 10;//默认数组大小
    private int usespace = 0;//顺序表有效数据个数

    // 构造方法
    public MyArrayList() {
      this.array = new int[defaultspace];//不指定大小就默认大小
    }

    public MyArrayList(int size) {
        this.array = new int[size] ;//用户自己指定大小
    }
}

再给一个方法让用户可以知晓表中有效数据个数

  public int size(){
        return this.usespace;
    }

2.1 增

这里进行一个方法的重载

   public void add(int data){
//     不指定位置就默认是数组尾插入数据
    }
    public void add(int data ,int pos){
//指定位置就插入到指定位置

在进行数据插入时

需要判断顺序表中是否还有足够的空间

给一个方法

检查操作不需要用户来使用

那就用 private 来修饰

   private boolean IsFull() {
//        检查顺序表空间是否还有剩余
        return usespace == this.array.length;
    }

如果顺序表空间没有剩余

就需要扩容这个顺序表

这里选择使用 Arrays 类中的 copyOf 方法

    public void add(int data) {
//     不指定位置就默认是数组尾插入数据
        if (IsFull(array)) {
            this.array = Arrays.copyOf(array, array.length * 2);
        }
        array[usespace] =  data;
        usespace++;

 将上述操作封装进一个方法 checkspace

 private void checkspace() {
        if (IsFull()) {
            array = Arrays.copyOf(array, array.length * 2);
        }
    }
   public void add(int data) {
//     不指定位置就默认是数组尾插入数据
        checkspace();
        this.array[usespace++] = data;
    }


而在指定位置的 add 方法中

 则是需要检查插入位置是否合法

这个下标的合法区间是 0~顺序表有效数据个数

那么不止在增删查改中都会有操作涉及到检查要进行操作的位置是否合法

不妨将操作位置不合法作为异常处理

自定义一个异常类

public class Pos_IllegalityException extends RuntimeException{
    public Pos_IllegalityException(String message) {
        super(message);
    }
}

检查操作不需要用户来使用

那就用 private 来修饰

  private void checkPos(int pos) throws Pos_IllegalityException {
        //检查插入位置是否合法
        if(pos < 0 || pos > usespace){
            throw new Pos_IllegalityException("输入的下标不合法:"+pos);
        }
    }

指定位置插入数据后

需要将原 pos及其以后得数据向后移动

    public void add(int data, int pos) {
//指定位置就插入到指定位置

        try {
            checkPos_add(pos);
        } catch (Pos_IllegalityException e) {
            e.printStackTrace();
        }
        checkspace();
        for (int i = usespace; i >= pos; i--) {
            this.array[i + 1] = this.array[i];
        }
        this.array[pos] = data;
        this.usespace++;
    }

在实现一个打印方法

便于测试

  public void print() {
        for (int i = 0; i < usespace; i++) {
            System.out.println(array[i]);
        }
    }

测试

  public static void main(String[] args) {
        MyArrayList arr1 = new MyArrayList();
        arr1.add(1);
        arr1.add(2,0);
        arr1.add(3,1);
        arr1.add(4);
        arr1.add(5);
        arr1.print();
    }
}


测试是否能捕捉到异常

 public static void main(String[] args) {
        MyArrayList arr1 = new MyArrayList();
        arr1.add(1);
        arr1.add(2,0);
        arr1.add(3,10);
        arr1.add(4);
        arr1.add(5);
        arr1.print();
    }

 

 符合预期

2.2 删

在进行删除操作的时候

这个顺序表肯定不能为空

就要先判断

   private boolean IsEmpty() {
        return this.usespace == 0;
    }
public void remove(int pos){
      
    }

在进行指定位置删除时,同样需要判断进行操作的位置是否合法

删除操作中

pos 合法范围是[0,usespace)

  private void chechPos_remove(int pos) throws Pos_IllegalityException {
        //检查删除位置是否合法
        if (pos < 0 || pos >= this.usespace) {
            throw new Pos_IllegalityException("输入的下标不合法:" + pos);
        }
    }

删除 pos 位置的数据就是将 pos 位置后的数据向前移动一位

pos + 1 位置开始向前覆盖

public void remove(int pos) {
        //删除指定位置的数据
        if (IsEmpty()) {
            System.out.println("当前没有可以删除的数据");
        }
        try {
            chechPos_remove(pos);
        } catch (Pos_IllegalityException e) {
            e.printStackTrace();
        }
        for (int i = pos; i < this.usespace - 1; i++) {
            this.array[i] = this.array[i + 1];
        }
        this.usespace--;
    }

测试

public static void main(String[] args) {
        MyArrayList arr1 = new MyArrayList();
        arr1.add(1);
        arr1.add(2);
        arr1.add(3);
        arr1.add(4);
        arr1.add(5);
        arr1.print();
        System.out.println("===========================");
        arr1.remove(0);
        arr1.remove(arr1.size() - 1);
        arr1.print();
    }


测试是否能捕捉异常

public static void main(String[] args) {
        MyArrayList arr1 = new MyArrayList();
        arr1.add(1);
        arr1.add(2);
        arr1.add(3);
        arr1.add(4);
        arr1.add(5);
        arr1.print();
        System.out.println("===========================");
        arr1.remove(0);
        arr1.remove(arr1.size() );
        arr1.print();
    }

符合预期

2.3 查 

用两个方法

一个叫 indexOf 

  public int indexOf(int data)

找到对应数据返回对应下标

找不到返回 -1

一个叫 get

public int get(int pos)

查找对应下标的数据


先说 indexOf

同样的

在查找时

也需要判断顺序表中是否有数据

public int indexOf(int data) {
        if (IsEmpty()) {

        }
        return -1;
    }

为空或者表中没这个数据都返回-1

找到了就返回对应的下标

   public int indexOf(int data) {
//        查找数据对应的下标
        if (IsEmpty()) {
            return -1;
        }
        for (int i = 0; i < this.usespace; i++) {
            if (this.array[i] == data) {
                return i;
            }
        }
        return -1;
    }


现在说 get

public int get(int pos)throws {
//        查找对应下标的数据
    if (IsEmpty()) {
        
    }
    
}

那么在这里遇到了一个小问题

在这个顺序表为空的情况下

返回值该是什么呢

似乎任意一个整数都不太适合进行返回

那么干脆将顺序表为空作为一种异常处理

public class MyArrayListEmptyException extends RuntimeException{
    public MyArrayListEmptyException(String message) {
        super(message);
    }
}

再将前文中删操作时也应用这个异常

 public void remove(int pos) throws MyArrayListEmptyException {
        //删除指定位置的数据
        if (IsEmpty()) {
            throw new MyArrayListEmptyException("当前顺序表为空!");
        }
        try {
            chechPos_remove(pos);
        } catch (Pos_IllegalityException e) {
            e.printStackTrace();
        }
        for (int i = pos; i < this.usespace - 1; i++) {
            this.array[i] = this.array[i + 1];
        }
        this.usespace--;
    }

然后完成 get 的逻辑

同样的

需要检查传入下标的合法性

这里传入下标的合法性与删除操作的合法范围相同

那么就可以调用 chechPos_remove 这个方法

为了方便就改个名

 private void chechPos_remove_and_get(int pos) throws Pos_IllegalityException {
        //检查删除位置是否合法
        if (pos < 0 || pos >= this.usespace) {
            throw new Pos_IllegalityException("输入的下标不合法:" + pos);
        }
    }
   public int get(int pos) throws MyArrayListEmptyException {
//        查找对应下标的数据
        chechPos_remove_and_get(pos);
        if (IsEmpty()) {
            throw new MyArrayListEmptyException("当前顺序表为空");
        }
        return this.array[pos];
    }

测试

 public static void main(String[] args) {
        MyArrayList arr1 = new MyArrayList();
        arr1.add(99);
        arr1.add(2);
        arr1.add(3);
        System.out.println(arr1.indexOf(3));
        System.out.println(arr1.indexOf(4));
        System.out.println(arr1.get(0));
    }

这里看起来好像没问题

需要注意的是

如果是顺序表中所存数据是引用数据类型

那么

就不能使用 == 号判断

需要重写 equals 方法

 2.4 改

通过一个 set 方法来实现

public void set(int data ,int pos){
        
}

类似的

顺序表不能为空

判断 pos 是否合法

合法区间也是[0,usespace)

那再改个名

private void checkPos_remove_get_set(int pos) throws Pos_IllegalityException {
        //检查删除位置是否合法
        if (pos < 0 || pos >= this.usespace) {
            throw new Pos_IllegalityException("输入的下标不合法:" + pos);
        }
    }

完成 set 的实现

public void set(int data, int pos) throws MyArrayListEmptyException{
        //修改表中数据
        if(IsEmpty()){
            throw new MyArrayListEmptyException("当前顺序表为空");
        }
        checkPos_remove_get_set(pos);
        this.array[pos] = data;
    }

测试

 public static void main(String[] args) {
        MyArrayList arr1 = new MyArrayList();
        arr1.add(99);
        arr1.add(2);
        arr1.add(3);
        arr1.set(199,0);
        arr1.set(299,1);
        arr1.print();
    }

 2.5 销毁顺序表

顺序表在使用完成之后需要进行销毁

如果顺序表存的是基本数据类型

可以直接让 usespace = 0

 public void clear(){
        this.usespace = 0;
    }

但是如果是引用数据类型

采用这种方法会造成内存泄漏

JVM 中的自动回收算法有一个要求便是没引用这个数据

而这里虽然将 usespacez 置为0了

但数组中的对象仍然是存储在内存当中的

0下标确实还在引用这个对象

那么最粗暴的方法

就是直接将数组置空

  public void clear(){
        this.array = null;
    }

平和一点就是写一个循环

让每一项都置空

public void clear(){
        for (int i = 0; i <this. usespace; i++) {
            this.array[i] = null;
        }
    }

那为什么基本数据类型不需要回收呢

比如这里的 int

就算不主动向表中插入数据

表中对应下标位置仍会有默认的 0

到这里

自己实现的一个简单顺序表就完成了

下面来看看 Java 中实现的 Arraylist

三、Arraylist

接下来来看一下 Java 中已经封装好的 Arraylist

这里只展示部分方法


3.1 构造方法

 来看看提供的构造方法


其中这个构造方法是由使用者指定顺序表大小

指定空间大小不合法就抛出一个异常


现在来看看这个无参构造方法 

可以看到的是

如果调用无参构造方法

并没有给数组分配内存空间

public static void main(String[] args) {
        ArrayList arrayList = new ArrayList<>();
        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(3);
        for (int i = 0; i < arrayList.size(); i++) {
            System.out.println(arrayList.get(i));
        }
    }

 

但是可以看到的是

往这个表中插入数据

还是可以成功插入

这时候就去看看方法 add 中是怎么执行的

 就是通过上述步骤

elementData 指定了一片内存空间

能够完成 add 操作


 

public static void main(String[] args) {
        ArrayList<Integer> arrayList1 = new ArrayList<>();
        ArrayList<Number> arrayList2 = new ArrayList<>(arrayList1);
    }

 

 public static void main(String[] args) {
        ArrayList<Integer> arrayList1 = new ArrayList<>();
        ArrayList<Number> arrayList2 = new ArrayList<>(arrayList1);
        LinkedList<Number> linkedList = new LinkedList<>(arrayList1);
        Vector<Number> vector = new Vector<>(arrayList1);
    }

 

都是可以的

而不满足上述条件

  public static void main(String[] args) {
        ArrayList<String> arrayList1 = new ArrayList<>();
        ArrayList<Number> arrayList2 = new ArrayList<>(arrayList1);
    }

 

 3.2 常用操作

方法作用
boolean add (E e)
尾插 e
void add (int index, E element)
e 插入到 index 位置
boolean addAll (Collection<? extends E> c)
尾插 c 中的元素
E remove (int index)
删除 index 位置元素
boolean remove (Object o)
删除遇到的第一个 o
E set (int index, E element)
将下标 index 位置元素设置为 element
void clear ()
清空
boolean contains (Object o)
判断 o 是否在线性表中
int indexOf (Object o)
返回第一个 o 所在下标
int lastIndexOf (Object o)
返回最后一个 o 的下标
List<E> subList (int fromIndex, int toIndex)
截取部分list
…………

这里主要说说重载的 remove 方法

    public static void main(String[] args) {
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(3);
        arrayList.add(4);
        arrayList.add(5);
        for (int i = 0; i < arrayList.size(); i++) {
            System.out.print(arrayList.get(i)+" ");
        }
        arrayList.remove(3);
        System.out.println();
        for (int i = 0; i < arrayList.size(); i++) {
            System.out.print(arrayList.get(i)+" ");
        }
    }

如果只传一个整形数字

删除的是对应下标的值 

如果想要具体删除某一个数据

那就要 new 一个对象

  public static void main(String[] args) {
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(3);
        arrayList.add(4);
        arrayList.add(5);
        for (int i = 0; i < arrayList.size(); i++) {
            System.out.print(arrayList.get(i)+" ");
        }
        arrayList.remove(new Integer(3));
        System.out.println();
        for (int i = 0; i < arrayList.size(); i++) {
            System.out.print(arrayList.get(i)+" ");
        }
    }


以及 subList 方法

public static void main(String[] args) {
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(3);
        arrayList.add(4);
        arrayList.add(5);
        List<Integer> list = arrayList.subList(0,3);
        for (int i = 0; i < list.size(); i++) {
            System.out.print(list.get(i)+" ");
        }
        arrayList.set(0,99);
        System.out.println();
        for (int i = 0; i < list.size(); i++) {
            System.out.print(list.get(i)+" ");
        }
    }

截取后并不是产生新的对象

而是将截取的地址返回

所以在修改 arraylist 的值后

list 也会被修改

3.3 ArrayList遍历

ArrayList 可以使用三方方式遍历: for循环+ 下标 foreach 使用迭代器
for循环+ 下标在前文已经使用,这里就不再赘述
public  static void main(String[] args) {
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(3);
        arrayList.add(4);
        arrayList.add(5);
       for (Integer integer:arrayList){
           System.out.println(integer);
       }
    }


迭代器

使用方法

  public  static void main(String[] args) {
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(3);
        arrayList.add(4);
        arrayList.add(5);
        Iterator<Integer> integerIterator = arrayList.iterator();
        while (integerIterator.hasNext()){
            System.out.println(integerIterator.next());
        }
    }

 

四、 ArrayList具体使用  

4.1 杨辉三角

题目来源

https://leetcode.cn/problems/pascals-triangle/description/


 这段代码表示

指定 对象 list 中存放的类型是 List<Integer>

 public static void main(String[] args) {
        List<List<Integer>> list = new ArrayList<>();
        ArrayList<Integer> arrayList = new ArrayList<>();
        ArrayList<Integer> arrayList2 = new ArrayList<>();
        list.add(arrayList);
        list.add(arrayList2);
        System.out.println();
    }

打个断点观察一下

可以看到其中存放的确实是 ArrayList 类型的对象


在本题中可以将整个杨辉三角看成是一个 List< List<Integer>> 对象

每一行就是单独的一个 Arraylist 对象 

就可以将 numRows Arraylist 对象增加到 List< List<Integer>> 对象中

完成这个杨辉三角


每一个 Arraylist 对象首元素和尾元素都是 1

就只需要给 (0,Arraylist 对象.length()) 下标处进行计算赋值

  public List<List<Integer>> generate(int numRows) {
        List<List<Integer>> list = new ArrayList<>();
        //        第一行只有一个元素 1
        List<Integer> firstrow = new ArrayList<>();
        firstrow.add(1);
        list.add(firstrow);//插入list
        for (int i = 1; i < numRows; i++) {
            List<Integer> currow = new ArrayList<>();//当前行
            currow.add(1);//当前行的首元素
            for (int j = 1; j < i; j++) {
//                只进行(0,尾元素下标)之间的值赋值
            }
            currow.add(1);//尾元素赋值
            list.add(currow);//插入list
        }
        return list;
    }

而处于这个范围内的值等于

上一行同一列的值+上一行前一列的值

而对于当前代码来说

以第三行为例

list 中的第二个存储的对象

通过 get 方法将获取

public List<List<Integer>> generate(int numRows) {
        List<List<Integer>> list = new ArrayList<>();
        //        第一行只有一个元素 1
        List<Integer> firstrow = new ArrayList<>();
        firstrow.add(1);
        list.add(firstrow);//插入list
        for (int i = 1; i < numRows; i++) {
            List<Integer> currow = new ArrayList<>();//当前行
            currow.add(1);//当前行的首元素
            for (int j = 1; j < i; j++) {
//                只进行(0,尾元素下标)之间的值赋值
                List<Integer> lastrow = list.get(i - 1);//上一行
                int num = lastrow.get(j) + lastrow.get(j - 1);
                currow.add(num);
            }
            currow.add(1);//尾元素赋值
            list.add(currow);//插入list
        }
        return list;
    }

现在来提交一下

可以看到是可行的

4.2 简单洗牌算法

假设有三人正在玩扑克牌

设计一个洗牌算法

这里不计入大小王

总共有五十二张牌

花色有四种

♠(黑桃)、♥(红桃)、♦(方块)、♣(梅花)

每种花色各有13张

J Q K A 用数字 11,12,13,1代替

大概逻辑如下


可以把每一张牌看成是一个对象

那就需要一个牌类

public class Card {
    private String color;//花色 ♠(黑桃)、♥(红桃)、♦(方块)、♣(梅花)
    private int point;//点数 1,2,3,4,5,6,7,8,9,10,11,12,13

    public  Card(){
        
    }
    public Card(String color, int point) {
        this.color = color;
        this.point = point;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public void setPoint(int point) {
        this.point = point;
    }

    @Override
    public String toString() {
        return "[" +
                  color + '\''
                 + point +
                "]";
    }
}

那么 Card 类实例化出来的 52 个对象放到一个牌组 CardList

public class CardList {
//牌组
    public static List<Card> BuyCard(){
        List<Card> cardList = new ArrayList<>();
        return cardList;
    }
}

再创建一个 Colors 类表示花色

Points 类表示点数

public class Colors {
    //花色
    private static String[] colors = {"♠","♥","♦","♣"};

    public static String getColors(int index) {
        return colors[index];
    }
    public static int size(){
        return colors.length;
    }

}
public class Points {
    //点数
    private static int[] points = {1,2,3,4,5,6,7,8,9,10,11,12,13};

    public static int getPoints(int index) {
        return points[index];
    }
    public static int size(){
        return points.length;
    }
}

通过这个类的静态方法返回一个 List<Card> 类对象

public static List<Card> BuyCard(){
        List<Card> cardList = new ArrayList<>();
        for (int i = 0; i < Colors.size(); i++) {
            for (int j = 0; j < Points.size(); j++) {
            Card card = new Card(Colors.getColors(i),Points.getPoints(j));
            cardList.add(card);
            }
        }
        return cardList;
    }

在通过循环给每张牌进行 colorpoint 的赋值

public static List<Card> BuyCard(){
        List<Card> cardList = new ArrayList<>();
        for (int i = 0; i < Colors.size(); i++) {
            for (int j = 0; j < Points.size(); j++) {
            Card card = new Card(Colors.getColors(i),Points.getPoints(j));
            cardList.add(card);
            }
        }
        return cardList;
    }

再将牌放入数组中

打印出来看看

public static void main(String[] args) {
        List<Card> cardList = CardList.BuyCard();
        System.out.println(cardList);
    }

 (仅展示部分)

那么生成一副牌的逻辑就完成了


现在要洗乱这副牌

其实就是交换 cardlist 中存放的牌的位置

即两个下标的数据互换

而要随机洗乱就要生成随机数

可以使用 Random

Random random = new Random();

random.nextInt();

random.nextInt() 传入一个整形 n 可以限制只生成 0~n 之间的整数

那么可以遍历 cardlist 

将遍历过程中的下标作为限制传入

这里选择从尾部开始遍历

private static void shuffle(List<Card> cardList) {
        Random random = new Random();
        for (int i = cardList.size() - 1; i > 0; i--) {
            int index = random.nextInt(i);
        }
    }

然后需要有一个交换的操作

可以通过 List 中的 set 方法

将交换的操作封装成一个方法

  private static void swap(List<Card> cardList, int index1, int index2) {
        Card tmp = new Card();
        tmp = cardList.get(index1);
        cardList.set(index1, cardList.get(index2));
        cardList.set(index2, tmp);
    }

放到生成牌的方法中 

   public static List<Card> BuyCard() {
        List<Card> cardList = new ArrayList<>();
        for (int i = 0; i < Colors.size(); i++) {
            for (int j = 0; j < Points.size(); j++) {
                Card card = new Card(Colors.getColors(i), Points.getPoints(j));
                cardList.add(card);
            }
        }
        shuffle(cardList);
        return cardList;
    }

测试一下看下行不行

public static void main(String[] args) {
        List<Card> cardList = CardList.BuyCard();
        System.out.println(cardList);
    }

(仅展示部分)

可以看到顺序确实是被洗乱了


发给三个人,每人一开始有五张

可以把玩家看成是一个专门存放 List<Card> 类对象的 List

cardlist 中摸牌就是 add

    public static void main(String[] args) {
        List<Card> cardList = CardList.BuyCard();
     List<List<Card>> player= new ArrayList<>();//人
        for (int i = 0; i < 3 ; i++) {
            //i表示人
            List<Card> list = new ArrayList<>();
            for (int j = i * 5; j < i * 5 + 5; j++) {
               list.add(cardList.get(j));
            }
            player.add(list);
            System.out.println(player.get(i));
        }
    }

感谢观看

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/697411.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

上汽集团25届暑期实习测评校招笔试题库已发(真题)

&#x1f4e3;上汽集团 25届暑期实习测评已发&#xff0c;正在申请的小伙伴看过来哦&#x1f440; ㊙️本次实习项目面向2025届国内外毕业生&#xff0c;开放了新媒体运营、销售策略、市场运营、物流、质量分析等岗位~ ✅测评讲解&#xff1a; &#x1f449;测评自收到起需在…

利用streamlit结合langchain_aws实现claud3的页面交互

测试使用的代码如下 import streamlit as st from langchain_aws import ChatBedrockdef chat_with_model(prompt, model_id):llm ChatBedrock(credentials_profile_name"default", model_idmodel_id, region_name"us-east-1")res llm.invoke(prompt)re…

市值超越苹果,英伟达的AI崛起与天润融通的数智化转型

Agent&#xff0c;开启客户服务新时代。 世界商业格局又迎来一个历史性时刻。 北京时间6月6日&#xff0c;人工智能芯片巨头英伟达&#xff08;NVDA&#xff09;收涨5.16%&#xff0c;总市值达到3.01万亿美元&#xff0c;正式超越苹果公司&#xff0c;成为仅次于微软&#xf…

C++ 命名空间|缺省参数|函数重载

一、命名空间 1.什么是命名空间 命名空间&#xff08;namespace&#xff09;是C中的一种机制&#xff0c;用来解决不同代码库之间的命名冲突问题。 先来看一个例子&#xff1a; #include <iostream>void print() {std::cout << "Hello from print()"…

Polar Web【简单】upload

Polar Web【简单】upload Contents Polar Web【简单】upload思路EXPPythonGo 运行&总结 思路 如题目所说&#xff0c;本题考查的是文件上传漏洞的渗透技巧。 打开环境&#xff0c;发现需要上传的是图片文件&#xff0c;故考虑使用截取数据包进行数据修改进行重放。在重发器…

Java面向对象-方法的重写、super

Java面向对象-方法的重写、super 一、方法的重写二、super关键字1、super可以省略2、super不可以省略3、super修饰构造器4、继承条件下构造方法的执行过程 一、方法的重写 1、发生在子类和父类中&#xff0c;当子类对父类提供的方法不满意的时候&#xff0c;要对父类的方法进行…

蓝牙安全入门——两道CTF题目复现

文章目录 蓝牙安全入门题目 low_energy_crypto获取私钥解密 题目 蓝牙钥匙的春天配对过程配对方法密钥分发数据加密安全漏洞和保护实际应用实际应用 蓝牙安全入门 &#x1f680;&#x1f680;最近一直对车联网比较感兴趣&#xff0c;但是面试官说我有些技术栈缺失&#xff0c;所…

一文带你轻松掌握Java数组定义和声明

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。运营社区&#xff1a;C站/掘金/腾讯云&#xff1b;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一…

【Redis】解决 Redis 运行在 Protected Mode 下的 DENIED 错误:消除 Redis 受保护模式的完美方案

【Redis】解决 Redis 运行在 Protected Mode 下的 DENIED 错误&#xff1a;消除 Redis 受保护模式的完美方案 大家好 我是寸铁&#x1f44a; 总结了一篇【Redis】解决 Redis 运行在 Protected Mode 下的 DENIED 错误&#xff1a;消除 Redis 受保护模式的完美方案✨ 喜欢的小伙伴…

优质免费的 5 款翻译 API 接口推荐

当谈到翻译API时&#xff0c;我们通常指的是一种编程接口&#xff0c;它允许开发者将文本从一种语言翻译成另一种语言。这些API通常由专业的翻译服务提供商提供&#xff0c;如谷歌翻译 API、实时翻译API、腾讯翻译API、DeepL翻译API、Azure翻译API等。 这些API通常提供多种语言…

【Linux文件篇】优化文件读写,加速数据处理策略——缓冲区

W...Y的主页 &#x1f60a; 代码仓库分享 &#x1f495; 前言&#xff1a;我们已经复习了C语言中的接口&#xff0c;并且学习了许多文件系统调用&#xff0c;了解了文件描述符以及重定向。今天我们继续学习文件缓冲区的相关内容。 缓冲区 在学习C语言时&#xff0c;我们经常…

codeforce round951 div2

A guess the maximum 问题&#xff1a; 翻译一下就是求所有相邻元素中max - 1的最小值 代码&#xff1a; #include <iostream> #include <algorithm>using namespace std;const int N 5e4;int a[N]; int n;void solve() {cin >> n;int ans 0x3f3f3f3f;…

贪心算法06(leetcode738,968)

参考资料&#xff1a; https://programmercarl.com/0738.%E5%8D%95%E8%B0%83%E9%80%92%E5%A2%9E%E7%9A%84%E6%95%B0%E5%AD%97.html 738. 单调递增的数字 题目描述&#xff1a; 当且仅当每个相邻位数上的数字 x 和 y 满足 x < y 时&#xff0c;我们称这个整数是单调递增的。…

MySQL普通表转换为分区表实战指南

码到三十五 &#xff1a; 个人主页 引言 本文将详细指导新手开发者如何将MySQL中的普通表转换为分区表。分区表在处理庞大数据集时展现出显著的性能优势&#xff0c;不仅能大幅提升查询速度&#xff0c;还能有效简化数据维护工作。通过掌握这一技巧能够更好地应对数据密集型应…

【Bazel入门与精通】 rules之属性

https://bazel.build/extending/rules?hlzh-cn#attributes Attributes An attribute is a rule argument. Attributes can provide specific values to a target’s implementation, or they can refer to other targets, creating a graph of dependencies. Rule-specifi…

【会议推荐|权威主办】2024年人工智能和机械技术应用国际学术会议 (AIMTA 2024)

2024年人工智能和机械技术应用国际学术会议 &#xff08;AIMTA 2024&#xff09; 2024 International Academic Conference on Artificial Intelligence and Mechanical Technology Applications 【大会信息】 大会地点&#xff1a;西安 大会官网&#xff1a;http://www.icaimt…

springCloudAlibaba之服务熔断组件---sentinel

sentinel组件学习 sentinel学习sentinel容错机制使用代码方式进行QPS流控-流控规则初体验使用SentinelResource注解进行流控 通过代码方式设置降级规则-降级规则初体验sentinel控制台部署客户端整合服务端 springcloud整合sentinelQPS流控规则并发线程数-流控规则BlockExceptio…

kettle从入门到精通 第六十七课 ETL之kettle 再谈kettle阻塞,阻塞多个分支的多个步骤

想真正学习或者提升自己的ETL领域知识的朋友欢迎进群&#xff0c;一起学习&#xff0c;共同进步。由于群内人员较多无法直接扫描进入&#xff0c;公众号后台加我微信入群&#xff0c;备注kettle。 场景&#xff1a;ETL沟通交流群内有小伙伴反馈&#xff0c;如何多个分支处理完…

QT 使用资源文件的注意点

不要存放没有使用的资源文件 即使在代码中没有使用到的资源文件&#xff0c;也会编译到执行文件或者DLL里面去这样会增大它的体积。如下 在代码没有使用这个资源文件(10.4M的2k图片)&#xff0c;但是编译出来的程序有 12M左右的大小 1 假设我们有一个比较复杂的项目&#…

vAttention:用于在没有Paged Attention的情况下Serving LLM

文章目录 0x0. 前言&#xff08;太长不看版&#xff09;0x1. 摘要0x2. 介绍&背景0x3. 使用PagedAttention模型的问题0x3.1 需要重写注意力kernel0x3.2 在服务框架中增加冗余0x3.3 性能开销0x3.3.1 GPU上的运行时开销0x3.3.2 CPU上的运行时开销 0x4. 对LLM服务系统的洞察0x5…