数据结构——线性结构

终于可以开始填这个坑了233333
————————————
像上一篇文章说的数据结构要解决的问题是数据如何在内存中存储,以什么结构存储。
用张仰森老师的话来说,就是“数据以及数据之间的关系。”
今天主要要聊的就是线性结构。

这里说的线性结构,是指从逻辑结构上来划分的。
说到这,就不得不提下物理结构。所谓逻辑结构,就是在逻辑、理论上定义的结构,而物理结构是指在实际的内存中数据的存储结构。

比如,有这么一种结构,每个元素只有唯一的前驱、唯一的后继、第一个元素没有前驱、最后一个元素没有后继。满足这样要求的结构就是线性结构。
而上面所说的结构仅仅是逻辑上的结构,而不是物理上的结构。之前已经学过的数组、链表,都可以表示这种结构。但是数组在物理结构上来说每个元素就是相邻摆放的,而链表的节点在实际内存中的分布却是分散的,仅仅是由于指针的存在好像使得前后有了关系。

C语言已经内置支持了最简单的线性结构,就是数组。
声明一个数组之后,就能得到N个相邻的物理空间。这N个空间中的变量就满足之前说的规律。
而概念里说的元素,可以是一个int,也可以是一个结构体。在本系列文章或者代码、我通常会用一个整数来代表一个元素。
而实际的应用中,一个元素可能是一个结构体、指针(最常见的是结构体的指针)。

说完了数据和数据之间的个关系,那么这个数据结构就已经快说完了,还差对应的一系列操作。
这里仅列出简单的几个操作,也就是增删改查,实际实现时候包括但不限于以下几种,候根据需要来写。
向线性表插入一个元素
从线性表删除一个元素
从线性表中查找关键字为i的元素
修改线性表中某个元素

套路:确定操作之后如何开始写代码
0.定义自己的数据结构(这里以C为例,所以写的是结构体。不排除以后用Java类的可能性=-=)
然后对每个操作按下面四个步骤
1.确定函数名、参数类型、参数数量
2.预想函数执行前内存的状态
3.确定函数执行后预期的内存状态
4.返回值类型极其含义

接下来将以两种实现方式进行说明,参考代码在github(求star求follow):
第一种:用数组实现的线性表
头文件:https://github.com/956237586/DataStructure-C/blob/master/DataStructure-C/1.1.linearlist.h
源文件:https://github.com/956237586/DataStructure-C/blob/master/DataStructure-C/1.1.linearlist.c

0.定义一个新的类型,叫List
//我默认大家都能看懂C语言,看不懂的请回上一篇看基础测试或者重新看下C的教程=-=
如上面代码中5-9行所示,我把一个数组和数组的长度定义为一个List。
createList,创建一个列表,
参数:长度
执行前状态:无
执行后状态:初始化一个指定长度的List
返回值定义 返回一个List
其他的同理。。。。

定义完了函数先写测试程序,如上面的主函数。
然后依次实现每个函数,createList的时候注意,在申请完内存后一定要初始化内存中每个地址的默认值,要么用NULL要么用0要么用参数,不要啥都不做,免得给自己挖坑
其实这也就是构造函数做的事情。。。
(代码中createList的时候其实应该返回指针更好一些,不然会再复制一份函数内部的List再return回去,然而这是很久之前的代码了,我懒得重写了=-=凑合着看吧233333)
代码中的问题(现在看当时写的代码简直是naive=-=):
风格不是很好。。。比如我省略了一些大括号,这是不好的习惯。。。
容错处理并没有做到最好,有些地方并不是一定会成功的操作我都没有做判断,比如realloc之后的返回值可能为NULL然而我没判断。。。

第二种实现方法,用链表实现线性表:
参考代码我就不贴上来了,去github看吧。。。
地址:
头文件:https://github.com/956237586/DataStructure-C/blob/master/DataStructure-C/1.2.linearlist.h
源文件:https://github.com/956237586/DataStructure-C/blob/master/DataStructure-C/1.2.linearlist.c

这是最基本的线性结构,之后所有复杂的结构都是这两种结构的组合、延伸,说白了再复杂的结构最终也能用这两种形式来组合表达。
其实计算机内存是线性的,所以某种意义上来说,所有的存储都是在把非线性的结构转换成线性结构来表达、然后存储、运算。

建议自己亲手仿写一个自己版本的线性表。。。。
写完后再继续往下看。
刚刚的线性表我们可以对对任意位置、任意元素进行操作。
如果我们加一点点限制,就出现了新的数据结构(其实并不是新的数据结构,只是操作操作受限的线性表而已)
也就是栈、和队列。
如果我们限制只能在一端增加和删除元素,那么就是栈。
如果我们限制只能在一端增加、在另一端删除,那么就是队列。
代码稍稍改一改就能搞定,参考代码地址如下:
https://github.com/956237586/DataStructure-C/tree/master/DataStructure-C
其中2.1是用数组实现的栈。
2.2是用链表实现的栈、也叫链栈。
(待补充详细说明,链栈的部分有个经典写法。。。)
3.1是用数组实现的队列,一般来说为了节省空间,数组会重复利用已有的空余内存,所以一般是循环队列。
(待补充详细说明,循环队列的关键在push和pop如何复用空余空间。。。。)
3.2是用链表实现的队列。(未完待续)
——————————–
今天先写到这=-=之后再继续写。。。。

0 Comments
Leave a Reply