![c23c940dbc56e1b63249c3bc75255614.png](https://i-blog.csdnimg.cn/blog_migrate/7e8287149182a01b1981838929eee404.jpeg)
小发言
写数据结构系列文章的原因: 正是因为我发现自己对于基本的东西都太不懂。大大小小的比赛也没少玩,代码也写了不少,但始终没有突破,到头却发现自己对于基本的知识都掌握的不扎实,真可悲! 数据结构系列文章的亮点: 通过图形化的学习,对每一种算法用图解的方式展开讲解,这样不仅可以剔除掉纯算法的枯燥乏味,而且还便于理解。本系列文章所有的代码本人都会验证通过,并且后期会在leetcode上选取合适的例题进行实际训练。
线性表介绍
线性表是数据结构中的一种存储结构,通俗点来说,就是把所有数据串成一串,然后在存储到物理空间中。
![3bacc71cc83d91a21d9f02dd6a1aa554.png](https://i-blog.csdnimg.cn/blog_migrate/3d77c34369cb5ccdd5217bcad445b098.png)
例如,对于数据
要将其存储到一段空闲的物理空间中,通常有如下两种存法:
数据集中存放
这种存放方式也是大家经常使用的一种存放方式,大多数人最容易想到。
![3592022e28b4db4acaa40f15bf0f0aaa.png](https://i-blog.csdnimg.cn/blog_migrate/093f51262eed5642f5f4dd4a6e40a281.png)
数据分散存放
![9c8ff8aa10ddb411dce9a2d503bec1ee.png](https://i-blog.csdnimg.cn/blog_migrate/77a51a45bb552dec9fbc74910d4f97af.png)
这种存放方式在物理地址空间上看似乱序且不连续,但是当我们按照原先的线性顺序依次遍历时,数据的顺序并不会因物理地址空间的乱序和不连续而出现差错,这也正是线性表的独特之处——用一根线把它们按照顺序串起来 。
顺序存储结构
上面我们介绍了两种存放方式,而第一种数据集中存放,即将数据依次存储在连续的整块物理空间中,这种存储结构称为顺序存储结构(简称顺序表)。可见,顺序表和数据非常相似,我们可以将其与数据类比学习
顺序表的初始化
首先,需要申请足够大小的物理空间,而且为了方便后期使用表中的数据,顺序表还需要实时记录顺序表申请的存储容量和顺序表的长度,也就是表中存储数据元素的个数。 首先,先定义一个顺序表
typedef struct Se_Table{
int * head;//head为一个长度不确定的数组
int length;//当前顺序表的长度
int size;//顺序表分配的存储容量,即顺序表的大小
}se_table;
注意:这里的head是一个未初始化的动态数组,用来存储顺序表中的数据,前往不要只把它看做是普通的指针。 然后就是顺序表的初始化,分两步完成:
- 给 head 动态数据申请足够大小的物理空间(一般情况下,顺序表申请的存储容量要大于顺序表的长度,这样会避免一些数组越界的问题);
- 给 size 和 length 赋初值;
//顺序表初始化
se_table init()
{
se_table t;
t.head=(int*)malloc(5*sizeof(int));//构造一个空的顺序表,动态申请存储空间
if (!t.head) //如果申请失败,作出提示并直接退出程序
{
printf("初始化失败");
exit(0);
}
t.length=0;//空表的长度初始化为0
t.size=5;//空表的初始存储空间为5
return t;
}
对上面提到的这两句代码,
t.length=0;//空表的长度初始化为0
t.size=5;//空表的初始存储空间为5
很多小伙伴可能不理解,长度初始化都为0了,存储空间却为5。其实这两者是互不相关的,初始空间为5,说明我向计算机预先申请了大小为5的存储空间,即t.size=5;,但在这个5存储空间里并没有存储任何数据,因此它的长度就为0,即t.length=0;。
这样我对顺表的初始化已经完成,通过改变size 的大小,我们可以改变预先申请的存储空间大小,接下来,我们就可以对顺序表进行操作了。在主函数添加代码,往顺序表中添加数据
并打印
int main()
{
se_table t=init();;
//向顺序表中添加元素
for (int i=1; i<=5; i++)
{
t.head[i-1]=i;
t.length++;
}
printf("顺序表中存储的元素分别是:n");
for (int i=0;i<t.length;i++)
{
printf("%d ",t.head[i]);
}
printf("n");
return 0;
}
输出如下
![e667dc00f75861c92d7c02dc0fc558c4.png](https://i-blog.csdnimg.cn/blog_migrate/32e2477f4596750686ca6f6a5c271284.png)
顺序表的插入
几乎所有的数据结构都有插入操作,对于顺序表来说,可以根据插入的位置不同分为三种情况:
- 表头插入
- 表尾插入
- 在表中插入
虽然数据元素插入顺序表中的位置有所不同,但我们都是使用的是同一种方式去解决,即:通过遍历,找到数据元素要插入的位置,然后做如下两步工作:
- 将要插入位置元素以及后续的元素整体向后移动一个位置。
- 将要插入的元素放到腾出来的位置上。 例如,我们要在顺序表
中
的位置插入6,需要一下几个步骤
首先找到要插入的目标位置
![d8bebc1ca72bbe84b6d352113a0820ff.png](https://i-blog.csdnimg.cn/blog_migrate/135a141dd23029d598523535c94f6e30.png)
然后将目标位置以后的元素(包括目标位置的元素)整体向后移一个单位
![c9158ed4a5eff06a2aafb48eef51a10b.png](https://i-blog.csdnimg.cn/blog_migrate/dfac553e4a023332182db9d4100583c8.png)
最后就是从此目标位置插入要插入的元素
![be2f202c67e0d2dc89eee45b18c41c8c.png](https://i-blog.csdnimg.cn/blog_migrate/31900d7fc3666a642aa96cf4450d5b42.png)
这里具体的代码不在给出,小伙伴如果想学习的话文章末尾留言即可。
顺序表的删除
顺序表中删除元素,这个实现起来的确没什么水平,非常简单,只需找到目标元素,并将其后续所有元素整体前移 1 个位置即可。后续元素整体前移一个位置,会直接将目标元素删除,可间接实现删除元素的目的。 例如,我们要在顺序表
首先遍历找到6
![1181f30aae9b81af131fcaa34ceeeda2.png](https://i-blog.csdnimg.cn/blog_migrate/32bd5b147bae8a5adc1d34bf7649889e.png)
后面的元素整体向前移一个单位
![f3d3f006ec78954ae739d72d7ab58c3f.png](https://i-blog.csdnimg.cn/blog_migrate/9017d1e3a68d4c9f8ef8aaf8bc2e7752.png)
这样,我们的删除操作就完成了,是不是很简单呀。
顺序表更改元素
顺序表的更改元素也很简单,直接找到要更改的元素,直接修改就行。 例如,我们要在顺序表
首先遍历找到3
![13aab124e473f05d6fe2ee66936b4b00.png](https://i-blog.csdnimg.cn/blog_migrate/ea509b5ca823b21a7f1687c064ad3675.png)
然后就可以直接将其修改为6,无需其他操作
![1b7c82b9998ecd4f25442c3fc5805e81.png](https://i-blog.csdnimg.cn/blog_migrate/af7ec0d8d83b716cdb9957ba086ba09f.png)
总结一下哈
这是数据结构系列文章的第二篇,主要介绍了线性表中的顺序表的相关操作,下一篇将主要介绍链表的相关知识。关于关于顺序表的相关代码本人已全部在linux上验证通过,各位小伙伴如果想要参考请在文章末尾留言。
欢迎关注本人公众号
![5e1f0a6638153a6fe778b3b45746e4be.png](https://i-blog.csdnimg.cn/blog_migrate/f115d47ba36133f263f9ca2e9a4b618f.jpeg)