• 数据结构与算法3-数组


    目录

    题目

    数组的定义

    数组的特点

    数组的表现形式

    数组的优缺点

    数组方法的实现

    数组的应用

    Java内存

    整理总结


    题目

    开始前,我们来看一道题:

    假设有这样一个需求,有一个文件,文件里包含了公司所有客户的年龄数据,现在需要统计每一个年龄段有多少人,以便后续开展活动,给定的主机硬件为单台主机,2core+2G,文件大小为6G,在不使用现有的容器的情况下,如何最高效解决这个问题?所谓容器包括map,set等

    如果不限制硬件资源以及容器技术等,那么可能上来我们直接拆开,将单个文件拆为多个文件,最后合并处理,但,限制了之后,就需要思考怎么做了

    OK,现在我们来开始想办法解决,因为内存只有2G,所以不能整个文件都取出来,也不能进行排序,毕竟排序的前提是数据都在内存里

    我们再来看一下已知条件,文件里的是客户的年龄数据,人类的年龄数据,是一个确定的范围,就算是很长寿,那也是0-200之间对吧

    那,我们创建一个长度为200的数组,索引位0代表0岁,数据0位的值,代表0岁的人数,以此类推,一行一行读取文件内容,每次将对应的位置数量追加,直到文件处理完成,时间复杂度为O(n)

    数组的定义

    什么是数组,所谓数组,就是有序的元素序列,当然,这个有序并非我们通俗意义上的大小

    如果将有限个类型相同的变量的集合明明,那么,这个名称就是数组名,组成数组的各个变量称做数组的分量,也称为数组中的元素,用于区分数组中各个元素的数字编号称为下标

    数组通常用Array表示,也称为线性表

    数组的特点

    1、数组是相同类型元素的集合,一定是相同类型,是int,那就都是int,不可能有int有string

    2、数组中的元素是有先后顺序的,并且,他们在内存中也是按照这个先后顺序连续放在一起的

    3、数组的元素用整个数组的名字加上自己在数组中的位置来表示,比如第一个元素,那就是arr[0]

    数组的表现形式

    数组在表现形式上,分为一维数组和多维数组,一维数组就是最常用的,比如 int a[],而多维数组,相信大部分人也用过int a[][],如果没用过的话,想象一下矩阵

    数组的优缺点

    数组的结构决定了它增删慢,查找快的特点

    比如我要在某个位置增加或删除一个数据,那这个变更位点的后面位置全都得变化,所以比较慢

    而正是因为这个特点,数组的查找快,比如我要访问第五个数组,我直接访问第五个位置就好

    数组方法的实现

    让我们来实现一下数组的常用方法,也就是增删改查

    1. public class Test {
    2. private int[] arr;
    3. private int index;
    4. public Test(int size) {
    5. this.index = 0;
    6. this.arr = new int[size];
    7. }
    8. public void printArg() {
    9. for (int i = 0; i < arr.length; i++) {
    10. System.out.println(arr[i]);
    11. }
    12. }
    13. public int findArg(int index) {
    14. return arr[index];
    15. }
    16. public void update(int index, int to) {
    17. arr[index] = to;
    18. }
    19. public void insert(int index, int to) {
    20. int length = arr.length;
    21. int endIndex = index;
    22. if (endIndex++ < length) {
    23. for (int i = length - 1; i > index; i--) {
    24. arr[i] = arr[i - 1];
    25. }
    26. arr[index] = to;
    27. this.index++;
    28. } else {
    29. throw new RuntimeException("can't insert,index is out of arr's size");
    30. }
    31. }
    32. public void delete(int index) {
    33. int length = arr.length;
    34. for (int i = index; i < length; i++) {
    35. if (i != length - 1) {
    36. arr[i] = arr[i + 1];
    37. } else {
    38. arr[i] = 0;
    39. }
    40. }
    41. this.index--;
    42. }
    43. }

    当然,这儿只是简单写了写,没有做扩容

    数组的扩容,本质上还是重新申请地址,然后将旧数组的数据全都放到新数组里

    数组的应用

    说到这儿,Java中的array list,本质也是数组,但是对比数组,大家用的多的还是array list,因为array list是jdk帮我们封装好的,已经实现了自动扩容等等的操作,可以节省我们很多功夫,如果直接用数组,相关的方法肯定是需要我们自己去实现的

    在应用中,一定要注意,小心越界

    Java内存

    Java中内存分为两种,堆内存和栈内存,都是Java用来存放数据的地方

    new出来的对象和数组都在堆内存

    引用对象存放在栈内存

    堆栈的区别:

    • 栈比堆块
    • 栈内存的数据可以共享,主要存一些基本数据类型,比如 int a =3; 流程就是现在栈内创建变量a,然后给变量a赋值,但是并不会立刻创建一个3,而是先在栈内寻找是否有3,如果有,直接将指针指向3,没有,就增加一个3

    举个例子

    1. String str1 = "abc";
    2. String str2 = new String ("abc");
    3. System.out.println(str1 == str2);

    这是个false,因为str2是new出来的,而==对于引用类型来说,对比的是地址值

    再来一个容易错的地方

    1. String str1 = "ja";
    2. String str2 = "va";
    3. String str3 = "java";
    4. String str4 = str1 + str2;
    5. System.out.println(str3 == str4);

    这个的答案也是false,不要看起来值相同

    问题出在这个加号上 ➕

    Java重载了加号,在底层调用了stringbuilder,而stringbuilder是创建新对象

    内存和数组也有关系,比如,数组为什么从0开始

    假设创建了一个数组,申请了内存空间,是1001,1002,1003,.......

    arr[0] 就应该存储在1001

    arr[1]就应该存储在1002

    对应的,结合下标,可以写成

    arr[0] -> 1001 -> 1001+0

    arr[1] -> 1002 -> 1001+1

    这样,拿到第一个地址,就可以拿到后续所有地址

    如果不从0开始,假设从1开始

    arr[1] -> 1001 -> 1001+(1-1)

    arr[1] -> 1002 -> 1001+(2-1)

    从性能上来说,这种减号运算性能更差

    数组的内存地址,可以用如这样表达

    初始内存地址 + 数组下标*数据的长度

    整理总结

    数组是一个最基础最简单的数据结构,存储的相同的数据类型

    用数组的时候,记得关注下标,下标是数组最优的一个特点

    数组增删慢,查找快

  • 相关阅读:
    JavaScript 浏览器对象模型BOM 概念
    公司如何实现多套环境的自动化测试?
    打破信息获取的界限:灵雀云推出自主研发智能文档机器人KnowledGenie
    数据结构第一章:部分答案
    删除 “显示不存在的文件夹” 的文件夹
    php:如何在curl方式下url请求域名使用指定ip地址来访问某个服务器
    JVM命令行监控工具
    pandas 笔记:get_dummies分类变量one-hot化
    进阶指针(一)
    服务器百万并发的原理与实现
  • 原文地址:https://blog.csdn.net/weixin_46097842/article/details/126110971