前言

数据结构,一门数据处理的艺术,精巧的结构在一个又一个算法下发挥着他们无与伦比的高效和精密之美,在为信息技术打下坚实地基的同时,也令无数开发者和探索者为之着迷。

也因如此,它作为博主大二上学期最重要的必修课出现了。由于大家对于上学期C++系列博文的支持,我打算将这门课的笔记也写作系列博文,既用于整理、消化,也用于同各位交流、展示数据结构的美。

此系列文章,将会分成两条主线,一条“数据结构基础”,一条“数据结构拓展”。“数据结构基础”主要以记录课上内容为主,“拓展”则是以课上内容为基础的更加高深的数据结构或相关应用知识。

欢迎关注博主,一起交流、学习、进步,往期的文章将会放在文末。


这一节我们将开始总结一个常见的数据结构:线性表。
由于线性表的内容较多,本节只能总结部分内容。
主要为两种基础的线性表,数组和链表。在简单介绍其定义之后,重点会放在实现对其各种操作的简单实现及封装。
由于内容较多,本篇截止到数组的操作封装完毕。链表的内容会放在之后的文章中
本节思维导图如下:


线性表的定义

线性表是较为常见的线性数据结构,又称为有序表(Ordered List)。简单点说,线性表就是节点的有限序列。

使用上一节的数据的逻辑结构的定义,可以从教科书上找到如下线性表定义:

一个线性表是由0个或多个具有相同类型的节点组成的有序集合。这里用(a1,a2,a3...an)来表示一个线性表,n为自然数。
当n=0时,线性表中无节点,称为空表;
当n≥1时,称a1位线性宝的表头(head),称an为线性表的表尾(tail);
当n≥2时,称ai为ai+1的前驱节点,称ai+1是ai的后继节点,其中1≤i<n;
表头结点无前驱节点,标为节点无后继节点;当n=1是,线性表中仅有一个节点时,该点既是表头又是表尾。

我们常用list来表示一个线性表,根据存储结构的不同,线性表又可分为顺序表和链表。Java中就使用ArrayList和LinkedList来分别表示这两种线性表。本文中的各种封装也基于这种命名

线性表的基本操作

对线性表的基本操作有很多,给他们分分类,可以分成

  • 线性表本身操作:的创建、遍历、规模及是否为空等访问
  • 数据的操作:插入、删除、修改
  • 数据的查询:查询元素,查询下标等查询方式

下面的内容将会重点放在这些基本操作的实现及分析上。

顺序存储结构——数组

常见的线性表中最最常见的存储结构——顺序存储。这样的线性表又称作顺序表,其中各元素不仅在逻辑上是线性相邻的,在空间中也是连续的。

我们最常用的数组就是这样一种顺序表。

数组的基本操作及封装

下面就来分析一下数组如何实现基本操作并进行封装

创建顺序表

创建数组是最基础的操作了。

在C语言中,我们可以直接在栈空间中创建一个数组,也可以动态申请一一片内存在堆空间中创建一个数组。以整形数组为例,对应的操作如下:

//假设数组规模为N
int array[N];
int *array = malloc(N * sizeof(int));

在Java语言中,只有数组的头引用是在栈区中创建的,数组的体则都在堆区中。同样以整形为例,操作如下:

//假设数组规模为N
int[] array = new int[N];

遍历顺序表

遍历一个数组也是最基本的操作,由于数组中元素的个数通常是不定的,也就是变量,所以遍历数组的操作通常使用循环来完成。同样以整形数组为例,C和Java使用for循环遍历数组的基础格式如下:

//假设数组中元素个数为n
for(int i = 0;i < n;i++){array[i];
}

Java中还提供了增强for循环用以遍历数组:

for(int k : array){k;
}

复杂度:O(n)

查询下标为k的元素

对于顺序表,也就是数组,按照下标查找元素可以说是他最得心应手的操作了。由于数据都是按照顺序且相邻存储的,访问确定下标的元素仅需要直接根据首地址进行加法运算即可获得对应下标的元素。

我们假设要访问的下标为k(k从0开始计数)
则在C语言中,可以直接使用指针运算获得下标为k的元素,可以以使用中括号
Java中没有指针,直接使用中括号即可

以整形数组array为例,其长度为len,当前元素个数为size,查询位置为k

//C
int selectByIndex(int * array,int size,int k){if(k < 0 || k > size)exit(0);return array[k];
}
//java
class ArrayList{int[] array;int len;int size;public int selectByIndex(int k) throws Exception{if(k < 0 || k > size)throw new Exception();return array[k];}
}

复杂度:O(1)

查询特定的元素

同样作为查询,查询特定元素的复杂性就要高于按照下标查询。原因在于线性表中的下标是有顺序的且各元素占位等长,对应下标可以计算。但是元素内容却没有顺序,因此只能遍历整个数组进行查找。

以整形数组array为例,查询值为value的元素的下标,数组长度为len,未查找到该元素则返回-1

//C
int selectByValue(int value,int * array,int size){for(int i = 0;i < size;i++){if(array[i] == value)return i;}return -1;
}
//Java
class ArrayList{//线性表类int[] array;int len;public int selectByValue(int value){for(int i = 0;i < len;i++){if(array[i] == value)return i;}return -1;}
}

复杂度:O(n)
(注:由于C语言和Java的编程思想不同(面向过程和面向对象),同样的算法可能会以不同的形式被封装在不同的结构下,C语言的函数往往会按照功能封装在一个文件中调用时需传入要处理的对象,Java则会将函数作为方法封装在对象节点内部。下文的各个方法封装都会有如此差别)

插入数据

插入一条数据通常指插入数据到指定位置,如插入到第k位。

对于顺序表,插入一条数据需要先将该位置后面的元素统一移动一格为新元素腾出空间,再将新元素插入其中。

以整形数组array为例,其长度为len,当前元素个数为size,插入元素为value,插入位置为k

//C
int insert(int * array,int len,int size,int value,int k){if(len == size || k < 0 || k > len)return 0;for(int i = len;i > k;i--){array[i] = array[i - 1];}array[k] = value;return 1;
}
//java
class ArrayList{int[] array;int len;int size;public boolean insert(int value,int k){if(len == size || k < 0 || k > len)return false;for(int i = len;i > k;i--){array[i] = array[i - 1];}array[k] = value;size++;return true;}
}

复杂度:O(n)

删除数据

删除某个数据的前提是检索到该数据,所以也可以分成删除某下标的数据和删除某个数据。

考虑到删除某个数据也可以分解成先查询某数据的下标再删除该下标对应的数据,因此只需要实现删除某下标的数据即可。

在顺序表中,直接删除某下标的数据会导致空缺,从而破坏顺序表的存储连续性。因此在删除某个元素之后还需要对数组进行维护,维护的操作就是将被删除的元素后面的元素依次向前移动。对于整形数组,可直接采用覆盖代替删除。

以整形数组array为例,其长度为len,当前元素个数为size,删除位置为k

//C
int remove(int * array,int size,int k){if(k < 0 || k > size)return 0;for(int i = k;i < size - 1;i++){array[i] = array[i + 1];}return 1;
}
//Java
class ArrayList{int[] array;int len;int size;public boolean remove(int k){if(k < 0 || k > len)return false;for(int i = k;i < size - 1;i--){array[i] = array[i + 1];}size--;return true;}
}

复杂度:O(n)

修改数据

同删除数据类似的,修改数据也面临着筛选数据的问题。因此也只需要我们封装好修改第k位数据的功能即可。

数组的优点就在于可以直接按照下标进行访问,因此对于修改制定下标的元素,数组的效率是非常高的。

以整形数组array为例,其长度为len,当前元素个数为size,修改值为value,修改位置为k

//C
int update(int * array,int size,int value,int k){if(k < 0 || k > size)return 0;array[k] = value;return 1;
}
//java
class ArrayList{int[] array;int size;int len;public boolean update(int k,int value){if(k < 0 || k > size)return false;array[k] = value;return true;}
}

复杂度:O(1)

顺序表的封装(以整形为例)

C
/*头文件*/
#ifndef ARRAYLIST_H_INCLUDED
#define ARRAYLIST_H_INCLUDED#include<malloc.h>int * createArray(int);//创建数组
int deleteArray(int*);//释放数组
int update(int*,int,int,int);//修改元素
int remove(int*,int,int);//删除元素
int insert(int*,int,int,int,int);//插入元素
int selectByValue(int*,int,int);//查找特定元素
int selectByIndex(int*,int,int);//根据下标查找元素#endif // ARRAYLIST_H_INCLUDED/*源文件*/
#include "ArrayList.h"int * createArray(int len){return (int*) malloc(len * sizeof(int));
}
int deleteArray(int* array){free(array);
}
int update(int * array,int size,int value,int k){if(k < 0 || k > size)return 0;array[k] = value;return 1;
}
int remove(int * array,int size,int k){if(k < 0 || k > size)return 0;for(int i = k;i < size - 1;i++){array[i] = array[i + 1];}return 1;
}
int insert(int * array,int len,int size,int value,int k){if(len == size || k < 0 || k > len)return 0;for(int i = len;i > k;i--){array[i] = array[i - 1];}array[k] = value;return 1;
}
int selectByValue(int * array,int value,int size){for(int i = 0;i < size;i++){if(array[i] == value)return i;}return -1;
}
int selectByIndex(int * array,int size,int k){if(k < 0 || k > size)exit(0);return array[k];
}
Java
public class ArrayList {int[] array;int len;int size;public ArrayList(int len) throws Exception {if(len <= 0) {throw new Exception();}this.len = len;array = new int[len];size = 0;}public int selectByIndex(int k) throws Exception{if(k < 0 || k > size)throw new Exception();return array[k];}public int selectByValue(int value){for(int i = 0;i < len;i++){if(array[i] == value)return i;}return -1;}public boolean insert(int value,int k){if(len == size || k < 0 || k > len)return false;for(int i = len;i > k;i--){array[i] = array[i - 1];}array[k] = value;size++;return true;}public boolean remove(int k){if(k < 0 || k > len)return false;for(int i = k;i < size - 1;i--){array[i] = array[i + 1];}size--;return true;}public boolean update(int k,int value){if(k < 0 || k > size)return false;array[k] = value;return true;}
}

往期博客

  • 【数据结构基础】数据结构基础概念

参考资料:

  • 《数据结构》(刘大有,杨博等编著)
  • 《算法导论》(托马斯·科尔曼等编著)
  • 《图解数据结构——使用Java》(胡昭民著)

【数据结构基础】线性数据结构——线性表概念 及 数组的封装(C和Java)相关推荐

  1. 算法与数据结构基础四----数据结构基础之动态数据结构基础:链表上

    接着上一次https://www.cnblogs.com/webor2006/p/15195969.html的数据结构继续往下学习,这次会进入一个非常重要的数据结构的学习----链表,这个是未来学习复 ...

  2. 有关数据结构基础知识(数据结构 严蔚敏版)

    1. 数据结构是一门研究非数值计算程序设计中的操作对象 以及这些对象之间的关系和操作的学科 2. 研究包括逻辑结构和存储结构 1) 逻辑结构(从具体问题抽象出来的数学模型)分为 集合结构 线性结构 树 ...

  3. 【数据结构与算法】广义表的储存结构和结点定义的Java实现

    广义表的存储结构 广义表中元素类型不统一,在Java语言的环境下难以用顺序结构存储.链式结构则相对灵活,可以解决广义表的递归和共享问题,所以常用链式存储结构来对广义表进行存储. 如果广义表不空,则可以 ...

  4. j - 数据结构实验:哈希表_一看就懂的数据结构基础「哈希表」

    哈希表 哈希表(Hash table),是存储键值(Key Value)对数据的一种数据结构. 例如,我们可以将人的名字作为键,性别作为值来存储.通过把键映射到表中的一个位置来访问数据,以提高查找速度 ...

  5. 数据结构基础之动态顺序表详解

    文章目录 前言 一.动态顺序表的概念 二.顺序表的结构体 三.基本接口 1.SeqListInit(初始化数组) 2.SeqListDestory(销毁数组) 3. SeqListCheckCapac ...

  6. 数据结构基础(18) --哈希表的设计与实现

    哈希表 根据设定的哈希函数 H(key)和所选中的处理冲突的方法,将一组关键字映射到一个有限的.地址连续的地址集 (区间) 上,并以关键字在地址集中的"映像"作为相应记录在表中的存 ...

  7. 【数据结构基础】线性数据结构——栈和队列的总结及封装(C和java)

    前言 数据结构,一门数据处理的艺术,精巧的结构在一个又一个算法下发挥着他们无与伦比的高效和精密之美,在为信息技术打下坚实地基的同时,也令无数开发者和探索者为之着迷. 也因如此,它作为博主大二上学期最重 ...

  8. 【数据结构基础】图的遍历方法与应用

    前言 数据结构,一门数据处理的艺术,精巧的结构在一个又一个算法下发挥着他们无与伦比的高效和精密之美,在为信息技术打下坚实地基的同时,也令无数开发者和探索者为之着迷. 也因如此,它作为博主大二上学期最重 ...

  9. 【数据结构基础】图的存储结构

    前言 数据结构,一门数据处理的艺术,精巧的结构在一个又一个算法下发挥着他们无与伦比的高效和精密之美,在为信息技术打下坚实地基的同时,也令无数开发者和探索者为之着迷. 也因如此,它作为博主大二上学期最重 ...

最新文章

  1. php mysql日期戳转时间戳_php日期转时间戳,指定日期转换成时间戳
  2. v8学习笔记(三) 运行时环境
  3. python二维数组去重_PHP二维数组去重
  4. ie11浏览器可以下载java吗_如何卸载IE11? 如何安装低版本的IE浏览器?
  5. 8年前端开发的知识点沉淀(不知道会多少字,一直写下去吧,)
  6. java之split用法注意
  7. smart原则_目标管理:OKR与SMART原则的异同
  8. 微信小程序实现将图片保存到手机相册
  9. linux 下svn: E175002: 方法 REPORT 失败于 “/svn/GameSvn/!svn/me”: 不能读块分割符: 安全连接切断 (https://192.168.0.88)
  10. 如何在淘宝上利用信息差赚钱
  11. Sql Server Update 更新数据
  12. 培根芦笋卷+蚝油家常豆腐+春笋甜椒拌饭
  13. 本机无法 正常连接到桌面端Ubuntu虚拟机
  14. 关于四叶玫瑰花数的问题
  15. 下载并安装vue-devtools(详细步骤)
  16. 解决latex图片浮动体过多的报错:Output loop---100 consecutive dead cycles和Too many unprocessed floats
  17. tableau:凹凸图
  18. oracle只导入dmp中指定表,oracle 如何导入dmp文件到指定表空间
  19. 多端口天线自动化测试系统,定制化解决方案
  20. 高校房产管理中数图互通CAD图形管理模块详细功能方案

热门文章

  1. 解决SecureCRT上下左右显示ABCD问题
  2. Visual Studio C++ 远程调试 附加到进程 MSVSMON.EXE
  3. 山东大学2020计算机二级考试,山东省2020年3月计算机二级考试报名通知
  4. 穿越Java - 基础篇 第一章 快速带你入门 | 第3节 Java语言发展史
  5. Chrome灵魂插件,我的十八搬兵器!
  6. 物联网技术在智慧城市中的应用
  7. Linux内核学习(七):linux kernel内核启动(一):概述篇
  8. 身份证工具类-获取性别、年龄、出生日期
  9. 布隆过滤器的原理及使用
  10. 桂林电子科技大学计算机评估,【图片】2016年第四次教育部学科评估结果【桂林电子科技大学吧】_百度贴吧...