【数据结构】顺序表

前言:

小编在开始之前就已经发了顺序表的相关用例,想看的小伙伴可以去看看哦http://t.csdnimg.cn/saIbn

1.概念 

什么是顺序表:

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

那么小编在之前就已经通过模拟顺序表实现了图书管理系统,这里也会再次模拟一下。

2.接口实现: 

1.首先先初始化数组,以及它的有效数据(这里的有效数据非常重要

public class MyArraylist {
    public int[] elem;
    public int usedSize;//0
    //默认容量
    private static final int DEFAULT_SIZE = 10;

    public MyArraylist() {
        this.elem = new int[DEFAULT_SIZE];
    }
2.实现顺序表的打印,通过有效数据的个数,实现次数循环,通过对应下标实现数组元素的打印
public void display() {
        for (int i = 0; i < usedSize; i++) {
            System.out.println(this.elem[i]);
        }
    }

3.添加元素,默认在最末尾加元素,在添加元素之前,需要进行数组是否为满的状态判断,如果满,则扩大两倍的长度,最后将元素放到末尾去。

// 新增元素,默认在数组最后新增
    public void add(int data) {
        if (isFull() == true) {
            this.elem = Arrays.copyOf(this.elem, 2 * this.elem.length);
        }
        this.elem[usedSize] = data;
        usedSize++;
    }

4.这里就是判断是否为满的状态,通过有效数据个数,与数组的长度进行对比,如果相等就是表示已经满了,返回一个true,反之则返回false。

public boolean isFull() {
        if(this.usedSize == this.elem.length) {
            return true;
        }
        return false;
       
    }

5.这里添加私有方法,传入pos判断插入该位置是否合法,若果输入的位置小于0,或者大于有效数字,则返回false。(为啥大于有效数字有误,因为顺序表是连续的,不能出现断点

如下图:(这是不合法的

private boolean checkPosInAdd(int pos) {
        if(pos < 0 || pos > this.usedSize) {
            System.out.println("pos位置不合法");
            return false;
        }
        return true;//合法
    }

6.插入数据,先要进行pos位置合法判断,以及是否为满的状态判断,在插入元素时,要将插入位置的后面所有元素向后移动一位,最后将元素插入对应位置。

 public void add(int pos, int data) {
        //判断下标是否是合法的
        if(!checkPosInAdd(pos)) {
            throw new MyArrayListIndexOutOfException("添加方法的pos不合理!");
        }
        //判断是否是满的
        if (isFull()) {
            this.elem = Arrays.copyOf(this.elem,2*this.elem.length);
        }
        //挪数据
        for (int i = this.usedSize-1; i >= pos ; i--) {
            this.elem[i+1] = this.elem[i];
        }
        //挪完了数据
        this.elem[pos] = data;
        this.usedSize++;
    }

7.实现元素的查找,通过遍历数组,每次进行对应元素与要查找的元素进行判断,找到了就放回true,反之就返回false。

public boolean contains(int toFind) {
        for (int i = 0; i < this.usedSize; i++) {
            if(this.elem[i] == toFind) {
                return true;
            }
        }
        return false;
    }

8.与上述代码一致,找到了对应的元素,就返回找到元素的下标,没找到就返回-1.

 public int indexOf(int toFind) {
        for (int i = 0; i < this.usedSize; i++) {
            if(this.elem[i] == toFind) {
                return i;
            }
        }
        return -1;
    }

9.判断pos位置的合法性,与上述判断不一样的是在usedsize位置时没有元素的。

  private boolean checkPosInGet(int pos) {
        if(pos < 0 || pos >= this.usedSize) {
            System.out.println("pos位置不合法");
            return false;
        }
        return true;//合法
    }

10.判断数组是否为空

 private boolean isEmpty() {
        return this.usedSize == 0;
    }

11.在那元素时,通过第9种的pos位置合法判断,返回对应的位置元素。

 public int get(int pos) {
        if(!checkPosInGet(pos)) {
            throw new MyArrayListIndexOutOfException("获取pos下标时,位置不合法");
        }
        //不用写判断空不空 没有问题的
        if(isEmpty()) {
            throw new MyArrayListEmptyException("获取元素的时候,顺序表为空!");
        }
        return this.elem[pos];
    }

12.更新元素,通过判断位置是否合法后,然后直接将元素放在对应位置,直接将初始的元素进行覆盖。

// 给 pos 位置的元素设为【更新为】 value
    public void set(int pos, int value) {
        if(!checkPosInGet(pos)){
            throw new MyArrayListIndexOutOfException("更新pos下标的元素,位置不合法");
        }
        //如果合法 ,那么其实不用判断顺序表为空的状态了
        if(isEmpty()) {
            throw new MyArrayListEmptyException("顺序表为空!");
        }
        //顺序表为满的情况也可以更新
        this.elem[pos] = value;
    }

13.将第一个遍历到的key实现删除,首先进行查找,如果找到了就返回元素下标,存在index变量里,最后从index位置开始,将后面的所有元素往前移,最后有效数据减去一。

  public void remove(int key) {
        if(isEmpty()) {
            throw new MyArrayListEmptyException("顺序表为空,不能删除!");
        }
        int index = indexOf(key);
        if(index == -1) {
            System.out.println("不存在你要删除的数据");
            return;
        }

        for (int i = index; i < this.usedSize-1; i++) {
            this.elem[i] = this.elem[i+1];
        }
        //删除完成
        this.usedSize--;
        // this.elem[usedSize] = null; 如果是引用类型 这里需要置为空
    }

14.最后实现长度,以及清空顺序表的操作。

  public int size() {
        return this.usedSize;
    }

    // 清空顺序表
    public void clear() {
        this.usedSize = 0;
    }

3.ArrayList简介

1. ArrayList 是以泛型方式实现的,使用时必须要先实例化

2. ArrayList 实现了 Cloneable 接口,表明 ArrayList 是可以 clone
3. ArrayList 实现了 Serializable 接口,表明 ArrayList 是支持序列化的
4. Vector 不同, ArrayList 不是线程安全的,在单线程下可以使用,在多线程中可以选择 Vector 或者 CopyOnWriteArrayList
5. ArrayList 底层是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序表

 4.ArrayList的简单构造

代码以及解释如下:

public static void main(String[] args) {
// ArrayList创建,推荐写法
// 构造一个空的列表
List<Integer> list1 = new ArrayList<>();
// 构造一个具有10个容量的列表
List<Integer> list2 = new ArrayList<>(10);
list2.add(1);
list2.add(2);
list2.add(3);
// list2.add("hello"); // 编译失败,List<Integer>已经限定了,list2中只能存储整形元素
// list3构造好之后,与list中的元素一致
ArrayList<Integer> list3 = new ArrayList<>(list2);
// 避免省略类型,否则:任意类型的元素都可以存放,使用时将是一场灾难
List list4 = new ArrayList();
list4.add("111");
list4.add(100);
}

5.ArrayList的简单使用

以及

boolean contains (Object o)
判断 o 是否在线性表中
int indexOf (Object o)
返回第一个 o 所在下标
int lastIndexOf (Object o)
返回最后一个 o 的下标
List<E> subList (int fromIndex, int toIndex)
截取部分 list

代码如下:

public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("JavaSE");
list.add("JavaWeb");
list.add("JavaEE");
list.add("JVM");
list.add("测试课程");
System.out.println(list);

// 获取list中有效元素个数
System.out.println(list.size());

// 获取和设置index位置上的元素,注意index必须介于[0, size)间
System.out.println(list.get(1));
list.set(1, "JavaWEB");
System.out.println(list.get(1));

// 在list的index位置插入指定元素,index及后续的元素统一往后搬移一个位置
list.add(1, "Java数据结构");
System.out.println(list);

// 删除指定元素,找到了就删除,该元素之后的元素统一往前搬移一个位置
list.remove("JVM");
System.out.println(list);

// 删除list中index位置上的元素,注意index不要超过list中有效元素个数,否则会抛出下标越界异常
list.remove(list.size()-1);
System.out.println(list);

// 检测list中是否包含指定元素,包含返回true,否则返回false
if(list.contains("测试课程")){
list.add("测试课程");
}

// 查找指定元素第一次出现的位置:indexOf从前往后找,lastIndexOf从后往前找
list.add("JavaSE");
System.out.println(list.indexOf("JavaSE"));
System.out.println(list.lastIndexOf("JavaSE"));

// 使用list中[0, 4)之间的元素构成一个新的SubList返回,但是和ArrayList共用一个elementData数组
List<String> ret = list.subList(0, 4);
System.out.println(ret);
list.clear();
System.out.println(list.size());
}

6.ArrayList的遍历

1.直接输出

List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);

System.out.println(list);
2.for循环输出
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
// 使用下标+for遍历
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i) + " ");
}

3.增强循环输出

List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);

for (Integer integer : list) {
System.out.print(integer + " ");
}

4.借助迭代器输出

List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);

Iterator<Integer> it = list.listIterator();
while(it.hasNext()){
System.out.print(it.next() + " ");
}

7.ArrayList的问题

1. ArrayList 底层使用连续的空间,任意位置插入或删除元素时,需要将该位置后序元素整体往前或者往后搬 移,故时间复杂度为O(N)
2. 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。
3. 增容一般是呈 2 倍的增长,势必会有一定的空间浪费。例如当前容量为 100 ,满了以后增容到 200 ,我们再继 续插入了5 个数据,后面没有数据插入了,那么就浪费了 95 个数据空间。

那么就要考虑到链表了

8.总结

限于小编能力大小,欢迎各位uu提出宝贵意见。

 制作不易,给小编点个赞吧。

  • 13
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
顺序表是一种常见的数据结构,用于存储一组具有相同类型的元素。它的基本操作包括创建、查找、插入和删除等。 在C语言中,可以通过使用数组来实现顺序表。我们可以定义一个数组来存储顺序表的元素,然后通过索引来访问和操作其中的元素。引用中的代码展示了一个简单的顺序表的例子,它使用了C语言来实现。在这个例子中,我们可以看到如何创建一个顺序表、插入元素、删除元素以及查找元素的前驱和后继。 引用中的代码是一个测试顺序表基本操作的例子。它使用了一个自定义的List类来实现顺序表,并对其进行了各种操作,包括插入元素、删除元素、查找元素的前驱和后继以及遍历整个顺序表顺序表的结构体定义可以根据具体的需求进行定义。在引用中的代码中,定义了一个结构体ConnTimeout,其中包含了一个int类型的fd和一个time_t类型的timeout成员变量。这个结构体可以用来表示连接超时的信息。 总而言之,顺序表是一种常见的数据结构,可以通过使用数组来实现。在C语言中,可以使用数组和相关的操作来创建、查找、插入和删除顺序表中的元素。结构体的定义可以根据具体的需求进行自定义。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [数据结构顺序表c++代码](https://download.csdn.net/download/qq_46546083/13458006)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [C++数据结构顺序表(模板类实现)](https://blog.csdn.net/sagjhdj/article/details/123260460)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [【数据结构顺序表(C++)](https://blog.csdn.net/qq_51604330/article/details/120600041)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值