文章目录

  • 一、什么是线性表
  • 二、顺序表
  • 三、手撕顺序表
    • 属性定义
    • 构造方法
    • 接口实现
      • 确保顺序表空间
      • 增加元素
      • 打印顺序表
      • 判断顺序表中是否包含某个元素
      • 查找元素
      • 获取 pos 位置的元素
      • 将 pos 位置的元素值设为 value
      • 删除第一次出现的关键字key
      • 获取顺序表长度
      • 清空顺序表
      • 删除所有的key

一、什么是线性表

线性表是最基本、最简单、也是最常用的一种数据结构。线性表*(linear list)*是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列。常见的线性表有顺序表,链表,栈,队列,字符串等

注意:这里说的线性表都指的是逻辑结构,也就是他们的逻辑结构是线性的,但物理结构却不一定是线性的。


在数据结构逻辑层次上细分,线性表可分为一般线性表受限线性表。一般线性表也就是我们通常所说的“线性表”,可以自由的删除或添加结点。受限线性表主要包括栈和队列,受限表示对结点的操作受限制

二、顺序表

顺序表是在计算机内存中以数组的形式保存的线性表,线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表中的各个元素、使得线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中

顺序表可以分为以下两类:

  1. 静态顺序表:通过定长数组实现
  2. 动态顺序表:数组长度可动态增长

静态顺序表比较死板,如果数组长度太小,担心后面数据存不下,太大,又会有空间浪费.

所以我们一般都用动态增长的顺序表,按需所取.

三、手撕顺序表

在学习数据结构的过程中,我们不仅要学会如何用数据结构,懂得它的理论部分,更要亲自动手去实践,将数据结构实现一遍,这样的话理解会更深刻

顺序表中我们如果只是单纯拿一个数组去用的话就会出现:顺序表中到底有多少有效数据,满了还是没满等问题,所以我们在实现顺序表的时候都还会再加一个size(有效数据个数)属性(顺序表的容量可以通过data.length获得)

属性定义

public class MyArrayList {public int[] data;    // 存储数据public int size;    // 有效数据个数
}

构造方法

public MyArrayList() {this.data = new int[10];   // 后面不够再增容this.size = 0;    // 初始无有效数据,size 为0
}

接口实现

对于顺序表我们一般都会有以下接口需要去实现:

// 打印顺序表
public void display();
// 在 pos 位置增加元素
public void add(int pos, int num);
// 判断顺序表中是否包含某个元素
public boolean contains(int num);
// 查找某个元素所在位置
public int search(int key);
// 获取 pos 位置的元素
public int getPos(int pos);
// 将 pos 位置的元素值设为 value
public void setPos(int pos, int value);
//删除第一次出现的关键字key
public void remove(int key);
// 获取顺序表长度
public int size();
// 清空顺序表
public void clear();

在实现这些接口的过程中,凡是涉及到数组下标的,我们都要进行下标合法性的检验,并且要注意用size,还是data.length

确保顺序表空间

在对顺序表增加元素的时候,我们一定要确保顺序表有足够的空间去增加元素,否则就会导致数组下标越界等情况发生

private void ensureCapacity() {if (this.size == this.data.length) {// 说明满了,该扩容了this.data = Arrays.copyOf(this.data, 2 * this.data.length);}
}

增加元素

往顺序表中增加元素的时候要注意可以在size位置去加元素(相当于尾插),同时也要确保顺序表有空间足够插入,在移动元素的时候要注意边界情况(下标越界,移动元素过多等),也别忘了size++

public void add(int pos, int num) {if (pos < 0 || pos > this.size) {    // 检验下表合法性throw new RuntimeException("ArrayIndexOutOfBoundsException : " + pos);}ensureCapacity();for (int i = this.size; i > pos; i--) {this.data[i] = this.data[i - 1];}this.data[pos] = num;this.size++;
}

打印顺序表

注意这里只打印有效数据

public String printMyArrayList() {String str = "[";for (int i = 0; i < this.size - 1; i++) {   // for循环中的右边界应该用size而不用data.lengthstr += this.data[i] + ", ";}str += this.data[this.size - 1];str += "]";return str;
}

测试

对前面写的三个接口做测试

public class UseArrayList {public static void main(String[] args) {MyArrayList myArrayList = new MyArrayList();myArrayList.add(0, 0);myArrayList.add(1, 1);myArrayList.add(2, 2);myArrayList.add(3, 3);myArrayList.add(4, 2);myArrayList.add(0, 100);   // 头插myArrayList.add(2, 666);   // 中间插System.out.println(myArrayList.printMyArrayList());}
}

运行结果:

判断顺序表中是否包含某个元素

public boolean contains(int num) {for (int i = 0; i < this.size; i++) {if (this.data[i] == num) {return true;}}return false;
}

测试:

public class UseArrayList {public static void main(String[] args) {MyArrayList myArrayList = new MyArrayList();myArrayList.add(0, 0);myArrayList.add(1, 1);myArrayList.add(2, 2);myArrayList.add(3, 3);System.out.println(myArrayList.contains(3));System.out.println(myArrayList.contains(2));System.out.println(myArrayList.contains(0));System.out.println(myArrayList.contains(666));}
}

运行结果:

查找元素

查找顺序表中某个元素的位置(返回下标)

public int search(int key) {for (int i = 0; i < this.size; i++) {if (this.data[i] == key) {return i;}}return -1;    // 不存在这个元素,返回-1
}

测试:

public class UseArrayList {public static void main(String[] args) {MyArrayList myArrayList = new MyArrayList();myArrayList.add(0, 0);myArrayList.add(1, 1);myArrayList.add(2, 2);myArrayList.add(3, 3);System.out.println(myArrayList.search(0));System.out.println(myArrayList.search(3));System.out.println(myArrayList.search(666));}
}

获取 pos 位置的元素

注意:size位置为无效元素

public int getPos(int pos) {if (pos < 0 || pos >= this.size) {throw new RuntimeException("ArrayIndexOfBoundsException : " + pos);}return this.data[pos];
}

测试:

public class UseArrayList {public static void main(String[] args) {MyArrayList myArrayList = new MyArrayList();myArrayList.add(0, 0);myArrayList.add(1, 1);myArrayList.add(2, 2);myArrayList.add(3, 3);System.out.println(myArrayList.getPos(0));System.out.println(myArrayList.getPos(3));System.out.println(myArrayList.getPos(1));System.out.println(myArrayList.getPos(6));}
}

将 pos 位置的元素值设为 value

这里不涉及元素的移动

public void setPos(int pos, int value) {if (pos < 0 || pos >= this.size) {     // size位置为无效元素throw new RuntimeException("ArrayIndexOfBoundsException : " + pos);}this.data[pos] = value;
}

测试:

public class UseArrayList {public static void main(String[] args) {MyArrayList myArrayList = new MyArrayList();myArrayList.add(0, 0);myArrayList.add(1, 1);myArrayList.add(2, 2);myArrayList.add(3, 3);myArrayList.setPos(0, 666);myArrayList.setPos(3, 777);System.out.println(myArrayList.printMyArrayList());}
}

删除第一次出现的关键字key

注意在删除的时候的数组边界以及改变size

public void remove(int key) {int pos = search(key);if (pos == -1) {return;        // 若是这个数字不存在,则返回}for (int i = pos; i < this.size - 1; i++) {this.data[i] = this.data[i + 1];      // 从后往前挪,直接将要删除的数字覆盖掉}this.size--;
}

获取顺序表长度

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

清空顺序表

public void clear() {this.size = 0;
}

删除所有的key

如果我们想要删除顺序表中所有的key,如何做?

法一:我们可以将第一次出现的key删除完之后再继续搜索若有,则删除,没有则删除完毕

public void removeAll(int key) {for (int i = 0; i < this.size; i++) {if (this.search(key) != -1) {remove(key);} else {return;}}
}

法二:我们可以转变以下思路,不直接删除key,而是重新创建一个数组,将源数组中不是key的值复制到新数组,再让原数组的引用指向新数组,间接完成删除操作

public void removeAllPlus(int key) {int[] newData = new int[this.data.length];    // 新数组长度应该和源数组长度相同int j = 0;for (int i = 0; i < this.size; i++) {if (this.data[i] != key) {newData[j] = this.data[i];j++;}}this.data = newData;this.size = j;
}

注意:在元素复制完之后要改变源数组的引用,并改变顺序表的size

法三:我们既然可以通过复制的方式实现间接删除操作,那么我们可以想着将原数组就当成目标数组,即两个指针,一个数组

public void removeAllPlusPlus(int key) {int dest = 0;for (int src = 0; src < this.size; src++) {if (this.data[src] != key) {this.data[dest] = this.data[src];dest++;}}this.size = dest;
}

欢迎大家关注!!!

一起学习交流 !!!

让我们将编程进行到底!!!

--------------整理不易,请三连支持------------------

【数据结构】手撕顺序表相关推荐

  1. 数据结构“入门”—手撕顺序表

    目录 一:顺序表基本概念 二:顺序表的实现 1 创建顺序表 2 初始化顺序表 3 检查是否需要扩容 4 打印顺序表 5 销毁顺序表 三:顺序表重要功能-"增 删 查 改" 1:增加 ...

  2. [ 数据结构 -- 手撕排序算法第三篇 ] 希尔排序

    手撕排序算法系列之:希尔排序. 从本篇文章开始,我会介绍并分析常见的几种排序,大致包括插入排序,冒泡排序,希尔排序,选择排序,堆排序,快速排序,归并排序等. 大家可以点击此链接阅读其他排序算法:排序算 ...

  3. 数据结构之——《顺序表》

    数据结构之--<顺序表> 1.含义 2.分类 3.接口函数实现 4.顺序表的优缺点 1.含义 顺序表示用一段纹理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储,在数组 ...

  4. 【数据结构】【顺序表】 SqList *L与SqList*L的区别

    [数据结构][顺序表] SqList *&L与SqList*L的区别 显然,对于顺序表的抽象数据模型中的函数,其参数使用各不相同. SqList *&L的情况 它的意思是,L是对Lis ...

  5. 数据结构之动态顺序表(含游戏菜单)

    上一篇文章我们谈了数据结构的静态顺序表,以及实现了静态顺序表,具体可以看我的上一篇文章->>>数据结构之静态顺序表. 我们可以知道,静态顺序表的缺点是:  因为使用的是定长数组,所以 ...

  6. [数据结构]数据结构简介和顺序表

    目录 什么是数据结构 数据结构的特性 线性表 顺序表 创建一个动态顺序表 顺序表的增删查改 尾插和尾删除 尾插 头插头删 头插 头删 任意位置的插入和删除 插入 删除 查找和打印 总结 这天,小明和小 ...

  7. [小森数据结构]看电影-顺序表技术精讲

    故事前研(言) 小森去看电影<<流浪地球2>>的时候买电影票的场景. 突然一个叫高启强的人买电影票 拉了两个Hei友,来看电影 <<流浪地球2>> 当场 ...

  8. java数据结构实验一顺序表,java数据结构实验代码之升序顺序表

    java数据结构实验代码之升序顺序表 数据结构实验报告 学院:管理学院 班级:13电子商务(1)班 姓名:廖秋君 学号:3213004779 2014年 10月 23 日 目录 一.需求分析----- ...

  9. 数据结构之基于顺序表的插入排序

    基于顺序表的插入排序(常规插入排序,二分插入排序,希尔排序) 这三种的都是插入排序算法的时间复杂度基本相似,但由于希尔排序不同于其他排序方式的思想,所以其时间复杂度会有所不同. 常规插入排序:O(n2 ...

最新文章

  1. AI助力清华博士进入周杰伦战队,预告AI应用迎来黄金时代?
  2. 87岁的老奶奶喜欢用windows画图程序作画,而且画得还贼好!
  3. JBOSS+EJB3之Entity 开发实例
  4. 线程池 And 线程池的使用(基于.net平台)
  5. pytorch学习之路
  6. 一个不错的游戏 - flash webgame
  7. django models 文件夹
  8. 相同Ip 不同端口配置Nginx反向代理Apache
  9. CenterOS防火墙操作
  10. pycharm-python文件注释头
  11. mysql join 循环_MySQL的JOIN(三):JOIN优化实践之内循环的次数
  12. python学习之课后习题
  13. Tapestry 教程(四)探索项目结构
  14. 基于python+django学生信息管理系统设计与实现(毕业论文+毕设源码)
  15. http长连接、长轮询的理解
  16. 支付宝生活号开发配置
  17. 鹅厂同学:7 月开始不再进行薪酬调整?
  18. linux mmc驱动
  19. Createprocess 函数运行出错的原因和解决办法
  20. js: 获取最近3天、1周、1个月、3个月、半年、1年的时间

热门文章

  1. Unity3d 制作铁链子
  2. ERROR queue.BoundedInMemoryExecutor: error producing records0] org.apache.parquet.io.ParquetDecoding
  3. 电力载波JST-HPLC-485 系列载波设备(HPLC转485三相透传设备)在物联网通信领域的应用
  4. 人工智能是不是对人体油画有什么误会?
  5. CCD、COMS,数字摄像头、模拟摄像头 区别和联系
  6. 普通文本格式转html
  7. c++day04 友元函数
  8. 无法定位程序输入点__gxx_personality_sj0 于动态链接库libstdc++-6.dll
  9. svn 无法检出的问题
  10. 如何判断一个数是小数(面试题)