第2章:数据结构之千万不要小瞧数组(1)

第二章 不要小瞧数组

2-1 使用Java中的数组
2-2 二次封装属于我们自己的数组
2-3 向数组中添加元素
2-4 数组中查询元素和修改元素
2-5 包含,搜索和删除


2-1 使用Java中的数组
数组概念:把数据码成一排进行存放
数组中存在一个很重要的概念:索引

  • 由于数组中每一个元素都是一个一个挨着排队存放的,那么就可以给数组中的每个元素一个编号。n个元素的索引:第一个元素的索引是0,最后一个元素的索引是n-1。有了索引,就可以快速地直接访问第i个元素是谁(如图所示)

Java中的数组如下:

public class Main {

    public static void main(String[] args) {
	// write your code here
        int[] arr = new int[10];
        for (int i = 0; i < arr.length; i++)
            arr[i] = i;
		
        int[] scores = new int[]{100, 99, 66};
        //方法一
        for (int i = 0; i < scores.length; i++)
            System.out.println(scores[i]);
        //可以修改数组中的变量
        scores[0]=98;
		//方法二
        for (int ss:scores)
            System.out.println(ss);
    }
}

2-2 二次封装属于我们自己的数组
数组最大的优点:快速查询。数组最好应用于“索引有语意”的情况,但并非所有有语意的索引都适用于数组。
举个栗子:设计一个数组,不同的数组存放不同的人的工资情况,索引到不同的人可以使用身份证号(ex. 身份证号 110103198512166666)

  • 因为数字太大了,数组需要开辟这样的一个大空间是不值当的,甚至是不可能。就算开辟出这样一个空间,对于很多空间都是浪费的。因为我可能只想要一个小组内10个人的个人情况,却要开辟出这样大的空间。

数组也可以处理“索引没有语意”的情况,在这一章,主要处理“索引没有语意”的情况数组的使用

方法:基于Java的数组,二次封装属于我们自己的数组类(动态数组)
capacity: 数组空间最多可以装多少个元素
size: 数组中实际有多少个元素
初始化数组时一个元素都没有,此时size应该等于0,相当于指向了第一个没有元素的索引data[0]

public class Array {
    // 类的成员变量都是私有的(private)
    private int[] data;
    private int size;

    // 构造函数,传入数组的容量capacity构造Array
    public Array(int capacity){
        data = new int[capacity];
        size = 0;
    }

    // 无参数的构造函数,默认数组的容量capacity=10
    public Array(){
        this(10);
    }

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

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

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

2-3 向数组添加元素
(1)向数组末尾添加元素(size位置的元素实际上就是数组末尾的元素)

// 向所有元素后添加一个新元素e
    public void addLast(int e){

        if(size == data.length)
            throw new IllegalArgumentException("AddLast failed. Array is full.")

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

(2)向指定位置添加元素
在数组元素中间添加元素时,需要从后向前依次挪一个位置,在先前的副本元素保存好之后,随后挪移的元素会覆盖之前的元素 (换句话说:移动位置并不能使该位置为空,而是有了“副本”之后,原数据可以被覆盖)

  • 检查数组的元素个数size是否超出容量,不合法抛出异常
  • 检查"插入元素的位置index"这个变量是否合法,不合法抛出异常
// 在第index个位置插入一个新元素e
    public void add(int index, int e){

        if (size == data.length)
            throw new IllegalArgumentException("Add failed. Array is full.");

        if (index < 0 || index > size)
            throw new IllegalArgumentException("Add failed. Required index >= 0 and index <= size ");

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

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

(3)在所有元素前添加一个新元素
这里要注意的是,调用了(2)的add方法,从而可以简化(1)&(2)

// 在所有元素前添加一个新元素e
    public void addFirst(int e){
        add(0,e);
    }

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

2-4 数组中查询元素和修改元素
(1)在“子类”中重写默认父类的方法
toString方法:返回对象的字符串表示
该方法重写/覆盖(@Override)了父类的toString方法(public String toString),同时在代码编写错误时,编译器会提示方法名称错误

@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();
    }

字符串最终输出形式如下:简单明了的信息表达方式(建议所有子类都重写toString方法)

(2)使用我们自己的Array对象测试一下

public class Main {

    public static void main(String[] args) {

        Array arr = new Array(20);
        for (int i = 0; i < 10; i ++)
            arr.addLast(i);
        System.out.println(arr);

        arr.add(1,100);
        System.out.println(arr);

        arr.addFirst(-1);
        System.out.println(arr);
    }
}

输出结果如下:

(3)如何获取某个索引位置的元素
在get方法中只传入index的值,返回data[index],这样做相当于对data静态数组进行了隐藏。

  • 这样只能获取index位置的元素,而不能获取整个静态数组data。好处是可以在中间加入对index是否合法的判断、也解决了未使用空间如何处理的问题。该方法使得用户永远无法去查询那些没有使用的空间的信息 (capacity>=size),从而保护数据安全)
// 获取index索引位置的元素
    int get(int index){
        if (index < 0 || index >= size)
            throw new IllegalArgumentException("Get failed. Index is illegal. Required index >= 0 and index < size ");
        return data[index];
    }

(4)如何修改某个索引位置的元素
使用set方法实现对数据的更新,同时也要检查index是否合法

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

2-5 数组中包含、搜索和删除
(1)查找数组中是否有元素e,并查询其所在的索引

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

    // 查找数组中元素e所在的索引,如果不存在元素e,则返回-1
    public int find(int e){
        for (int i = 0; i < size; i ++){
            if (data[i] == e)
                return i;
        }
        return -1;
    }

(2)从数组中删除元素

  • 从数组中删除index位置的元素
// 从数组中删除index位置的元素,返回删除的元素
    public int remove(int index){
        if (index < 0 || index >= size)
            throw new IllegalArgumentException("Get failed. Index is illegal. Required index >= 0 and index < size ");

        int ret = data[index];
        for (int i = index + 1; i < size; i ++)
            data[i-1] = data[i];
        size --;
        return ret;
    }
  • 从数组中删除第一个元素
  // 从数组中删除第一个元素,返回删除的元素
    public int removeFirst(){
        return remove(0);
    }
  • 从数组中删除最后一个元素
    // 从数组中删除最后一个元素,返回删除的元素
    public int removeLast(){
        return remove(size-1);
    }
  • 从数组中删除元素e
 // 从数组中删除元素e
    public void removeElement(int e){
        int index = find(e);
        if (index != -1)
            remove(index);
    }

使用Array对象测试一下,测试代码及输出结果如下:

// Original array: [-1, 0, 100, 1, 2, 3, 4, 5, 6, 7, 8, 9]
        arr.remove(2);
        System.out.println(arr);
        //[-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

        arr.removeElement(4);
        System.out.println(arr);
        //[-1, 0, 1, 2, 3, 5, 6, 7, 8, 9]

        arr.removeFirst();
        System.out.println(arr);
        //[0, 1, 2, 3, 5, 6, 7, 8, 9]

        arr.removeLast();
        System.out.println(arr);
        //[0, 1, 2, 3, 5, 6, 7, 8]
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值