IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 数据结构——线性表1:顺序表 -> 正文阅读

[数据结构与算法]数据结构——线性表1:顺序表

顺序表的定义

顺序表是在计算机内存中以数组的形式保存的线性表,线性表的顺序存储是指用一组地址连续的存储单元,依次存储线性表中的各个元素、使得线性表中再逻辑结构上响铃的数据元素存储在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系。

顺序表的实现

顺序表API设计

?顺序表的代码实现

public class SequenceList<T> implements Iterable<T>{
    private T[] eles; //存储元素的数组
    private int N; //当前线性表的长度
    //创建容量为capacity的SequenceList
    public SequenceList(int capacity){
           eles=(T[])new Object[capacity];
           N=0;
    }
    //空置线性表
    public void clear(){
          N=0;
    }
    //判断线性表是否为空,是返回true 否返回false
    public boolean isEmpty(){
         return N==0;
    }
    //获取线性表中元素的个数
    public int length(){
        return N;
    }
    //读取并返回线性表中的第i个元素的值
    public T get(int i){
        return eles[i];
    }
    //在线性表的第i个元素插入一个值为t的数据元素
    public void insert(int i,T t){
        //把i位置空出来,i位置及其后边的元素依次向后移动一位
        for(int index=N-1;index>=i;index--){
            eles[index+1]=eles[index];
        }
        //把t放到i位置处
        eles[i]=t;
        //元素数量+1
        N++;
    }
    //向线性表插入一个元素t
    public void insert(T t){
            eles[N++]=t;
    }
    //删除并返回线性表中第i个数据元素
    public T remove(int i){
         //记录i位置处的元素
        T result=eles[i];
        //把i位置后边的元素都向前移动一位
        for(int index=i+1;index<N;index++){
            eles[index-1]=eles[index];
        }
        //元素数量-1
        N--;
        return result;

    }
    //返回线性表中首次出现的指定的数据元素的位序号,若不存在,则返回-1
    public int indexOf(T t){
        for(int index=0;index<N;index++){
            if(eles[index].equals(t)){
                return index;
            }
        }
        return -1;
    }
     //打印当前线性表的元素
    public void showEles(){
        for(int i=0;i<N;i++){
            System.out.print(eles[i]+" ");
        }
        System.out.println();
    }

    @Override
    public Iterator iterator() {
        return new SIterator();
    }
    private class SIterator implements Iterator{
        private int cur;
        public SIterator(){
            this.cur=0;
        }
        @Override
        public boolean hasNext() {
            return cur<N;
        }

        @Override
        public T next() {
            return eles[cur++];
        }
    }
}
//测试代码
public class SequenceListTest {
    public static void main(String[] args){
        SequenceList<String> s=new SequenceList<>(10);
        //测试插入
        s.insert("a1");
       s.insert("b2");
        s.insert("c3");
        s.insert("d4");
        s.insert(0,"a");
        //测试遍历
        s.showEles();
        //测试获取
        String s1 = s.get(1);
        System.out.println(s1);
        //测试删除
        String remove = s.remove(2);
        System.out.println(remove);
        s.showEles();
        //测试清空
        s.clear();
        System.out.println(s.length());
    }
}

顺序表的容量可变

在之前的实现中,当我们使用SequenceList时,先new SequenceList(10)创建一个对象,创建对象时就需要指定容器的大小,初始化指定大小的数组来存储元素,当我们插入元素时,如果已经插入了10个元素,还要继续插入数据,则会报错,就不能插入了。这种设计不符合容器的设计理念,因此我们在设计顺序表时,应该考虑它的容量的伸缩性。

情况一:添加元素时

添加元素时,应该检查当前数组的大小是否能容纳新的元素,如果不能容纳,则需要创建新的容量更大的数组,我们这里创建一个是原数组两倍容量的新数组存储元素。

情况二:移除元素时

移除元素时,应该检查当前数组的大小是否太大,比如正在用100个容量的数组存储10个元素,这样就会造成内存空间的浪费,应该创建一个容量更小的数组存储元素。如果我们发现数据元素的数量不足数组容量的1/4,则创建一个是原数组容量的1/2的新数组存储元素。

顺序表的容量可变代码实现

public class SequenceList<T> implements Iterable<T>{
    private T[] eles; //存储元素的数组
    private int N; //当前线性表的长度
    //创建容量为capacity的SequenceList
    public SequenceList(int capacity){
           eles=(T[])new Object[capacity];
           N=0;
    }
    //空置线性表
    public void clear(){
          N=0;
    }
    //判断线性表是否为空,是返回true 否返回false
    public boolean isEmpty(){
         return N==0;
    }
    //获取线性表中元素的个数
    public int length(){
        return N;
    }
    //读取并返回线性表中的第i个元素的值
    public T get(int i){
        return eles[i];
    }
    //在线性表的第i个元素插入一个值为t的数据元素
    public void insert(int i,T t){
        //当数组元素达到容量时 需要扩容
        if(N==eles.length){
            resize(eles.length*2);
        }
        //把i位置空出来,i位置及其后边的元素依次向后移动一位
        for(int index=N-1;index>=i;index--){
            eles[index+1]=eles[index];
        }
        //把t放到i位置处
        eles[i]=t;
        //元素数量+1
        N++;
    }
    //向线性表插入一个元素t
    public void insert(T t){
        //当数组元素达到容量时 需要扩容
        if(N==eles.length){
            resize(eles.length*2);
        }
            eles[N++]=t;
    }
    //删除并返回线性表中第i个数据元素
    public T remove(int i){
         //记录i位置处的元素
        T result=eles[i];
        //把i位置后边的元素都向前移动一位
        for(int index=i+1;index<N;index++){
            eles[index-1]=eles[index];
        }
        //元素数量-1
        N--;
        //当数组元素小于数组大小的1/4 则重置数组的大小
        if(N>0 && N<eles.length/4){
            resize(eles.length/2);
        }
        return result;

    }
    //返回线性表中首次出现的指定的数据元素的位序号,若不存在,则返回-1
    public int indexOf(T t){
        for(int index=0;index<N;index++){
            if(eles[index].equals(t)){
                return index;
            }
        }
        return -1;
    }
     //打印当前线性表的元素
    public void showEles(){
        for(int i=0;i<N;i++){
            System.out.print(eles[i]+" ");
        }
        System.out.println();
    }
    //改变容量
    public void resize(int newSize){
        //存上旧的数组元素
        T[] temp=eles;
        //创建新数组
        eles=(T[])new Object[newSize];
        //将旧数组的元素拷贝到新数组中
        for(int i=0;i<N;i++){
            eles[i]=temp[i];
        }
    }

    @Override
    public Iterator iterator() {
        return new SIterator();
    }
    private class SIterator implements Iterator{
        private int cur;
        public SIterator(){
            this.cur=0;
        }
        @Override
        public boolean hasNext() {
            return cur<N;
        }

        @Override
        public T next() {
            return eles[cur++];
        }
    }
}
//测试代码
public class SequenceListTest2 {
    public static void main(String[] args){
        SequenceList<String> str=new SequenceList<>(2);
        str.insert("qw");
        str.insert("er");
        str.insert("12");
        str.insert("34");
    }
}

顺序表的时间复杂度分析

1.get(i):不难看出,不论数据元素量N有多大,只需要一次eles[i]就可以获取到对应的元素,所以时间复杂度为O(1);
2.insert(int i,T t):每一次插入,都需要把i位置后面的元素移动一次,随着元素数量N的增大,移动的元素也越多,时间复杂为O(n);
3.remove(int i):每一次删除,都需要把i位置后面的元素移动一次,随着数据量N的增大,移动的元素也越多,时间复杂度为O(n);
4.由于顺序表的底层由数组实现,数组的长度是固定的,所以在操作的过程中涉及到了容器扩容操作。这样会导致顺序表在使用过程中的时间复杂度不是线性的,在某些需要扩容的结点处,耗时会突增,尤其是元素越多,这个问题越明显。

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-05-11 16:39:00  更:2022-05-11 16:41:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 3:54:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码