【数据结构(C语言版)系列一】 线性表
最近开始看数据结构,该系列笔记简单记录总结下所学的知识,更详细的推荐博主StrayedKing的数据结构系列,笔记部分也摘抄了博主总结的比较好的内容。
一些基本概念和术语
数据是对客观事物的符号表示,在计算机科学中是指所有能输入到计算机中并被计算机程序处理的符号的总称。
数据元素是数据的基本单位,在计算机程序中通常作为一个整体进行考虑和处理。有时,一个数据元素可由若干个数据项组成,数据项是数据的不可分割的最小单位。
数据对象是性质相同的数据元素的集合,是数据的一个子集。
数据结构是相互之间存在一种或多种特定关系的数据元素的集合。根据数据元素之间关系的不同特性,通常由下列4类基本结果:
(1)集合
(2)线性结构 结构中的数据元素之间存在一个对一个的关系;
(3)树形结构 结构中的数据元素之间存在一个对多个的关系;
(4)图形结构或网状结构 结构中的数据元素之间存在多个对多个的关系。
数据元素之间的关系在计算机中由两种不同的表示方法:顺序映像和非顺序映像,据此得到两种不同的存储结构:顺序存储结构和链式存储结构。顺序映像和特点是借助元素在存储器中的相对位置来表示数据元素之间的逻辑关系;非顺序映像的特点是借助表示元素存储地址的指针表示数据元素之间的逻辑关系。
算法是对特定问题求解步骤的一种描述,它是指令的有限序列,其中每一条指令表示一个或多个操作;一个算法还具有5个重要特性:
(1)有穷性 一个算法必须总是(对任何合法的输入值)在执行有穷步之后结束,且每一步都可在有穷时间内完成。
(2)确定性 算法中每一条指令必须有确切的含义,读者理解时不会产生二义性。在任何条件下,算法只有唯一的一条执行路径,即对相同的输入只能得到相同的输出。
(3)可行性 一个算法是能行的,即算法中描述的操作都是可以通过已经实现的基本运算执行有限次来实现的。
(4)输入 一个算法有零个或多个的输入 ,这些输入取自于某个特定的对象的集合。
(5)输出 一个算法有一个或多个的输出,这些输出是同输入有着某些特定关系的量。
线性表——顺序存储结构
线性表的顺序的顺序表示指的是用一组地址连续的存储单元依次存储线性表的数据元素。
假设线性表的每个元素需占用l个存储单元,并一所占的第一个单元的存储地址作为数据元素的存储位置。则线性表中第i+1个数据原色的存储位置LOC(ai+1)和第i个数据元素的存储位置LOC(ai)之间满足下列关系:
LOC(ai+1) = LOC(ai) + l
一般来说,线性表的第i个数据元素ai的存储位置为:
LOC(ai) = LOC(a1) + (i-1) * l
LOC(a1)指线性表中的第一个数据元素a1的存储位置,通常称做线性表的起始位置或基地址。
只要确定了存储线性表的起始位置,线性表中任一数据元素都可随机存取,所以线性表的顺序存储结构是一种随机存取的存储结构。
若表长为n,为删除或插入元素的时间复杂度为O(n)。
单链表强调元素在逻辑上紧密相邻,所以首先想到用数组存储。但是普通数组有着无法克服的容量限制,在不知道输入有多少的情况下,很难确定出一个合适的容量。对此,一个较好的解决方案就是使用动态数组。首先用malloc申请一块拥有指定初始容量的内存,这块内存用作存储单链表元素,当录入的内容不断增加,以至于超出了初始容量时,就用calloc扩展内存容量,这样就做到了既不浪费内存,又可以让单链表容量随输入的增加而自适应大小。
单链表顺序存储结构如下图:
单链表强调元素在逻辑上紧密相邻,所以首先想到用数组存储。但是普通数组有着无法克服的容量限制,在不知道输入有多少的情况下,很难确定出一个合适的容量。对此,一个较好的解决方案就是使用动态数组。首先用malloc申请一块拥有指定初始容量的内存,这块内存用作存储单链表元素,当录入的内容不断增加,以至于超出了初始容量时,就用calloc扩展内存容量,这样就做到了既不浪费内存,又可以让单链表容量随输入的增加而自适应大小。
单链表顺序存储结构如下图:
线性表——链式存储结构
链式存储删除与插入更方便,不用来回移动大量元素。但与此对应的是存取指定位置元素时将变得费劲,因为顺序存储结构中,通过数组下标就可以获取第i个元素,但是在链式存储中,必须由头指针或尾指针(如果有的话)开始遍历整个链表直至寻找到需要的元素。在元素的查找效率方面,此两种存储结构无明显差异。
最后一个结点指针通常为NULL。如果将最后一个结点的指针指向开头,那么这个链表就成了循环单链表。
有头结点的单链表:有时,在单链表的第一个节点之前附设一个节点,称之为头结点。头结点指针指向的结点数据域为空,指针域存储指向第一个结点的指针(即第一个元素结点的存储位置)。头结点的存在仅仅是作为标记单链表的开始,有头结点的单链表在操作时更加方便,不用专门为头结点的增删情况写额外代码,这一点可以在实际应用中加以体会。
单链表链式存储也用到了动态分配内存。值得注意的是,由于头结点的指针本身就是个结构指针,所以在初始化、创建、销毁等需要改变头结点指针的地方,则要注意函数形参为二级指针,即指向头指针的指针。新手很容易犯的错误是该用二级指针的地方使用了一级指针,这样做的后果就是明明函数内分配了所需内存,但是外面却访问不到,也可能明明函数内销毁掉的内存,外面还可以访问到。这样不仅会引起内存访问差错,甚至会引起程序崩溃,所以,这一点很值得引起重视。
线性表——静态链表
静态链表用数组存放数据,存取方式模拟了系统的malloc分配和free回收机制。
书中的描述如下:
//-----线性表的静态单链表存储结构-----//
#define MAXSIZE 1000
typedef struct{
ElemType data;
int cur;
}componet,SlineList[MAXSIZE];
数组的一个分量表示一个结点,同时用游标(指示器cur)代替指针指示结点在数组中的相对位置,数组的第零分量可看成头结点,其指针域表示链表的第一个结点。这种存储结构仍需要预先分配一个较大的空间,但在作线性表的插入和删除操作时不需要移动元素,仅需修改指针,故仍具有链式存储结构的主要优点。
假设SWieSLinkList型变量,则S[0].cur指示第一个结点在数组中的位置,若设i = s[0].cur,则S[i].data存储线性表的第一个数据元素,且S[i].cur指示第二个结点在数组中的位置。一般情况,若第i个分量表示链表的第k个结点,则S[i].cur指示第k+1个结点的位置。因此在静态链表中实现线性表的操作和动态链表相似,以整形游标i代替动态指针p,i = S[i].cur的操作实为指针后移(类似与p = p->next)。
在《数据结构》原书中,对静态链表的表述是有些复杂的,这里对其进行了适当简化,但中心思想不变。
静态链表是特殊的顺序表,它从数组(一块连续的内存)中孕育,但行为却类似于单链表,它反映出了链式单链表在系统中实现的本质。静态链表依靠自身的一个游标来实现单链表中结构指针的作用,所以,在存取元素时,一方面要考虑静态链表内部的游标变动,另一方面也要考虑整个空间中剩余内存的游标变化,因为整个内存块同样也是通过游标来链接的。
静态链表存储结构及存取机制如下图:
灵活应用typedef来创造新类型,比如在静态空间SPACE定义时,将整个结构数组看做了一个新的类型Component。
关于静态链表的一些操作书中的我看不太明白,参考了博客《数据结构——静态链表》
几个注意点如下:
初始化时别忘了将最后一个指针域指向0;
分配空闲结点时总是取头结点之后的第一个空闲结点,如果空闲链表非空,调整头结点的值;
回收结点时总是将回收的结点放在头结点之后。
#include <stdio.h>
#define N 100
typedef struct{
char data;
int cur;
}SList;
void init_sl(SList slist[]){//初始化成空闲静态链表,
int i;
for(i=;i<N-;i++)
{
slist[i].cur=i+;
}
slist[N-].cur=;//最后一个指针域指向0
}
int malloc_sl(SList slist[]){//分配空闲结点
int i=slist[].cur;//总是取头结点之后的第一个空闲结点做分配,同时空闲链表非空,头结点做调整
if (i)
{
slist[].cur=slist[i].cur;//空闲链表头结点调整指针域
}
return i;//返回申请到的空闲结点的数组下标
}
void free_sl(SList slist[],int k){//将k结点回收
slist[k].cur=slist[].cur;//总是将回收的结点放在头结点之后
slist[].cur=k;
}
线性链表——循环链表
循环链表就是头尾相连,表中最后一个结点的指针域指向头结点,整个链表形成一个环,由此,从表中任一结点出发均可找到表中其他结点。
循环链表的操作和线性链表基本一致,差别仅在于算法中的循环条件不是p或p->next是否为空,而是它们是否等于头指针。
线性链表——双向链表
单链表的单向性是的从某个结点出发只能顺指针往后寻找其他结点,如果要寻找结点的直接前趋,需从表头指针出发。因此,提出了双向链表,一个结点中有两个指针域,其一指向直接后继,另一指向直接前趋。
若d为指向表中某一结点的指针,则有d->next->prior = d->prior->next = d
【数据结构(C语言版)系列一】 线性表的更多相关文章
- 【数据结构(C语言版)系列二】 栈
栈和队列是两种重要的线性结构.从数据结构角度看,栈和队列也是线性表,但它们是操作受限的线性表,因此,可称为限定性的数据结构.但从数据类型角度看,它们是和线性表大不相同的两类重要的抽象数据类型. 栈的定 ...
- 【数据结构(C语言版)系列三】 队列
队列的定义 队列是一种先进先出的线性表,它只允许在表的一端进行插入,而在另一端删除元素.这和我们日常生活中的排队是一致的,最早进入队列的元素最早离开.在队列中,允许插入的一端叫做队尾(rear),允许 ...
- 深入浅出数据结构C语言版(4)——表与链表
在我们谈论本文具体内容之前,我们首先要说明一些事情.在现实生活中我们所说的"表"往往是二维的,比如课程表,就有行和列,成绩表也是有行和列.但是在数据结构,或者说我们本文讨论的范围内 ...
- 【数据结构(C语言版)系列四】 串
串类型的定义 串(或字符串)是由零个或多个字符组成的有限序列,一般记为 s = 'a1a2...an',s为串名.子串在主串中的位置以子串的第一个字符在主串中的位置来表示. 串和表示和实现——定长顺序 ...
- c++学习书籍推荐《清华大学计算机系列教材:数据结构(C++语言版)(第3版)》下载
百度云及其他网盘下载地址:点我 编辑推荐 <清华大学计算机系列教材:数据结构(C++语言版)(第3版)>习题解析涵盖验证型.拓展型.反思型.实践型和研究型习题,总计290余道大题.525道 ...
- 数据结构C语言版 表插入排序 静态表
数据结构C语言版 表插入排序.txt两个人吵架,先说对不起的人,并不是认输了,并不是原谅了.他只是比对方更珍惜这份感情./* 数据结构C语言版 表插入排序 算法10.3 P267-P270 编译 ...
- 数据结构与算法系列2 线性表 使用java实现动态数组+ArrayList源码详解
数据结构与算法系列2 线性表 使用java实现动态数组+ArrayList源码详解 对数组有不了解的可以先看看我的另一篇文章,那篇文章对数组有很多详细的解析,而本篇文章则着重讲动态数组,另一篇文章链接 ...
- 数据结构C语言版 有向图的十字链表存储表示和实现
/*1wangxiaobo@163.com 数据结构C语言版 有向图的十字链表存储表示和实现 P165 编译环境:Dev-C++ 4.9.9.2 */ #include <stdio.h> ...
- 数据结构C语言版 弗洛伊德算法实现
/* 数据结构C语言版 弗洛伊德算法 P191 编译环境:Dev-C++ 4.9.9.2 */ #include <stdio.h>#include <limits.h> # ...
随机推荐
- Java的变量类型
以下内容引用自http://wiki.jikexueyuan.com/project/java/variable-types.html: 一个变量提供了程序可以操作的命名存储.Java中的每个变量都有 ...
- Meteor在手机上运行
在本章中,我们将学习如何在Android设备上运行你的应用程序.最近Meteor刚刚添加此功能适用于Windows操作系统,所以我们需要更新 Meteor 应用到 1.3测试版. 注 在写的时候本教程 ...
- SQL2012 尝试读取或写入受保护的内存。这通常指示其它内存已损坏
今天打开SQL2012,突然就连接不了数据库.一開始还以为是某个server崩溃了.结果试了好几个.都还是如此,弹出提演示样例如以下: 尝试读取或写入受保护的内存.这通常仅仅是其它内存已损坏.(Sys ...
- 解决运行scrapy是报错No module named cryptography,解决cryptography的安装问题,解决libffi的安装问题
在linux下配置完运行是出现ImportError: No module named cryptography.hazmat.bindings.openssl.binding的错误.原因是crapt ...
- Coding Ninja 修炼笔记 (1)
大家好啊~我又回来了. 这次主要是给大家带来一些提升 Coding 效率的建议. 效率都是一点一滴优化出来的,虽然每一条建议给你带来的提升可能都不大,但是积累起来,仍然是一股不可忽视的力量. 第一条 ...
- conda安装速度慢解决办法
注意,清华已经撤掉其ananconda源, 下面的方法已经失效,中科大源好像也不行,如果有解决办法烦请评论告诉我. conda config --add channels https://mirror ...
- 【iOS系列】-程序开启后台运行
[iOS系列]-程序开启后台运行 iOS程序是伪后台的运行,可是有时候我们需要让其在后台也要进行一些操作,我们可以让其伪装成音乐的APP,这样就可以让程序后台进行相关操作了,具体做法如下: 1:在Ap ...
- MVC为Html对象建立一个扩展方法,使用自己的控件就像使用TextBox一样方便
先看一下我想要的结果: 很容易它就是一个单选按钮组,当我后台为Html对象(HtmlHelper的一个实例,它被定义在System.Web.Mvc名称空间下的WebViewPage类,即它对于所有MV ...
- 第一个WordCount类运行
import java.io.IOException; import java.util.*; import org.apache.hadoop.fs.Path; import org.apache. ...
- Java中会存在内存泄露吗?请简单描述。
本文转载自:Java中会存在内存泄漏吗,请简单描述 会.java导致内存泄露的原因很明确:长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露,尽管短生命周期对象已经不再需要,但是因为长生命周 ...