JavaSE · 线性表 · 顺序表 · 顺序表的问题 · 顺序表接口实现(新增元素,删除元素,修改元素,查找元素,清空顺序表)

一、线性表

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

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


二、顺序表

概念以及结构

顺序表是用一段物理地址连续的存储单元,依次存储数据元素的线性结构,一般情况下采用数组存储。
在数组上完成数据的增删改查。

顺序表一般可以分为:

  • 静态顺序表:使用定长的数组存储。
  • 动态顺序表:使用动态开辟的数组存储。

静态顺序表适合确定知道需要存储多少数据的场景.
静态顺序表的定长数组导致 N 定大了,浪费空间;定小了,不够用。

相比之下动态顺序表更加灵活,根据需要动态的分配空间大小.

动态顺序表的接口

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

public class SeqList {
	// 打印顺序表
	public void display() {  }
	
	// 在 pos 位置新增元素
	public void add(int pos, int data) { }
	
	// 判定是否包含某个元素
	public boolean contains(int toFind) { return true; }
	
	// 查找某个元素对应的位置
	public int search(int toFind) { return -1; }
	
	// 获取 pos 位置的元素
	public int getPos(int pos) { return -1; }
	
	// 给 pos 位置的元素设为 value
	public void setPos(int pos, int value) {  }
	
	//删除第一次出现的关键字key
	public void remove(int toRemove) {  }
	
	// 获取顺序表长度
	public int size() { return 0; }
	
	// 清空顺序表
	public void clear() {  }
}

顺序表的问题以及思考

  1. 顺序表中间 / 头部的插入删除,时间复杂度为O(N).
  2. 增容需要申请新空间,拷贝数据,释放旧空间。会有不小消耗.
  3. 增容一般是呈 2 倍增长,势必会造成空间浪费。例如当前容量为 100,满了之后增容到 200,我们再插入 5 个数据,就会浪费 95 个数据空间.

接口实现

public class MyArrayList {
    //顺序表名
    public int[] elem;
    //有效元素
    public int usedSize;
    //顺序表容量
    public static int capacity = 10;

    
    //构造方法创建数据
    public MyArrayList() {
        this.elem = new int[capacity];
    }
    
    
    //判断顺序表是否满
    public boolean isFull() {
//        if (this.usedSize == capacity) {
//            return true;
//        }
        return this.usedSize == capacity;
    }
    
    
    // 在 pos 位置新增元素
    public void add(int pos, int data) {
        //判断pos位置的合法性
        if (pos < 0 || pos > this.usedSize) {
            System.out.println("pos位置不合法");
            return;
        }
        //判断是否需要扩容
        if (isFull()) {
            this.elem = Arrays.copyOf(this.elem, 2*capacity);
            capacity *= 2;  //更新最大容量
        }
        //开始添加元素,其余元素后移
        for (int i = this.usedSize-1; i >= pos; i--) {
            this.elem[i+1] = this.elem[i];
        }
        //添加元素
        this.elem[pos] = data;
        //有效元素++
        this.usedSize++;
    }
    
    
    // 打印顺序表
    public void display() {
        if (this.usedSize <= 0) {
            System.out.println("顺序表为空");
            return;
        }
        for (int i = 0; i < this.usedSize; i++) {
            System.out.print(this.elem[i] + " ");
        }
        System.out.println();
    }
    
    
    //判断顺序表是否空
    public boolean isEmpty() {
//        if (this.usedSize <= 0) {
//            return true;
//        }
//        return false;
        //直接看有效元素
        return this.usedSize == 0;
    }
    
    
    // 判定是否包含某个元素
    public boolean contains(int toFind) {
        //判断是否空表
        if (isEmpty()) {
            System.out.println("顺序表为空~");
            return false;
        }
        //开始对比顺序表元素
        for (int i = 0; i < this.usedSize; i++) {
            if (this.elem[i] == toFind) {
                return true;
            }
        }
        //没找到
        return false;
    }

        
    // 查找某个元素对应的位置
    public int search(int toFind) {
        if (isEmpty()) {
            System.out.println("表空~");
            return -1;
        }
        //直接找
        for (int i = 0; i < this.usedSize; i++) {
            if (this.elem[i] == toFind) {
                return i;
            }
        }
        //没找到
        return -1;
    }
    
    
    // 获取 pos 位置的元素
    public int getPos(int pos) {
        //判断pos位置是否合法
        if (pos < 0 || pos >= this.usedSize) {
            System.out.println("pos有问题");
            return -1;
        }
        if (isEmpty()) {
            System.out.println("空表");
            return -1;
        }
        return this.elem[pos];
    }
    
    
    // 获取顺序表长度
    public int size() {
        return this.usedSize;
    }
    
    
    // 给 pos 位置的元素设为 value
    public void setPos(int pos, int value) {
        if (pos < 0 || pos >= this.usedSize) {
            System.out.println("pos有问题");
            return;
        }
        if (isEmpty()) {
            System.out.println("表为空");
            return;
        }
        this.elem[pos] = value;
    }
    
    
    //删除第一次出现的关键字key
    public void remove(int key) {
        if (this.usedSize == 0) {
            System.out.println("表为空");
            return;
        }
        //找key
        for (int i = 0; i < this.usedSize; i++) {
            //找到了,让后面的元素覆盖它
            if (this.elem[i] == key) {
                while (i < this.usedSize) {
                    this.elem[i] = this.elem[i+1];
                    i++;
                }
                System.out.println("删除成功");
                this.usedSize--;
                return;
            }
        }
        System.out.println("没有key值");
        return;
    }
    
    
    // 清空顺序表
    public void clear() {
        //循环给表中元素赋值初始值即可
        for (int i = 0; i < this.usedSize; i++) {
            this.elem[i] = 0;
        }
        //最后重置有效数据变量
        this.usedSize = 0;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值