逻辑结构上呈线性分布的数据元素在实际的物理存储结构中也同样相互之间紧挨着,这种存储结构称为 线性表的顺序存储结构 。

也就是说,逻辑上具有线性关系的数据按照前后的次序全部存储在一整块连续的内存空间中,之间不存在空隙,这样的存储结构称为顺序存储结构。

使用顺序存储结构存储的数据,第一个元素所在的地址就是这块存储空间的首地址。通过首地址,可以轻松访问到存储的所有的数据,只要首地址不丢,数据永远都能找着(一根绳上的蚂蚱,要有就都有)。

使用线性表的顺序存储结构生成的表,称为 顺序表 。


图1 顺序表结构示意图

顺序表的实现方法

顺序表中存放数据的特点和数组这种数据类型完全吻合,所以顺序表的实现使用的是数组。

数组实现顺序表的存储结构时,一定要注意预先申请足够大的内存空间,避免因存储空间不足,造成数据溢出,导致不必要的程序错误甚至崩溃。

顺序表的存储结构

在建立顺序表时,除了预先申请内存空间,还需要实时记录顺序表的长度和顺序表本身申请的内存大小,便于后期对顺序表中的数据元素进行调取。
 
所以,要自定义顺序表的结构:

  1. typedef struct Table{
  2. int * head;//声明了一个名为head的长度不确定的数组,也叫“动态数组”
  3. int length;//记录当前顺序表的长度
  4. int size;//记录顺序表分配的存储容量
  5. }table;

顺序表的创建

顺序表的建立,也就是顺序表进行初始化,在预先申请内存空间的同时,给变量size和length赋初值:

  1. table initTable(){
  2. table t;
  3. t.head=(int*)malloc(Size*sizeof(int));//构造一个空的顺序表,动态申请存储空间
  4. if (!t.head) //如果申请失败,作出提示并直接退出程序
  5. {
  6. printf("初始化失败");
  7. exit(0);
  8. }
  9. t.length=0;//空表的长度初始化为0
  10. t.size=Size;//空表的初始存储空间为Size
  11. return t;
  12. }

顺序表查找元素

在数组中查找某个数据元素时,可以采取多种查找算法,例如二分查找、插值查找、斐波那契查找算法等。

具体的查找算法以及各自的时间复杂度后续章节会介绍。

根据顺序表中存储的数据的特点,选择合适的算法。这里,采用顺序查找算法(普通的遍历算法)。

实现代码:

  1. //查找函数,其中,elem表示要查找的数据元素的值
  2. int selectTable(table t,int elem){
  3. for (int i=0; i<t.length; i++) {
  4. if (t.head[i]==elem) {
  5. return i+1;
  6. }
  7. }
  8. return -1;//如果查找失败,返回-1
  9. }

顺序表中更改元素

顺序表中更改数据元素,最简单直接的方式就是:调用查找算法找到该数据元素的位置,直接在该位置上更改。

实现代码:

  1. //更改函数,其中,elem为要更改的元素,newElem为新的数据元素
  2. table amendTable(table t,int elem,int newElem){
  3. int add=selectTable(t, elem);
  4. t.head[add-1]=newElem;//由于返回的是元素在顺序表中的位置,所以-1就是该元素在数组中的下标
  5. return t;
  6. }

顺序表插入元素

插入数据元素,无非三种情况:

  1. 在表头插入
  2. 在表的中间某个位置插入
  3. 直接尾随顺序表,作为表的最后一个元素

无论在顺序表的什么位置插入数据元素,解决办法都是:找到要插入的位置,将后续数据元素整体向后移动一个位置,最后直接在腾出来的位置上插入数据元素。

实现代码:

  1. //插入函数,其中,elem为插入的元素,add为插入到顺序表的位置
  2. table addTable(table t,int elem,int add)
  3. {
  4. //判断插入本身是否存在问题(如果插入元素位置比整张表的长度+1还大(如果相等,是尾随的情况),
  5. //或者插入的位置本身不存在,程序作为提示并自动退出)
  6. if (add>t.length+1||add<1) {
  7. printf("插入位置有问题");
  8. return t;
  9. }
  10. //做插入操作时,首先需要看顺序表是否有多余的存储空间提供给插入的元素,如果没有,需要申请
  11. if (t.length==t.size) {
  12. t.head=(int *)realloc(t.head, (t.size+1)*sizeof(int));
  13. if (!t.head) {
  14. printf("存储分配失败");
  15. return t;
  16. }
  17. t.size+=1;
  18. }
  19. //插入操作,需要将从插入位置开始的后续元素,逐个后移
  20. for (int i=t.length-1; i>=add-1; i--) {
  21. t.head[i+1]=t.head[i];
  22. }
  23. //后移完成后,直接将所需插入元素,添加到顺序表的相应位置
  24. t.head[add-1]=elem;
  25. //由于添加了元素,所以长度+1
  26. t.length++;
  27. return t;
  28. }

注意:在此程序中,当数组存储空间不足时,使用realloc函数每次额外多申请 1 个int型的存储空间,这么做还不是最优。最好的办法就是每次发现空间不够时,多申请几个内存空间,这么做的好处是:在后续做插入操作过程中不需要每次都运行realloc函数,提高了程序的运行效率。

顺序表删除元素

在数组中删除元素时,只需将该元素所在位置后的所有数据元素整体前移 1 个位置即可。

前移的过程中被删除元素被后一个元素覆盖掉,间接实现了删除操作。

实现代码:

  1. table delTable(table t,int add){
  2. if (add>t.length || add<1) {
  3. printf("被删除元素的位置有误");
  4. exit(0);
  5. }
  6. //删除操作
  7. for (int i=add; i<t.length; i++) {
  8. t.head[i-1]=t.head[i];
  9. }
  10. t.length--;
  11. return t;
  12. }

完整的程序

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #define Size 4
  4. typedef struct Table{
  5. int * head;
  6. int length;
  7. int size;
  8. }table;
  9. table initTable(){
  10. table t;
  11. t.head=(int*)malloc(Size*sizeof(int));
  12. if (!t.head)
  13. {
  14. printf("初始化失败");
  15. exit(0);
  16. }
  17. t.length=0;
  18. t.size=Size;
  19. return t;
  20. }
  21. table addTable(table t,int elem,int add)
  22. {
  23. if (add>t.length+1||add<1) {
  24. printf("插入位置有问题");
  25. return t;
  26. }
  27. if (t.length>=t.size) {
  28. t.head=(int *)realloc(t.head, (t.size+1)*sizeof(int));
  29. if (!t.head) {
  30. printf("存储分配失败");
  31. }
  32. t.size+=1;
  33. }
  34. for (int i=t.length-1; i>=add-1; i--) {
  35. t.head[i+1]=t.head[i];
  36. }
  37. t.head[add-1]=elem;
  38. t.length++;
  39. return t;
  40. }
  41. table delTable(table t,int add){
  42. if (add>t.length || add<1) {
  43. printf("被删除元素的位置有误");
  44. exit(0);
  45. }
  46. for (int i=add; i<t.length; i++) {
  47. t.head[i-1]=t.head[i];
  48. }
  49. t.length--;
  50. return t;
  51. }
  52. int selectTable(table t,int elem){
  53. for (int i=0; i<t.length; i++) {
  54. if (t.head[i]==elem) {
  55. return i+1;
  56. }
  57. }
  58. return -1;
  59. }
  60. table amendTable(table t,int elem,int newElem){
  61. int add=selectTable(t, elem);
  62. t.head[add-1]=newElem;
  63. return t;
  64. }
  65. void displayTable(table t){
  66. for (int i=0;i<t.length;i++) {
  67. printf("%d",t.head[i]);
  68. }
  69. printf("\n");
  70. }
  71. int main(){
  72. table t1=initTable();
  73. for (int i=1; i<=Size; i++) {
  74. t1.head[i-1]=i;
  75. t1.length++;
  76. }
  77. printf("原顺序表:\n");
  78. displayTable(t1);
  79. printf("删除元素1:\n");
  80. t1=delTable(t1, 1);
  81. displayTable(t1);
  82. printf("在第2的位置插入元素5:\n");
  83. t1=addTable(t1, 5, 2);
  84. displayTable(t1);
  85. printf("查找元素3的位置:\n");
  86. int add=selectTable(t1, 3);
  87. printf("%d\n",add);
  88. printf("将元素3改为6:\n");
  89. t1=amendTable(t1, 3, 6);
  90. displayTable(t1);
  91. return 0;
  92. }

输出结果:

原顺序表:
1234
删除元素1:
234
在第2的位置插入元素5:
2534
查找元素3的位置:
3
将元素3改为6:
2564

顺序表的优缺点

顺序表实现的基础,完全借用了数组这一数据类型,优点是在对数据进行遍历时,数据在连续的物理空间中存放,查找的速度比较快。

但是由于数组本身的限制,在向顺序表中新增或者删除数据元素时,如果被操作位置后续有很多数据元素,后续所有的数据元素都需要前移,最后虽然实现了功能,但是程序总体效率不高。

线性表:2.线性表的顺序存储结构--顺序表及C语言实现相关推荐

  1. 线性表的顺序存储结构——顺序表

    什么是线性表? 线性表简称表,是n(n>=0)个具有相同类型的数据元素的有限序列,线性表中数据元素的个数称为线性表的长度,长度为0的表称为空表. 什么是顺序表? 线性表的顺序存储结构称为顺序表. ...

  2. 线性表—顺序存储结构-顺序表

    把线性表中的所有元素按照其逻辑顺序依次存储到从计算机存储器中指定存储位置开始的一块连续的存储空间中. 一般分配空间是需要一些冗余的. 专门开辟一块空间线性表有n个数据 占用空间:n*sizeof(El ...

  3. c语言实现顺序存储程序,线性表的顺序存储结构动态态分配C语言实现

    线性表的顺序存储结构动态态分配C语言实现 线性表的顺序存储结构动态态分配C语言实现 初始化执行期间通过malloc函数为数组申请空间,程序运行期间若空间不够可通过realloc函数在保留原存储值的前提 ...

  4. vue+ele 实现v-for动态数据循环表单,然后对每个结构进行表单校验的方法

    vue+ele 实现v-for动态数据循环表单,然后对每个结构进行表单校验的方法 项目开发时遇到form结构是动态遍历出来的,但是每个遍历出来的表单都需要做相对应的检验处理,ele提供的办法只能对单个 ...

  5. 顺序表(一篇带你掌握顺序表)

    目录 一.顺序表是什么 1.1 概念 1.2 分类 1.3 结构 二.顺序表的基本操作 2.1 前绪准备 2.2 初始化 2.3  扩容 2.5 尾插 2.6 打印 2.7 尾删 2.8 头插 2.9 ...

  6. 顺序表的插入与删除java_C++实现顺序表的常用操作(插入删出查找输出)

    实现顺序表的插入,删除,查找,输出操作在C语言中经常用到.下面小编给大家整理实现代码,一起看下吧 代码如下所示: #include using namespace std; #define MAXSI ...

  7. 将两个有序顺序表合并为一个新的有序顺序表

    将两个有序顺序表合并为一个新的有序顺序表 题目要求 基本思想 核心代码 完整代码(C++) 题目要求 将两个有序顺序表合并为一个新的有序顺序表,并由函数返回合并后的顺序表. 基本思想 非常经典的题目, ...

  8. 将两个有序顺序表合并为一个新的有序顺序表MergeList_Sq

    将两个有序顺序表合并为一个新的有序顺序表,输出合并后的顺序表的所有数据元素: #include<stdio.h> #include<stdlib.h> #define LIST ...

  9. 顺序表:将两个有序表合并成一个新的有序顺序表

    题目:将两个有序表合并成为一个新的有序顺序表,并由函数返回结果顺序表. 算法思想:假设有AB两个顺序表,要使得合并后仍然有序,因此可以将AB中对应的数作比较,把较小的放入C中,比完之后将剩下的依次放入 ...

最新文章

  1. 【TP3.2】路由匹配和规则
  2. PHP语言特性和各版本的差异
  3. wegame饥荒一直连接中_腾讯WeGame注册用户超3亿 国产游戏销量超500万
  4. 汉诺塔III HDU - 2064
  5. list python 转tensor_Tensorflow模型量化4 --pb转tflite(uint8量化)小结
  6. WINDOWS下的squid
  7. 4.7、Bootstrap V4自学之路------组件---广告屏
  8. eclipse导入myeclipse项目
  9. java模块间调用信息_java与c++模块之间的交互方法?
  10. BootLoader学习笔记(1)
  11. kubenetes 1.4 修改kubelet启动参数修改方法
  12. MFC 教程【1_MFC概述 】
  13. putty screen 快捷键
  14. 番外5. Python OpenCV 中滑动条详细说明与常见问题解决方案
  15. 巨佬Jake Wharton谈Android对Java 8的支持
  16. 海外代理ip池购买推荐,易路s5海外ip代理如何提取使用?
  17. 麻将判断胡牌 java_麻将基本胡的算法——Java
  18. nand2tetris 布尔函数和和门逻辑路线图
  19. C# 产生验证码 利用背景图片绘制
  20. HDFS名字空间(NameSpace)

热门文章

  1. 程序员什么时候该考虑换工作
  2. pycharm引用python_在Python/Pycharm中找不到引用“xxx”
  3. python 执行shell_python中执行shell的两种方法总结
  4. 利用 QQWry.Dat 实现 IP 地址高效检索(PHP)
  5. 暴涨30%!马斯克突然杀入推特:当上最大股东!
  6. 星巴克又出事 被强制执行1087万!网友:欠租了吗?
  7. 别人家的公司!雷军发红包 人均39万
  8. 行拘被释放,车顶维权女车主首发声!出手就是对特斯拉放大招?
  9. 华为鸿蒙OS 2.0系列Beta 2发布:逼近公测版
  10. 我们采访了小鹏G3「高温抑菌」项目负责人,发现智能车OTA并不简单