[笔记]算法复习笔记---数组、集合、散列表(上)

数组是数据结构中最基础的存储方式之一,集合是数组的延伸,散列表,又称哈希表(Hash Table),许多高级语言中都是在数组的基础上实现的,当然还有其他实现形式。

一、数组的特点:

1、定长

数组的的长度是固定的,数组的长度在声明时候已经确定,在使用的时候发现不够用,只能重新声明一个数组

2、按照顺序访问

在访问数组中某一个元素的时候,只能从第一个元素按照顺序访问,知道访问到指定位置的元素。虽然在写程序时候可以通过下标直接访问指定位置的元素,但计算机实际上还是按照顺序访问的。

二、升级版数组——集合

数组的致命缺点就是长度固定,如果我们一开始不确定,就变得很麻烦了。有可能你会说,那就来个动态的呗,动态数组,在C语言中有一种实现动态数组的方式,就是用Malloc函数动态开辟内存空间, 但在这里我要说的是另一种方式,集合

什么是集合?

我的理解就是长度可变的列表(动态数组)

下面这些都是集合:

  • 列表:一般的有序集合,特点是没有顺序,比如链表、队列、栈。
  • :一般是无序的集合,特点就是没有顺序不能重复,多数语言都是散列表实现的,支持对集合进行添加、删除、查找等操作。
  • 多重集:一般是无序的集合,但是数据可以有重复的值,支持对集进行添加、删除、查找包含、查找一个元素 在集合中的个数等操作。多重集通过排序可以转换为列表。
  • 关联数组:多数语言也是用散列表实现的,就是可以通过键(key)获取到值(value)。也是没有顺序的
  • 树、图:树、图 同样是集合

那集合是怎么实现的呢?

既然集合是长度可变的数组,那么我们就可以用数组实现集合。

下面,用ArrayList实现简单的集合,也可以叫它变长数组。

ArrayList插入数据的流程

public class ArrayList {

    private static final int INITIAL_SIZE = 10;

    private int size = 0;

    private int[] array;

    public ArrayList() {

        array = new int[INITIAL_SIZE];
    }

    public ArrayList(int initial){

        if (initial <= 0) {
            initial = INITIAL_SIZE;
        }

        array = new int[INITIAL_SIZE];

    }
    /**
     * 添加一个元素
     * @param num
     */
    public void add(int num) {

        if (size == array.length) {
            array = Arrays.copyOf(array, size*2);
        }

        array[size++] = num;

    }

    /**
     * 获取指定位置的元素值
     * @param i
     */
    public int get(int i) {

        if (i >= size) {
            throw new IndexOutOfBoundsException("获取的元素位置超过了最大长度");
        }

        return array[i];
    }
    /**
     * 设置指定位置的元素值
     * @param i
     * @param num
     * @return  指定的这个位置 之前的值
     */
    public int set(int i,int num) {

        int oldNum = get(i);
        array[i] = num;
        return oldNum;
    }
    /**
     * 获取变长数组的长度
     * @return
     */
    public int size() {
        return size;
    }

}
public class ArrayListTest {

    public static void main(String[] args) {

        ArrayList arrayList = new ArrayList(1);
        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(3);
        arrayList.add(4);
        arrayList.add(5);

        System.out.println(arrayList.get(3));//获取数组下标为3的值,也就是第4个位置的值,打印4
        arrayList.set(3, 9);//设置第4个位置的值为9
        System.out.println(arrayList.get(3));//再次获取,这次打印9
        System.out.println(arrayList.size());//变长数组的长度为5,实际上内部数组长度为8,在add(2)和add(5)时,分别进行了长度翻倍和数组复制

    }

}

集合的特点:

  1. 集合的特点,跟它的实现有关,那就是变长,变长是相对而言,内部还是通过数组实现的,只是在不够用的时候根据策略生成一个更长的数组,把旧数组复制到新数组里。
  2. 在正常情况下,会有两个系统开销,一个是数组总是比我们实际使用的长度长,因此存在空间浪费,另一个是数组不够长的时候,需要新建一个更长的数组,同时把旧数组的数据复制到新数组中,这个操作比较消耗系统的性能。
    3.

数组与变长数组的性能

  • 虽然集合这个变长数组比普通数组更高级一些,但本质上还是基于数组实现的,所以和数组的性能差不多。
  • 对数组的操作,并不是我们看到的那么直观,计算机需要根据我们的操作寻找指定位置,在数组中添加元素,修改元素,获取元素的时间复杂度都是O(n).
  • 变长数组也有性能损耗的情况,在插入元素时发现其中固定数组的长度不够用,需要新建数组,复制数据,这个过程中会有性能损耗。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值