数据结构02 线性表之顺序表
这篇文章主要总结线性表之顺序表的相关操作,主要分以下几个部分来总结。
1、线性表是什么? 2、线性表的两种存储结构? 3、顺序表的存储结构表示? 4、顺序表的常见操作和代码实现?
1、线性表是什么
(1)线性表是最基本、最简单的一种数据结构。
(2)线性表中元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的。
(3)如果是一对多就用树来表示,如果多对多就用网状来表示。
(4)线性表具有以下几个特征:
①有且只有一个“首”元素 ②有且只有一个“尾”元素 ③除“首”元素之外,其余元素都有唯一的前驱元素。 ④除“尾”元素之外,其余元素都有唯一的后继元素。
2、线性表的两种存储结构
(1)顺序表,即线性表用顺序存储结构保存数据,数据是连续的。这一篇文章总结的就是顺序表 (2)链表,即线性表用链式存储结构保存数据,数据是不连续的。
3、顺序表的存储结构表示
顺序表在内存中的存储结构为连续的存储单元。
4、顺序表的常见操作和代码实现
顺序表主要有以下几个常见操作,我们一般用数组来保存数据
1、初始化
思路:将数组的长度 size 设为0,时间复杂度为O(1)。
2、求顺序表的长度
思路:获取数组的 size 值,时间复杂度为O(1)。
3、插入元素
思路:分两种情况,一种是插入位置在数组的末尾,这种情况的时间复杂度为O(1) 。另一种情况是插入位置在数组的头部,这时候被插入元素的后续元素都要依次向后移动一位,也就是说整个数组都会移动,所以最坏时间复杂度为O(n)。
4、删除元素
思路:同样分两种情况,一种是删除位置在数组的末尾,不用移动任何元素,因此时间复杂度为O(1),另一种情况是删除位置在数组的头部,这时候被删除元素的后续元素都要依次向前移动一位,因此时间复杂度为O(n)。
5、按序号查找元素
思路:因为顺序表的存储地址是连续的,所以第n个元素的地址偏移量公式为:(n-1)*单元存储长度,不用移动任何元素,因此时间复杂度为O(1)。
代码实现:
package com.demo;
public class SequenceList {
// 默认的长度
final int defaultSize = 10;
// 最大长度
int maxSize;
// 当前长度
int size;
// 顺序表对象
Object[] list;
/**
* 1、顺序表的初始化方法
* 时间复杂度为O(1)
*
* @param size
*/
private void init(int size) {
this.size = 0;
maxSize = size;
list = new Object[size];
}
/**
* 2、求顺序表的长度
* 时间复杂度为O(1)
*
* @return
*/
public int size() {
return size;
}
/**
* 3、插入元素
* 时间复杂度为O(n)
*
* @param index
* @param obj
* @throws Exception
*/
public void insert(int index, Object obj) throws Exception {
// 如果当前顺序表已满,那就不允许插入数据
if (size == maxSize) {
throw new Exception("顺序表已满,无法插入!");
}
// 插入元素的位置编号是否合法
if (index < 0 || index > size) {
throw new Exception("插入元素的位置编号不合法!");
}
// 移动元素。 要从后往前操作
for (int i = size - 1; i >= index; i--) {
list[i + 1] = list[i];
}
list[index] = obj;
size++;
}
/**
* 4、删除元素
* 时间复杂度为O(n)
*
* @param index
* @throws Exception
*/
public void delete(int index) throws Exception {
// 判断当前顺序表是否为空
if (size == 0) {
throw new Exception("顺序表为空,无法删除!");
}
// 删除元素的位置编号是否合法
if (index < 0 || index > size - 1) {
throw new Exception("删除元素的位置编号不合法!");
}
// 移动元素。 要从前往后操作
for (int i = index; i < size - 1; i++) {
list[i] = list[i + 1];
}
size--;
}
/**
* 5、按序号查找元素
* 时间复杂度为O(1)
*
* @param index
* @return
* @throws Exception
*/
public Object get(int index) throws Exception {
// 查找元素的位置编号是否合法
if (index < 0 || index > size - 1) {
throw new Exception("查找元素的位置编号不合法!");
}
return list[index];
}
}
注意:
插入元素时,移动元素要从后往前操作,否则元素会被覆盖。
删除元素时,移动元素要从前往后操作。
5、总结
顺序表插入元素和删除元素的时间复杂度为O(n)
顺序表查找一个元素的时间复杂度为O(1) ,因为顺序表可以通过下标直接访问,所以时间复杂度是固定的,和问题规模无关。
顺序表的优点:随机访问的速度很快;空间利用率高(存储空间连续分配,不存在浪费)。
顺序表的缺点:大小固定(一开始就要固定顺序表的最大长度); 插入和删除元素需要移动大量的数据。
- Log4j详细使用教程
- Android系统线控和歌曲信息屏显的那点事
- 利用Spring中同名Bean相互覆盖的特性,定制平台的类内容。
- 关于java传参
- 浅析ButterKnife
- SQL Server常用语句
- pyecharts(一):Python可视化利器
- 如何在Python中保存ARIMA时间序列预测模型
- SVN+Apache域用户认证配置方法_Windows(转,重新排版,部分内容更新优化)
- sum(x) over( partition by y ORDER BY z ) 分析
- Android DataBinding 数据绑定
- Flask拾遗笔记之上下文
- switch.....case....使用最容易犯错的地方
- electron 构建跨平台桌面应用
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- TS核心知识点总结及项目实战案例分析
- 用Python开发 写个消消乐小游戏
- 原理+代码|Python实战多元线性回归模型
- nestjs+vue+ts打造一个酷炫的星空聊天室(含完整数据库设计)
- JUnit 5基础指南
- 记录一则expdp任务异常处理案例
- Jenkins打造多分支流水线指南
- Spring中的设计模式
- java单元/集成测试中使用Testcontainers
- AOP编程简介及其在Spring框架中的使用
- 使用Maven Archetype创建Java项目模板
- left join左表一定是驱动表吗?
- OneFlow快速上手教程
- [译]HAL-超文本应用语言
- OneFlow | 新深度学习框架后浪(附源代码)