数据结构与算法系列1之数组介绍与动态数组实现

数据结构与算法系列1之数组介绍与动态数组实现

数组基本概念介绍

本节讲解顺序

1数组的概念
2数组的定义
2.1动态初始化
2.2静态初始化
3数组中的内存划分
4两个数组指向一个地址
5两个常见问题

1数组的概念

数组是用来存储固定大小的同类型元素。

2数组的定义

2.1动态初始化

1 public class Test {
2     public static void main(String[] args) {
3         int[] arr=new int[100];
4     }
5 }

arr是数组名称 100是数组的大小

2.2 静态初始化

public class Test {
    public static void main(String[] args) {
        int[] arr=new int[] {1,2};
    }
}

该数组大小即为2

3内存角度解析数组

首先简单等等介绍一下java中的内存划分

Java内存主要划分为五部分

1栈(stack):

存放的都是方法中的局部变量,方法的运行一定要在栈中运行,
局部变量:方法的参数,或者是方法{}内部的变量
作用域:一旦超出作用域,立刻从内存中消失

2堆(Heap):

凡是new 出来的东西都在堆里
堆中的东西都有地址值:地址值为16进制 0x开头
堆中的数据都有默认值,规则:
如果是整数 0
如果是布尔 false
如果是浮点数 0.0
如果是引用数据类型 null
如果是字符 “\u000”

3方法区(Method Area):

存储.class相关的信息,包含方法信息

4本地方法栈(Natice Method Stack):

与操作系统相关

5 寄存器(pc Register):

与cpu相关

6.下面用一张图来讲解 java中new一个数组的步骤

1 public class Test {
2     public static void main(String[] args) {
3         int[] arr=new int[3] ;
4         arr[0]=10;
5         arr[1]=20;
6         System.out.println(arr[0]);
7         System.out.println(arr[1]);
8     }
9 }

第一步 int[ ] arr=new int[2];
数组名称相当于一个存储地址值的变量,指向存储在堆中的int [3]
记住凡是new出来的都在堆里


在这里插入图片描述

第二步 arr[0]=10

arr[1]=20

首先通过地址值去堆中找到该数组
在通过下标来判断这是第几个


在这里插入图片描述

)
第三步输出

第三步与第二步同理这里就不继续叙述

7. 两个数组指向一个变量

两个数组指向同一个变量,即栈中两个变量存储的值相同

1 public class Test {
2     public static void main(String[] args) {
3         int[] arr=new int[2] ;
4         int[] arr2=arr;
5         System.out.println(arr);
6         System.out.println(arr2);
7     }
8 }

运行结果

在这里插入图片描述

内存图解


在这里插入图片描述

8.两个常见问题

8.1数组索引越界

public class Test {
    public static void main(String[] args) {
        int[] arr=new int[2] ;
        System.out.println(arr[3]);
    }
}

抛出异常


在这里插入图片描述

为了防止越界我们可以引用length方法来解决一些问题方法

public class Test {
    public static void main(String[] args) {
        int[] arr=new int[2] ;
        System.out.println(arr.length);
    }
}

运行结果


在这里插入图片描述

8.2 空指针异常

所有的引用类型变量都可以可以赋值为null,这就会导致空指针异常

1 public class Test {
2     public static void main(String[] args) {
3         int[] arr=null ;
4         System.out.println(arr[0]);
5 
6     }
7 }

异常抛出

在这里插入图片描述

二维数组

在内存中的存放

二维数组在概念上是二维的,而存储器单元是按一维线性排列的。 如何在一维存储器中存放二维数组,可有两种方式:一种是按行排列, 即放完一行之后顺次放入第二行。另一种是按列排列, 即放完一列之后再顺次放入第二列

以C语言为例
**
在C语言中,二维数组是按行排列的

例如: int [3][4];

其二维数组示意图如图1所示:

在这里插入图片描述

图1 a[3][4]二维数组示意图

在图1中,按行顺次存放,先存放a[0]行,再存放a[1]行,最后存放a[2]行。每行中有四个元素也是依次存放。由于数组a说明为int类型,该类型占4个字节的内存空间,所以每个数组元素均占有4个字节。 假设数组a的起始地址为2000,则该二维数组在内存在的存放方式如图2所示。

图2 a[3][4]二维数组的存放方式


在这里插入图片描述

动态数组的实现

什么是动态数组?

动态数组

顾名思义,动态数组即可以动态扩容的数组,一般的数组是不能扩容的,及在创建数组对象的时候就规定了数组的大小,规定数组是多大就是多大,后期不可以存储多余的元素

动态数组的优点

动态数组的好处也显而易见:
1.动态的增加和减少元素
2.实现collection和list接口
3.灵活设置数组的大小
java中已经给我们封装好了一个动态数组Arraylist的类,我们可以直接使用,其内部有许多方法,我们先来看看有什么方法,下面仅仅讲我们经常使用到的方法那些不怎么使用的我们在这就不讲了:

int size();元素的数量
boolean isEmpty();是否为空
boolean contains(E element); 判断是否包含某个元素
void add(E element) ;添加元素到最后
E get(int index);返回index对应位置的元素
E set(int index,E element);往index位置添加元素
void add(int index,E element);往index位置添加元素
E remove(int index); 删除index位置对应的元素
int indexOf(E element); 查看元素的位置
void clear();清除所有元素

接下来我们逐一讲解这些方法

定义的变量

//元素的数量
    private int size;
    //存储元素
    private E[] elements;
    //初始化大小
    private static  final int DEFAULT_CAPACITY=16;
    //元素没有找到时的放回值
    private static  final int ELEMENT_NOT_FOUND=-1;

构造方法

//自定义大小
    public ArrayList(int capacity){
        //如果传入的大小小于默认数组的大小,则使用默认的大下
        capacity= (capacity<DEFAULT_CAPACITY)?DEFAULT_CAPACITY:capacity;
        elements=(E[])new Object[capacity];
    }
    //默认大小的构造方法
    public  ArrayList(){
        this(DEFAULT_CAPACITY);
    }

判断index的范围有没有越界

public void rangeCheak(int index){
        if (index<0||index>size){
            outofBounds(index);
        }
    }
 

获取指定位置的元素

public E get(int index){
        rangeCheak(index);
        return  elements[index];
    }

重新设定指定位置的元素

public E set(int index,E element){
        //检查插入位置是否合法
        rangeCheak(index);
        //返回原来的元素
        E oldelement1 = elements[index];
        //插入新的元素
        elements[index]=element;
        return oldelement1;
    }

判断是否为空

public boolean isEmpty(){
        return size==0;
    }

返回元素的数量

public int size(){
        return  size;
    }

判断是否包含某个指定元素

public boolean contains(E element){
        return indexOf(element)!=ELEMENT_NOT_FOUND;
    }

返回指定元素的位置

public int indexOf(E element){
     if (element==null){
         for (int i = 0; i < size; i++) {
             if (elements[i]==null){
                 return  i;
             }
         }
     }else{
         for (int i = 0; i < size; i++) {
             if (element.equals(elements[i])){
                 return i;
             }
         }
     }
     return  ELEMENT_NOT_FOUND;
    }

在末尾插入元素

public void add(E element){
        add(size,element);}

在指定位置插入元素

public void   add(int index,E element){
        //检查范围
        rangeCheakForadd(index);
        //判断容量是否足够
        ensureCapacity(size+1);
        for (int i = size; i > index; i--) {
            elements[i]=elements[i-1];
        }
        elements[index]=element;
        size++;
    }

检查插入范围

public void rangeCheakForadd(int index){
        if (index<0||index>size){
            outofBounds(index);
        }
    }

移除指定位置的元素

public  E remove(int index){
        //检查范围
        rangeCheak(index);
        E removeElement = elements[index];
        for (int i=index+1;i<size;i++) {
            elements[i-1]=elements[i];
        }
        elements[--size]=null;
        return removeElement;
    }

清除所有元素

public void clear(){
for (int i = 0; i < size; i++) {
elements[i]=null;
}
}
[图片上传失败...(image-c8c984-1613461950845)]

其实动态数组最重要的一个方法就是扩容,下面来重点讲解

public void ensureCapacity(int capacity){
        int oldcapacity = elements.length;
        //如果比原来小则不做改变
        if (oldcapacity>= capacity){
            return;
        }
        //使用位运算,速度更快
        //我这里用的是二倍扩容,这里的扩容大小可以自己来设置,以达到最高的使用率
        int newCapacity=oldcapacity+(oldcapacity>>1);
        E[] newElements = (E[]) new Object[newCapacity];
        for (int i = 0; i < size; i++) {
            newElements[i]=elements[i];
        }
        //将elements的地址赋值新的地址
        elements=newElements;
        System.out.println(oldcapacity+"扩容为:"+newCapacity);
    }

复写toString()方法

@Override
    public String toString(){
        //使用StringBuilder
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append('[');
        for (int i = 0; i < size; i++) {
            if (i!=0){
                stringBuilder.append(",");
            }
            stringBuilder.append(elements[i]);
        }
        stringBuilder.append(']');
        return  stringBuilder.toString();
    }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容