数据结构-数组篇

数据结构-数组篇
1. 基础

‘ ‘

public class Main {
    /**
     * 数组基础
     * 索引  索引可以有语意也可以没有语意
      * @param args
     */
    public static void main(String[] args) {
        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 score:scores) {
            System.out.println(score);
        }
    }
}

数组最大的优点:快速查询
数组最好应用于‘索引有语意’的情况
但并非所有有语意的索引都适用于数组 例如:身份证号
数组也可以处理‘索引没有语意’的情况

2. 数组二次封装

基于java的数组,二次封装属于我们自己的数组类

’ ‘

public class Array {
    /*
     * 索引没有语意,如何表示没有元素
     * 如何添加元素?如何删除元素?
     * @param args
     */
    private int[] data;
    private int size;

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

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

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

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

    /**
     * 返回数组是否为空
     * @return
     */
    public boolean isEmpty(){
        return  size==0;
    }
}
3. 数组操作
  • 如何在数组中添加元素

’ ‘

/**
 * 向所有元素后添加一个新元素
 * @param e
 */
public void addLast(int e){
    /*if(size==data.length){
        throw new IllegalArgumentException("AddLast failed.Array is full");
    }
    data[size] = e;
    size++;     //data[size++]=e;*/
    add(size,e);
}

/**
 * 在第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.Require index >=0 and index <= size");
    for(int i=size-1;i>=index;i--){
        data[i + 1] = data[i];
    }
    data[index] = e;
    size++;
}

/**
 * 在所有元素前添加一个新元素
 * @param e
 */
public void addFirst(int e){
    add(0,e);
}
  • 查询和修改数组元素

’ ‘

/**
 * 获取index索引位置的元素
 */
int get(int index){
    if(index <0 || index >=size)
        throw new IllegalArgumentException("Get failed. Index is illegal");
    return data[index];
}

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

/**
 *重写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();
}

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);
}
  • 数组中的包含、搜索元素

’ ‘

/**
 * 查找数组中是否有元素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;
}
  • 删除元素

’ ‘

/**
 *从数组中删除index位置的元素,返回删除的元素
 */
public int remove(int index){
    if(index<0||index>=size)
        throw new IllegalArgumentException("Remove id failed.Index is Illegal");
    int e=data[index];
    for(int i=index+1;i<size;i++){
        data[i-1]=data[i];
    }
    size--;
    return e;
}

/**
 *从数组中删除第一个元素,返回删除的元素
 */
public int removeFirst(){
    return remove(0);
}

/**
 * 从数组中删除最后一个元素,返回删除的元素
 */
public int removeLast(){
    return remove(size-1);
}

/**
 *从数组中删除元素e
 */
public void removeElement(int e){
    int index = find(e);
    if(index != -1){
        remove(index);
    }
}

使用泛型
  • 让我们的数据结构可以放置“任何”数据类型
  • 不可以是基本数据类型,只能是类对象 (boolean,byte,char,short,int ,long,float,double)
  • 每个基本数据类型都有对应的包装类 (Boolean,Byte,Char,Short,Int,Long,Float,Double)

’ ‘

public class Array1<E> {

    private E[] data;
    private int size;


    public Array1(int capacity) {
        data = (E[])new Object[capacity];
        size = 0;
    }
    /**
 * 在第index个位置插入一个新元素e
 */
public void add(int index, E e) {
    if (size == data.length)
        throw new IllegalArgumentException("Add failed.Array is full");
    if (index < 0 || index > size)
        throw new IllegalArgumentException("Add failed.Require index >=0 and index <= size");

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

  • 动态数组:扩容(添加元素)

‘ ’

/**
 * 动态数组:扩容
 * @param args
 */
private void resize(int newCapacity){
    E[] newData = (E[])new Object[newCapacity];
    for(int i=0;i<size;i++){
        newData[i] = data[i];
    }
    data = newData;
}

if (size == data.length) {
    //  throw new IllegalArgumentException("Add failed.Array is full");
    //扩容
    resize(2 * data.length);
}
  • 缩小容量(删除时)

‘ ’

if(size==data.length /2){
    resize(data.length /2);
}

测试类

‘ ’

public class Student {
    private String name;
    private int score;

    public Student(String studentName,int studentScore){
        name = studentName;
        score = studentScore;
    }

    @Override
    public String toString(){
        return String.format("Student(name: %s,score:%d)",name,score);
    }

    public static void main(String[] args) {
        Array1<Student> arr = new Array1<>();
        arr.addList(new Student("Alice",100));
        arr.addFirst(new Student("Bob",98));
        arr.add(1,new Student("CharLie",99));
        System.out.println(arr);
    }
}

4. 时间复杂度分析

时间复杂度包括:O(1),O(n),O(lgn),O(nlogn),O(n^2)

大O描述的是算法的运行时间和输入数据之间的关系,n指元素个数

在这里插入图片描述

O(n)渐进时间复杂度,描述n趋近于无穷的情况(忽略低阶项和常数)

增:O(n)

删:O(n)

改:已知索引O(1);未知索引O(n)

查:已知索引O(1);未知索引O(n)

5. resize的复杂度分析

在这里插入图片描述

这样均摊计算,时间复杂度是O(1)的

在这个例子里,这样均摊计算,比计算最坏情况有意义,因为不是每一次都触发最坏情况

同理,removeLast操作,均摊复杂度也为O(1)

6. 复杂度震荡

同时看addLast和removeLast操作

在这里插入图片描述

出现问题的原因:removeLast时resize过于着急

解决方案:

当size==capacity/4时,才将capacity减半

remove时

‘’

if(size==data.length /4 && data.length/2!=0){
    resize(data.length /2);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值