DS-顺序表

线性表

定义

  • n个 相同数据类型的元素构成的有限序列
  1. n:元素个数确定
  2. 数据类型相同
  3. 序列:有先后顺序
  4. 除了表头表尾元素之外,其他元素都有唯一前驱和后继
  5. 表头元素只有后继,表尾元素只有前驱
  • 线性表是逻辑结构,表示在脑里想象的时候是一条线串联起来的,而顺序表和链表则是存储结构,是在计算机内存中的。
  • 线性表分为顺序表和链表。

顺序表和链表对比

  • 详细对比了两个存储结构的优缺点
对比项目 顺序表 链表
存储结构 连续的内存空间(数组)存储数据 不连续的内存空间,通过指针连接节点
内存 可以动态扩容,但要把原数据全拷贝过去 需要增加数据就插入一个节点
查找 支持随机访问,通过下标 O(1) 获取元素 只能从头遍历,访问第 i 个元素需要 O(n)
增删改 O(n) O(1)
特点 用空间换时间,查询快,插入删除慢 用时间换空间,插入删除快,查询慢。

ArrayList(顺序表)

小巧思

  • 在c语言中实现顺序表通常使用结构体,在结构体中定义数组,和数组初始长度。
  • 但是在Java中没有结构体,通常使用类进行定义顺序表,同样的可以在类中定义数组,数组初始长度。此外,类中还可以定义方法,对数组进行增删改查等操作。
  • 我们还可以让顺序表类去继承其他的类/接口。
  • 我们还可以去定义一个泛型类顺序表,当创建对象的时候在去指定顺序表中存储数据的数据类型,实现定义一个类,就有了可以存储所有类型数据的顺序表。

  • 那么顺序表可以通过类去定义实现,链表如何实现?
  • 在c语言中可以使用结构体,把结构体看成一个节点,节点中可以存储数据,还可以存储下一个节点的地址,Java中没有地址,这咋搞?(没有地址,我有引用)
  • 那么是否可以把类看成节点?节点中也存储此节点的数据和下一个节点的引用,这不就行了吗。

优点

  1. 空间利用率高:节点内只存储数据,不存储下一个节点的地址
  2. 随机存取:可以通过数组下标i,想访问哪个元素访问哪个
  3. 访问元素快:通过下标访问,时间复杂度:O(1)

基本操作

  • 主要分为:List接口/MyArrayList类/test测试类
List接口
  • 顺序表的父类,主要存储一些增删改查这些抽象方法。
java 复制代码
package List;
//List接口中是对顺序表的增删改查操作
public interface List {
    void add(int data);
    //增加元素
    void add(int pos,int data);
    //构成重载,特定位置pos增加元素
    void findData(int data);
    //按值查找
    void indexData(int pos);
    //按位查找
    void Empty();
    //判空
    void deletePosData(int pos);
    //按位删除
    void deleteData(int data);
    //按值删除
    void listLength();
    //返回顺序表的长度
    void PrintArrayList();
    //输出顺序表
}
MyArrayList类
  • 主要实现顺序表的类,重写接口中所有的方法。
java 复制代码
package List;
//实现一个类似于Java自带的顺序表类
import java.util.Arrays;
public class MyArrayList implements List{
    //设定数组长度
    private int length = 5 ;
    //存储元素数组
    private int[] myArray;
    //方法中当前长度
    public    int preLength = 0;

    //让myArray引用指向对象中新开辟的数组空间
    //对象中的引用指向一个数组对象
    public MyArrayList(){
        this.myArray = new int[length];
    }

    @Override
    public void add(int data) {
        //判断顺序表是否存满,存满则不可插入
        if (preLength < length){
            this.myArray[preLength] = data;
            preLength++;
        }else {
            System.out.println("顺序表已经存满,无法存入数据");
        }
        //尾部插入元素
    }

    @Override
    public void add(int pos, int data) {
        // 检查位置是否合法
        if (pos < 0 || pos > preLength) {
            System.out.println("插入位置不合法");
            return;
        }
        if (preLength < length) {
            // 将pos及其后面的元素后移
            for (int i = preLength; i > pos; i--) {
                this.myArray[i] = this.myArray[i - 1];
            }
            this.myArray[pos] = data;
            preLength++;
        } else {
            System.out.println("顺序表已经存满,无法存入数据");
        }
    }

    @Override
    public void findData(int data) {
        for (int i = 0; i < this.myArray.length; i++) {
            if (this.myArray[i] == data) {
                System.out.println("按值查找的元素为:" + data);
            }
        }
        //按值查找
    }

    @Override
    public void indexData(int pos) {
        for (int i = 0; i <this.myArray.length ; i++) {
            if (i == pos) {
                System.out.println("按位查找的元素index为:" + i);
            }
        }
        //按位查找
    }

    @Override
    public void Empty() {
        if (preLength == 0) {
            System.out.println("顺序表为空");
        } else {
            System.out.println("顺序表非空");
            //判空,对象自己的数组,不需要传参,直接对象名.方法名进行判断
        }
    }

    @Override
    public void deletePosData(int pos) {
        if (pos < 0 || pos >= preLength) {
            System.out.println("删除位置不合法");
        }
         else if (preLength != 0) {
            for (int i = 0; i < this.preLength-1; i++) {
                if (i == pos){
                    for (int j = i; j < this.preLength-1; j++) {
                        this.myArray[j] = this.myArray[j+1];
                    }
            }
                this.myArray[preLength - 1] = 0;
                System.out.println("删除后的顺序表为:" +Arrays.toString(myArray) );
                preLength--;
                //长度减1
            }
        }else {
            System.out.println("删除失败");
        }
    }

    @Override
    public void deleteData(int data) {
        //按值删除
        if (preLength == 0) {
            System.out.println("顺序表为空,无法删除");
        }
        if (preLength != 0) {
            //顺序表非空才可以删除
            for (int i = 0; i < this.preLength-1; i++) {
                if (this.myArray[i] == data) {
                    for (int j = i ; j < this.preLength-1; j++) {
                        this.myArray[j] = this.myArray[j + 1];
                        //顺序表要求连续存放,数据之间不可以有null值。
                    }
                    this.myArray[preLength - 1] = 0;
                    System.out.println("删除后的顺序表为:" +Arrays.toString(myArray) );
                    preLength--;//删除成功
                }
            }
        } else {
            System.out.println("顺序表为空,无法删除");
        }
    }
    @Override
    public void listLength() {
        System.out.println("当前顺序表长度为:" + this.preLength);
        //返回顺序表的长度,对象自己的数组不需要传参,直接对象名.方法名就可以调用判断
    }

    @Override
    public void PrintArrayList() {
            System.out.println( Arrays.toString(myArray));
    }
}
test类
  • 测试结果输出
java 复制代码
package List;
public class test {
 static void main() {
  MyArrayList myArrayList = new MyArrayList();
  myArrayList.PrintArrayList();
  myArrayList.listLength();
  myArrayList.add(1);
  myArrayList.add(1,20);
  myArrayList.add(3);
  myArrayList.add(3,40);
  myArrayList.add(5);
  myArrayList.PrintArrayList();
  myArrayList.listLength();
  System.out.println("插入功能测试成功");
  myArrayList.findData(20);
  myArrayList.indexData(3);
  System.out.println("查找功能测试成功");
  System.out.print("当前表内元素为:");
  myArrayList.PrintArrayList();
  myArrayList.deleteData(1);
  myArrayList.deletePosData(-2);
    }
}
复制代码
/Users/mdj/Library/Java/JavaVirtualMachines/openjdk25/Contents/List.test
[0, 0, 0, 0, 0]
当前顺序表长度为:0
[1, 20, 3, 40, 5]
当前顺序表长度为:5
插入功能测试成功
按值查找的元素为:20
按位查找的元素index为:3
查找功能测试成功
当前表内元素为:[1, 20, 3, 40, 5]
删除后的顺序表为:[20, 3, 40, 5, 0]
删除位置不合法
Process finished with exit code 0

相关推荐
回家吃饭去吧1 小时前
AI Agent Function Calling / Tool Use 深度解析
后端
TinyMemory1 小时前
Java 面向对象核心入门(七):方法重载 Overload,同一个方法名能干不一样的活
java·面向对象·overload·方法重载
大黄评测1 小时前
Oracle 锁等待、会话阻塞故障复盘:生产事故排查步骤
后端
大勇前进1 小时前
Oracle 慢 SQL 优化避坑:索引建了为什么依然走全表扫描
后端
良在掘金542231 小时前
匹配服排行榜位置原子交换与锁粒度设计
后端
用户233376852181 小时前
Docker部署Kafka排障实录
后端
吴声子夜歌2 小时前
Java扩展——OkHttp
java·开发语言·okhttp
卓怡学长2 小时前
w210基于springboot反诈平台设计与实现
java·spring boot·spring·intellij-idea
萧瑟余晖2 小时前
Java深入解析篇六十一之编译器API(javax.tools)详解
java·开发语言