数据结构-ArrayList

目录

线性表

顺序表

ArrayList

ArrayList的使用

ArrayList的构造方法

ArrayList的常用方法

ArrayList的遍历

实现简单的ArrayList

洗牌算法

删除公共字符串问题

杨辉三角


线性表

线性表是n个具有相同特性的数据元素的有限序列.线性表是一种在实际中广泛使用的数据结构.常见的线性表有顺序表,链表,栈和队列等等.

线性表在逻辑上是线性结构,也就是说是连续的一条直线.但是在物理结构上并不一定是连续的,线性表在物理上存储的时候,通常是以数组和链式结构的形式存储.

顺序表

顺序表是一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下用数组存储.在数组上完成数据的增删查改.

ArrayList

在集合框架中,ArrayList是一个普通的类,实现了List接口.

1. ArrayList 实现了 RandomAccess 接口,表明 ArrayList 支持随机访问
2. ArrayList 实现了 Cloneable 接口,表明 ArrayList 是可以 clone
3. ArrayList 实现了 Serializable 接口,表明 ArrayList 是支持序列化的
4. Vector 不同, ArrayList 不是线程安全的,在单线程下可以使用,在多线程中可以选择 Vector或者 CopyOnWriteArrayList
5. ArrayList 底层是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序表

ArrayList的使用

ArrayList的构造方法

 第二种构造方法,实现了collection接口的都可以传进来.但是需要注意的是E是泛型通配符的上界,只有类型相同是E或者是E的子类的时候,才可以传进来.

当我们调用不带参数的构造方法的时候,只有第一个add的时候,我们才会为其分配大小为10的内存.

扩容是采用1.5倍的扩容方式.如果用户所需大小超过预估的1.5倍大小,则按照用户所需大小进行扩容,并且在真正的扩容之前会检测能否扩容成功,防止太大导致扩容失败.扩容是采用copyOf进行扩容.


ArrayList的常用方法

subList方法需要注意的是:截取的部分并没有创建新的顺序表,而是新的引用(截取的部分)还是指向了原来的顺序表.所以修改截取部分的内容就是将原来顺序表的内容给修改了.

对于remove需要注意的是,编译器会将我们传入的int类型的值统一认定为是下标而不是实际内容的值.

比如有一个ArrayList:[1,7]两个元素.

public static void main(String[] args) {
    ArrayList<Integer> arrayList = new ArrayList<>();
    arrayList.add(1);
    arrayList.add(7);
    System.out.println(arrayList);
    //我们要删除值为7的元素
    //arrayList.remove(7);//编译器会把7当成下标,而不是实际的值,所以我们执行起来会报越界错.
    //正确的做法是传入一个引用类型
    arrayList.remove(new Integer(7));
}

ArrayList的遍历

ArrayList的遍历有三种:for循环+下标的方式,foreach,和迭代器.

public static void main(String[] args) {
    ArrayList<Integer> arrayList = new ArrayList<>();
    arrayList.add(1);
    arrayList.add(2);
    arrayList.add(3);
    arrayList.add(4);
    //for循环+下标
    for (int i = 0; i < arrayList.size(); i++) {
        System.out.printf(arrayList.get(i)+" ");
    }
    System.out.println();
    //foreach
    for (int x:arrayList) {
        System.out.printf(x+" ");
    }
    System.out.println();
    //使用迭代器
    //必须实现了Iterable接口
    Iterator<Integer> it = arrayList.iterator();
    while (it.hasNext()){
        //it指向上一个数据
        //it.next()会使it访问下一个元素并且向下走一步
        System.out.printf(it.next()+" ");
    }
    System.out.println();
}

实现简单的ArrayList

import java.util.Arrays;

public class MyArrayList {
    public int[] elem;//数组
    public int usedSize;//记录有效的数据的个数
    public static final int DEFAULT_SIZE = 10;

    public MyArrayList(){
        this.elem = new int[DEFAULT_SIZE];
    }

    // 打印顺序表
    public void display() {
        for (int i = 0;i < this.usedSize; i++){
            System.out.print(this.elem[i]+" ");
        }
        System.out.println();
    }
    // 新增元素,默认在数组最后新增
    public void add(int data) {
        //1.检查当前的顺序表是不是满了
        if (isFull()){
            //2.如果满了就要扩容
            this.elem = Arrays.copyOf(this.elem,2*this.elem.length);
        }
        //3.
        this.elem[usedSize] = data;
        //4.
        usedSize++;
    }

    public boolean isFull(){
        if (this.usedSize > elem.length){
            return true;
        }
        return false;
    }

    // 在 pos 位置新增元素
    //负数下标不可以
    //越过数组的长度不可以
    //不能隔着元素放
    public void add(int pos, int data) throws PosWrongfulException {
        if (isFull()){
            System.out.println("满了!");
            this.elem = Arrays.copyOf(this.elem,2*this.elem.length);
        }
        if (pos < 0 || pos > this.usedSize){
            System.out.println("pos的位置不合法!");
            throw new PosWrongfulException("Pos位置不合法!");
        }

        //pos一定是合法的
        //1.开始挪动数据
        for (int i = this.usedSize-1; i >= pos; i--) {
            this.elem[i+1] = this.elem[i];
        }
        //2.插入数据
        this.elem[pos] = data;
        //3.usedSize++
        usedSize++;
    }
    // 判定是否包含某个元素
    public boolean contains(int toFind) {
        for (int i = 0; i < this.usedSize; i++) {
            if (elem[i] == toFind){
                return true;
            }
        }
        return false;
    }
    // 查找某个元素对应的位置
    public int indexOf(int toFind) {
        for (int i = 0; i < this.usedSize; i++) {
            if (this.elem[i] == toFind){
                return i;
            }
        }
        return -1;
    }
    // 获取 pos 位置的元素
    public int get(int pos) {
        //判空
        if (isEmpty()){
            throw new EmptyException("当前顺序表为空!");
        }
        //判断pos位置的合法性
        if (pos < 0 || pos >= this.usedSize){
            throw new PosWrongfulException("get获取元素的时候,Pos位置不合法!");
        }
        return this.elem[pos];
    }
    //判空
    public boolean isEmpty(){
        return size() == 0;
    }
    // 给 pos 位置的元素更新为 value
    public void set(int pos, int value) {
        //判空
        if (isEmpty()){
            throw new EmptyException("当前顺序表为空!");
        }
        //判断pos位置的合法性
        if (pos < 0 || pos >= this.usedSize){
            throw new PosWrongfulException("pos位置不合法!");
        }
        this.elem[pos] = value;
    }
    //删除第一次出现的关键字key
    public void remove(int key) {
        if (isEmpty()){
            throw new EmptyException("顺序表为空!");
        }
        int index = this.indexOf(key);
        if (index == -1){
            System.out.println("没有这个数字!");
            return;
        }
        // 9 3 4 8 6
        // 0 1 2 3 4
        //usedSize==5,i<4,i最大到3
        //index==4的情况下直接不走循环,usedSize--即可.
        for (int i = index; i <size()-1 ; i++) {
            this.elem[i] = this.elem[i+1];
        }
        usedSize--;
    }
    // 获取顺序表长度
    public int size() { return this.usedSize; }
    // 清空顺序表
    public void clear() {
        this.usedSize = 0;
    }

}

洗牌算法

使用ArrayList实现三个人轮流摸牌的过程.

1.先买一副扑克牌,四种花色,每种花色13张.

2.洗牌

3.揭牌,每人按序摸一张,总共摸五轮.

public class Poker {
    //花色
    private String suit;
    //数值
    private int rank;

    public Poker(String suit, int rank) {
        this.suit = suit;
        this.rank = rank;
    }

    public void setSuit(String suit) {
        this.suit = suit;
    }

    public void setRank(int rank) {
        this.rank = rank;
    }

    public String getSuit() {
        return suit;
    }

    public int getRank() {
        return rank;
    }

    @Override
    public String toString() {
        return "["+"suit= " + suit + ", rank=" + rank +"]";
    }
}
import java.util.ArrayList;
import java.util.List;
import java.util.Random;



//1.买一副扑克牌
//2.洗牌
//3.三个人轮流揭牌,每个人揭5次
public class Pokers {
    public static final String[] SUITS = {"♥","♠","♣","♦"};

    /**
     *买一副扑克牌
     */

    public static List<Poker> bugPokers(){
        List<Poker> pokerList = new ArrayList<>();
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 13; j++) {
                String suit = SUITS[i];
                int rank = j;
                Poker poker = new Poker(suit,rank);
                pokerList.add(poker);
            }
        }
        return pokerList;
    }
    //洗牌
    public static void shuffle(List<Poker> list){
        Random random = new Random();
        for (int i = list.size()-1; i > 0 ; i--) {
            int index = random.nextInt(i);
            swap(list,i,index);
        }
    }

    private static void swap(List<Poker> list, int i, int index) {
        Poker tmp = list.get(i);
        list.set(i,list.get(index));
        list.set(index,tmp);
    }

    public static void main(String[] args) {
        List<Poker> list = bugPokers();
        System.out.println("买牌:"+list);
        //洗牌
        shuffle(list);
        System.out.println("洗牌:"+list);
        //揭牌 3个人 每个人轮流抓五张牌
        //1.如何描述3个人
        List<Poker> hand1 = new ArrayList<>();
        List<Poker> hand2 = new ArrayList<>();
        List<Poker> hand3 = new ArrayList<>();
        //2.如何区分往哪个人手里送牌
        List<List<Poker>> hand = new ArrayList<>();
        hand.add(hand1);
        hand.add(hand2);
        hand.add(hand3);
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 3; j++) {
                List<Poker> handTmp = hand.get(j);
                handTmp.add(list.remove(0));
            }
        }
        for (int i = 0; i < hand.size(); i++) {
            System.out.println("第"+(i+1)+"个人的牌是:"+hand.get(i));
        }
        System.out.println("剩余的牌是: "+ list);
    }
}

删除公共字符串问题

//删除第一个字符串当中出现的第二个字符串中的字符,使用集合
//str1:welcome to bit
//str2:come
//输出wel t bit
//需要注意的是contains方法传的是一个字符串,字符+""就是将字符传为字符串,也可以字符包装类的toString方法将一个字符转为字符串
public static void main(String[] args) {
    String s1 = "welcome to bit";
    String s2 = "come";
    ArrayList<Character> arrayList = new ArrayList<>();
    for (int i = 0; i < s1.length(); i++) {
        if (!s2.contains(s1.charAt(i)+"")){
            arrayList.add(s1.charAt(i));
        }
    }
    for (Character a:arrayList) {
        System.out.printf(a.toString());
    }
}

杨辉三角

public List<List<Integer>> generate(int numRows) {
    List<List<Integer>> ret = new ArrayList<>();
    List<Integer> list1 = new ArrayList<>();
    list1.add(1);
    ret.add(list1);
    for (int i = 1; i <numRows ; i++) {
        //当前行
        List<Integer> curRow = new ArrayList<>();
        curRow.add(1);//一行中开始的1
        //前一行
        List<Integer> prevRow = ret.get(i-1);
        //中间位置需要计算
        for (int j = 1; j < i; j++) {
            int num = prevRow.get(j)+prevRow.get(j-1);
            curRow.add(j,num);
        }
        curRow.add(1);//一行中最后的那个1
        ret.add(curRow);
    }
    return ret;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值