目录

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

这天,小明和小亮刚做完核酸,看了看下一节课,是张三老师的数据结构课程,决定不逃课了,兴致冲冲地来到教室,看到老师正拿着一本《大话数据结构》的书看着,边看边点头,让他两甚是好奇

小小提醒:结尾有思维导图,点赞评论就是对我最大的鼓励呀

什么是数据结构

小明和小亮和张三打了个招呼,倒是把张三惊了一跳,好奇的小明便问他,什么是数据结构啊? 于此同时,上课铃也响了

张三老师倒是反过来问了小明一句,我们在学习过程中,经常用什么方式把数据放在一起呢?

小明还在想着啥是数据结构
小亮倒是不自信地说了一句——变量?
张三摇摇头,是放在一块的数据哦?
小亮又猜,数组?

没错,张三点点头,数组就能够看成一种数据结构

数据结构就是一群数据按照一定的结构组合在一起就可以理解为数据结构

官方语言是 :数据结构(Data Structure)是计算机存储、组织数据的方式,指相互之间存在一种或多种特定关系的 数据元素的集合。

当然,你也可以把他叫做数据的结构

常见的数据的结构有这么几种
有线性的,有树形的,有图形的,这些我们以后都会接触
咱们这两天的重点,就是把线性的数据结构弄明白

好,小明和小亮异口同声地答道

数据结构的特性

小亮又摸摸脑袋,那老师,我们知道数据结构,能用他做什么呢?
小明在知道数组也是数据结构后,就抢答道
能够找数据,能够添加数据和删除数据,数组就能这么干

张三老师很高兴,没错,数据结构的基本操作就是
创建,增删查改

小明这是就问了,那增删查改,不同的结构有什么不一样呢?
好问题,当我们讲完了数据结构,你就明白了,张三说

线性表

我们现在要介绍第一种数据的结构
线性表

小亮疑惑道,为什么他叫线性表呢?难道它像锁链一样一个环套着一个环连在一起吗?

没错,我们经常使用线性表而不自知,当数据是首尾依次相连的,那这种数据结构就是线性表
但是注意,这种相连是逻辑上的相连,并不只是空间上的相连

小明脱口: 数组就是典型的线性表,但是我们好像还只接触过数组,还有空间不相连的线性表吗?
好像真是这样,小亮也赞同

张三笑笑说,数组是一种线性表,但是线性表还包含许多不同的兄弟
链表,栈,队列等,像链表,就不一定是空间上的相连

顺序表

我们先来介绍线性表的第一个兄弟—顺序表

小亮吐槽道,说过好多遍了,不就是数组么?
张三说是,但不完全是

顺序表指的是 一组数据是依次放在一段连续的物理地址的 线性结构

啥呀,小亮说
小明解释说,就是 你的数据是连着放的,放数据的空间也是连着的

张三看小亮明白了,继续说
顺序表和数组的的区别就是,不按空间顺序地放数据,但是顺序表的数据是要按空间顺序放的

这有是什么意思,小亮又懵了,小明也不知道

张三就随手画了一张图

小亮很快就明白了,数据结构还是要画图,才能看明白

创建一个动态顺序表

随后,张三老师继续道,顺序表有静态的顺序表和动态的顺序表
静态就是说,连续的空间开辟后没有再添加和减少的可能

那如果我的一块空间能存100个数,只用了5个,那不是就浪费95个了吗?
那如果我要存储100个数,空间只有5个,那不就存不下了吗?

动态储存能够减少空间的浪费

是的,所以我们一般使用动态的顺序表,但是怎么样去创建一个动态的顺序表呢?
他还有什么好处呢?

动态开辟的信息储存在堆区中,这些信息在函数栈帧销毁后不会消失,我们在这个基础上才能操作顺序表

小亮很麻溜地就定义了一个结构体,叫做顺序表

typedef struct sequencelist
{int* Link;
}SL;int main()
{SL* ps;ps->psl = (int*)malloc(10*sizeof(int));
}

很快小亮就意识到一个问题,我要什么时候扩容呢?
他问张三,张三随后展示出了顺序表的定义

typedef int Datatype
typedef struct sequencelink
{Datatype* Link;int size;int capcity;
}SL;

小明立刻指出,哦,size 记录的是顺序表中实际存储的数据个数,capcity 就是说顺序表的容量,当我要扩容,只要判断 size 是否和 capcity 相等就可以了

张三点点头,我们先初始化一个顺序表吧,然后测试一下吧

void SLInit(SL* ps)
{ps->Link = NULL;ps->size = 0;ps->capcity = 0;
}void Test1()
{SL s1;SLInit(&s1);
}

随后我们可以先把扩容拿出来写一个函数
如果我们最开始给的空间是 4 个空间,随后每次增加大的空间是上一次的两倍
成功开辟后,要修改原来顺序表的地址

void checkLink(SL* ps)
{assert(ps);if(ps->size == ps->capcity){int newcapcity = capcity>0?capcity*2:4;Datatype* newlink = (Datatype*)realloc(newcapcity * sizeof(Datatype));if(newLink == NULL){perror("checklink");exit(-1);}ps->Link = newlink;ps->capcity = newcapcity;}
}

顺序表的增删查改

随后张三马不停蹄进入下一个环节
曾经说过,数据结构最常见的操作是什么?
增删查改,小亮抢答道
那不同的位置是不是操作的方式是不同的? 小明发出疑问

没错,现在我们看看如何在顺序表的尾部增加元素

尾插和尾删除

一个顺序表示什么样子呢?,自问自答画起了图
补充 顺序表的图片,上面有 size 和 capcity

尾插

size 记录了数据的元素个数
如果我们在最后增加一个元素,是不是在size 处插入数据
size 是不是要自加呢?

张三循循善诱
这时小明又提出问题,如果空间不够,就需要扩容了对吗?
对的,随后张三写下了这个代码

void SLPushBack(SL* ps,Datatype x)
{assert(ps);checkLink(ps);ps->Link[size] = x;ps->size++;
}

那尾删也是类似的咯? 随后小亮照猫画虎写了这么一段

void SLPopBack(SL* ps)
{assert(ps);ps->size--;
}

但是小明发现了问题,如果size 为0,size 就不能再减了
如果再减,下一次的插入数据元素会导致越界访问了
然后通过一点点的修改,让程序在违规操作时报错

void SLPopBack(SL* ps)
{assert(ps);assert(ps->size>0);ps->size--;
}

小亮说,小明你可真tnd是个天才
随后张三老师的笑声迸溅出来,笑着说
这些代码是不是很简单嘞?

时间复杂度和空间复杂度都是 O(1)
所以顺序表是非常适合尾插和尾删的

头插头删

但是我们看一下头插和头删,就是在顺序表的头部放置数据
张老师又举起满是灰尘的手,在黑板上把整个过程画出来

头插

如果我们要在顺序表的开头插入一个 4
就要 顺序表后面数字要依次向后移动


小亮 说,为什么是从三开始向后移到空白的地方,然后是2移动到三的地方,然后依次类推呢?

张三说 : 如果我们反过来,先从1向后移动到2,这个时候 2就变成了 1 ,然后还是1向后移动到3 这是就让顺序表里面的元素都改变了呀


随后思考的小明写出了如下的代码


void SLPushfront(SL *ps,Datatype x)
{assert(ps);checkLink(ps);for(int i = size-1;i>=0;i--){ps->Link[i+1] = ps->Link[i];        }ps->Link[0] = x;ps->size++;
}

张三老师点点头,补充道,没错,但是我们要注意 i 的取值
如果是 i = size

for(int i = size;i>0;i--)
{ps->Link[i] = ps->Link[i-1];
}

并且记得因为是添加元素,要检查扩容,并且在 size++ ,所以画图是最好的帮手,想清楚再去写代码是一个好习惯

头删

既然我们尾删,那我们就可以有头删
张三说,我们类比一下头插,不难发现,头删也是需要移动数据的
我们把最开头的元素拿出来,后面的数据紧跟着就要填充之前的空位

小亮 说,是不是长这样?

是的,张三说,但是为什么你不从最后一个元素,也就是4开始向前移动呢?
小亮说,如果四向前移动,之前的三就会被拷贝变成4,3就消失了
然后 2 也会被拷贝变成 4 ,这样就失去了移动元素的意义了
张三很高兴,没错,就是这样的
紧接着,他让小亮写出代码
小亮也很快就写了出来

void SLPopfront(SL* s)
{assert(s);for(int i = 1;i<size;i++){p->Link[i-1] = p->Link[i];}p->size--;
}

小明看完后便又发现了问题,如果 size == 0?
这是小亮忙说,提醒得对,我差点忘了
随后加上

void SLPopfront(SL* s)
{assert(s);assert(s->size>0);//这句for(int i = 1;i<size;i++){p->Link[i-1] = p->Link[i];}p->size--;
}

任意位置的插入和删除

插入

在最后,我们在头插和头删思路的基础上,进一步做到任意位置的删除和插入
老规矩,我们先讲插入吧

小明很快发现,插入和头插的方式只是位置不同,元素都是从前向后依次移动元素,空出那个应该插入的位置,然后插入元素
知道这个道理,爱动手的小明就开始写下了这个代码

void SLInsert(SL* ps,int pos,Datatype x)
{assert(ps);assert(pos>=0);assert(pos<=ps->size);checkLink(ps);for(int i = size-1;i>=pos;i--){ps->Link[i+1] = ps->Link[i];}ps->Link[pos] = x;ps->size++;
}

删除

看到爱徒已经能够写出代码,张三也就接着讲
这是小亮打岔了,那按照道理,任意位置删除的方式也就和头删差不多咯
图大概就是这样的

然后就写下了这个代码

void SLErase(SL* ps,int pos)
{assert(ps);assert(ps->size>0);assert(ps->pos>=0);assert(ps->pos<=size);for(int i = pos+1;i<size;i++){ps->Link[i-1] = ps->Link[i];}ps->size--;
}

但是小明很快发现不对

assert(ps->size>0);
assert(ps->pos<=size);

size 的位置本来没有数,怎么能减呢?
应该是 pos<size
那这样说的话 size>0 因为 pos 的限制,就不需要了,所以程序要这样稍微修改一下

void SLErase(SL* ps,int pos)
{assert(ps);assert(ps->pos>=0);assert(ps->pos<size);for(int i = pos+1;i<size;i++){ps->Link[i-1] = ps->Link[i];}ps->size--;
}

小亮点点头,果然小明还是严谨一些

但是这是,小亮发现,如果我能够修改任意位置的元素,那头和尾只是任意位置的特殊情况而已,那我的头删和头插,尾删和尾插是不是只要调用这两个任意插入就足够了呢?

没错,你掌握了精髓,张三为你点赞

查找和打印

随后铃声打了,张三老师急着下课,开始火速讲课

张三的嘴像机关枪一样
如果我们想要删除在顺序表中特定的值,怎么办呢?
我们要先找到这个数,然后调用我们的任意删除
我们就需要一个查找函数,遍历一遍即可
没有找到我们就返回 -1

int SLsearch(SL* ps,Datatype x)
{assert(ps);for(int i = 0;i<ps->size;i++){if(ps->Link[i] == x){return i;}}return -1
}

并且在调试过程中,我们总是想打印整个顺序表,也是遍历一遍即可

void SLPrint(SL* ps,Datatype x)
{assert(ps);assert(ps->size>0);for(int i = 0;i<ps->size;i++){printf("%d ",ps->Link[i]);}printf("\n");
}

正当老师准备开溜
小明叫住他,老师,空间还没释放呢!!
你来写吧,我先去吃饭了,老师身子跑到了走廊
无奈小明只能这样写下来

void SLDestroy(SL*ps)
{assert(ps);free(ps->Link);ps->Link = NULL;ps->size = 0;ps->capcity = 0;
}

随后走廊传来一声喊叫,下次讲链表啊~

总结

希望大家看完,能够有所收获
如果有错误,请指出我一定虚心改正
动动小手点赞
鼓励我输出更加优质的内容

[数据结构]数据结构简介和顺序表相关推荐

  1. 数据结构之python实现顺序表

    数据结构之python实现顺序表 顺序表是指采用顺序存储的方式来存储数据元素的线性表. 初始化以及创建顺序表 class SequenceList(object):def __init__(self) ...

  2. 逆置单链表c语言程序,(数据结构C语言版)顺序表和单链表的逆置

    <(数据结构C语言版)顺序表和单链表的逆置>由会员分享,可在线阅读,更多相关<(数据结构C语言版)顺序表和单链表的逆置(7页珍藏版)>请在人人文库网上搜索. 1.实验1-1顺序 ...

  3. java数据结构与算法之顺序表与链表深入分析

    转载请注明出处(万分感谢!): http://blog.csdn.net/javazejian/article/details/52953190 出自[zejian的博客] 关联文章: java数据结 ...

  4. 数据结构学习笔记:顺序表的删除操作及其演化题目总结

    目录 前言 例题 类似题目1 类似题目2 类似题目3 类似题目4 类似题目5 结语 前言 文章代码皆在Dev-C++ 5.11中测试,主要是总结一些方法,从而总结一些规律使自己进一步地深化学习内容,仅 ...

  5. 【数据结构与算法】顺序表V3.0的Java实现

    更新说明 经过了顺序表V1.0的根据接口编写成型.顺序表V2.0的功能大幅度增强,这里推出了顺序表V3.0,功能的丰富性不及V2.0,但加入了迭代器,代码的编写也更加的合理了,应该说是比较好的作品了. ...

  6. 数据结构 严薇敏 顺序表的实现(增 删 改)及其使用方法详解

    时间复杂度 数据结构 时间复杂度和空间复杂度 目录 1.线性表 2.顺序表 2.1概念及结构 2.2 接口实现 SeqList.h SeqList.c 2.2.1初始化链表以及销毁链表的实现 初始化顺 ...

  7. (PTA数据结构与算法) 6-2 顺序表操作集 ——请告诉我什么是顺序表!!!

    6-2 顺序表操作集 (20 分) 本题要求实现顺序表的操作集. 函数接口定义: List MakeEmpty(); Position Find( List L, ElementType X ); b ...

  8. 数据结构--学生成绩管理系统(顺序表)

    一. 实验目的: 1.通过此次课程设计学生成绩管理系统的题目,掌握链表等数据结构的基本操作方面的知识,并能灵活的解决一些基本的问题,加深对其性质及各项操作的理解: 2. 将所学数据结构方面的知识与具体 ...

  9. 【数据结构】手撕顺序表

    文章目录 一.什么是线性表 二.顺序表 三.手撕顺序表 属性定义 构造方法 接口实现 确保顺序表空间 增加元素 打印顺序表 判断顺序表中是否包含某个元素 查找元素 获取 pos 位置的元素 将 pos ...

最新文章

  1. POJ-2513 Colored Sticks 字典树,欧拉回路
  2. Citrix Port(常用端口)
  3. Python中的iteritems()和items()
  4. .NET Core开发实战(第25课:路由与终结点:如何规划好你的Web API)--学习笔记(下)...
  5. javascript消除字符串两边空格的两种方式,面向对象和函数式编程。python oop在调用时候的优点...
  6. 基于java的qq屏幕截图工具的设计与实现_几款鲜为人知的实用工具,你都尝试过吗?...
  7. 我为什么放弃了 Chrome?
  8. 谷歌发布自然问答数据集 Natural Questions
  9. 【Python实例第2讲】特征提取集成方法
  10. Pytest报告添加描述时报错:AttributeError: ‘TestReport‘ object has no attribute ‘description‘
  11. 计算机开关机命令,电脑定时关机命令取消以及开启方法介绍
  12. 图片在线编辑器怎么使用教程
  13. C语言:输入年份,判断生肖
  14. 使用Elasticsearch和Kibana挖掘邮箱
  15. 【MATLAB-app】如何使用键盘回调以及在app设计中应用
  16. Dragonfly——一款功能强大的在线家庭装潢设计软件
  17. redis incr mysql_INCR
  18. Office的Ctrl C,Ctrl V使用过多?一起看看python如何处理
  19. 梳理:WPS JS宏之WPS表格单元格读写值
  20. 艾森哲面试 Accenture

热门文章

  1. 解决Simplify chained comparison
  2. Praat使用 | 辅助Praat进行标注的工具
  3. Linux设备驱动开发详解【三】_Linux 内核及内核编程
  4. 谈谈自己的未来规划和学习方法
  5. X-MAN丨华为郑叶来:不畏浮云遮望眼,做有信仰的云
  6. 性格内向的人,是否适合做产品经理 ?
  7. 为什么你学过Java却忘光了——记第一次助教同学见面会
  8. 数学推理相关的几个名词及LaTeX用法
  9. 第二宇宙速度的小学生难度推导
  10. Zephyr启动过程与中断响应