javase - 顺序表

javafx顺序播放列表_顺序表

第一章 javase 顺序表学习




文章目录

  • javase - 顺序表
  • 前言
  • 一、线性表
  • 二、顺序表是什么
  • 2.1 概念及结构
  • 2.2 自己实现一个顺序表
  • 2.3 接口实现
  • 2.3.1 插入实现
  • 1.1给定位置插入元素:
  • 1.2 尾插法
  • 1.3 头插法
  • 1.4 顺序表满后实现扩容
  • 1.5 判断顺序表是否为满
  • 2.3.2 查找实现
  • 2.1 判定是否包含某个元素
  • 2.2 查找某个元素对应的位置
  • 2.3 获取给定位置的元素
  • 2.3.3 修改实现
  • 3.1 将给定位置的元素设为value
  • 2.3.4 删除实现
  • 4.1 清空所有数据
  • 4.2 删除第一次出现的关键字key
  • 2.3.5 其他实现
  • 5.1 获取顺序表长度
  • 三 、顺序表的问题及思考



前言

java语言学习之路上要注意基础学习,如果基础没有打好,在好的技术,也无法进步,关注我带你系统的学习Javase


一、线性表

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串…

线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储 时,通常以数组和链式结构的形式存储。

javafx顺序播放列表_java_02

二、顺序表是什么

2.1 概念及结构

顺序表的底层是一个数组;
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。
顺序表一般可以分为:
静态顺序表:使用定长数组存储。
动态顺序表:使用动态开辟的数组存储。
静态顺序表适用于确定知道需要存多少数据的场景.
静态顺序表的定长数组导致N定大了,空间开多了浪费,开少了不够用.
相比之下动态顺序表更灵活, 根据需要动态的分配空间大小.
代码举例

int[] arr = new int[n];

2.2 自己实现一个顺序表

/**
 * 实现ArrayList类
 */

public class MyArrayList {
   /* public  int[] elem = new int[10]; //实现数组特征
    public  int usedSize = 0; //实现长度特征
    */
    private  int[] elem;
    private  int useSize;

    public  MyArrayList(){
        this.elem = new int[10]; //默认长度为11的数组
    }

    public  MyArrayList(int len){
        this.elem = new int[len];  //动态初始化数组
    }
}

实例化静态和动态的顺序表;

public class TestDemo {
    public static void main(String[] args) {
     MyArrayList myArrayList =  new MyArrayList(10);//动态创建长度为11的顺序表
        MyArrayList myArrayList1 = new MyArrayList();//默认长度为11的顺序表
    }
}

2.3 接口实现

这可是重点:

我们来实现一个动态顺序表. 以下是需要支持的接口.

2.3.1 插入实现

1.1给定位置插入元素:

1.首先我们要进行判断顺序表是不是满了,满了是不可以添加的

public  boolean isFull(){
        if(this.useSize==this.elem.length){
            return  true;  //如果当前的长度和数组的长度相等,那么就说明顺序表满了
        }
        return false; //顺序表未
    }

2.编写插入代码

//给定位置插入元素
    public void add(int pos, int data) {
        if(isFull()){
            System.out.println("顺序表已经满了!");
            return;
        }

        if(pos<0||pos>this.useSize){
            System.out.println("输入位置不合法!");
            return;
        }
        for( int i =this.useSize-1;i>=pos;i--){
            this.elem[i+1] = this.elem[i]; //将pos位置后的元素向后移动元素,到pos位置停止;
        }
        this.elem[pos] = data;//将数据插入
        this.useSize++; //顺序表长度增加1
    }
1.2 尾插法
//尾插法
    public  void add(int data){
        if(isFull()){
           // System.out.println("顺序表已经满了");
            resize();
            //return;
        }
        this.useSize++;//长度加一
        this.elem[this.useSize] = data;
    }
1.3 头插法
//头插法
    public  void addHead(int data){
        if(isFull()){
            // System.out.println("顺序表已经满了");
            resize();
            //return;
        }
     for(int i = this.useSize-1;i>=0;i--){
         this.elem[i+1] = this.elem[i];
     }
     this.elem[0] = data;
     this.useSize++;
    }
1.4 顺序表满后实现扩容
//扩容
    public  void resize(){
     this.elem = Arrays.copyOf(this.elem,2*this.elem.length);
     //扩容为原来数组长度的两倍,并且扩容后,还是一个数组。
    }
1.5 判断顺序表是否为满
public  boolean isFull(){
        if(this.useSize==this.elem.length){
            return  true;  //如果当前的长度和数组的长度相等,那么就说明顺序表满了
        }
        return false; //顺序表未满
    }

2.3.2 查找实现

2.1 判定是否包含某个元素
// 判定是否包含某个元素
    public boolean contains(int toFind) {
        if(this.elem==null||this.useSize<=0) {
            System.out.println("线性表是空的!");
            return false;
        }
        for(int i = 0;i<this.useSize;i++){
            if(this.elem[i]==toFind){
                return true;
            }
        }
        return false;
    }
2.2 查找某个元素对应的位置
// 查找某个元素对应的位置
    public int search(int toFind) {
        if(this.elem==null||this.useSize<=0){
            System.out.println("线性表是空的!");
            return -1;
        }
        for(int i =0;i<this.useSize;i++){
            if(this.elem[i]==toFind){
                return i;//找到则返回下标
            }
        }
        return -1; //没有找到则返回-1
    }
2.3 获取给定位置的元素
// 获取 pos 位置的元素
    public int getPos(int pos) {
        if(this.elem==null||this.useSize<=0){
            System.out.println("线性表是空的!");
            return -1;
        }
        if(pos>=0&&pos<this.useSize){
            return this.elem[pos];
        }
        return -1;
    }

2.3.3 修改实现

3.1 将给定位置的元素设为value
public void setPos(int pos, int value) {
        if(this.elem==null||this.useSize<=0){
            System.out.println("顺序表为空!");
            return;
        }
       this.elem[pos] = value;
    }

2.3.4 删除实现

4.1 清空所有数据
// 清空顺序表
  public void clear() {
     this.useSize=0;
    }
4.2 删除第一次出现的关键字key
//删除第一次出现的关键字key
    public void remove(int toRemove) {
        if(this.elem==null||this.useSize<=0){
            System.out.println("线性表为空!");
            return;
        }
        //1.查找是否有key
        if(contains(toRemove)){ //查找是否包含toRemove
            int i = search(toRemove); //得到toRemove的位置
            for(int n = i ;n<this.useSize-1;n--)
            this.elem[n] = this.elem[n+1];
        }
    }

2.3.5 其他实现

5.1 获取顺序表长度
// 获取顺序表长度
    public int size() {
        return this.useSize;
    }

三 、顺序表的问题及思考

1.顺序表中间/头部的插入删除,时间复杂度为O(N)
2.增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。
3.增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,我们再继续 插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。
思考: 如何解决以上问题呢?详情请看下一篇链表实现。