学习数据结构的目标: 学会从问题出发,分析和研究计算机加工的数据的特性,以便为应用所涉及的数据选择适当的逻辑结构、存储结构及相应的操作方法,为提高利用计算机解决问题的效率服务。
- 数据结构:数据元素的集合及元素间的相互关系和构造方法
- 数据的逻辑结构:元素间的相互关系
- 数据结构(按照逻辑关系分类):线性结构、非线性结构
- 非线性结构:树结构、图结构
- 存储结构:数据结构及元素之间关系的存储
3.1 线性结构
- 主要用途:用于对客观世界中具有单一前驱和后继的数据关系进行描述。
- 特点:特点是数据元素之间呈现一种线性关系,即元素“一个接一个排列”
3.1.1 线性表
线性表: 常采用顺序存储和链式存储,主要基本操作是插入、删除、查找。
1、线性表的定义
一个线性表是n(n>=0)个元素的有限序列。非空线性表的特点如下:
- 存在唯一的一个称作“第一个”的元素。
- 存在唯一的一个称作“最后一个”的元素。
- 除第一个元素外,序列中的每个元素均只有一个直接前驱。
- 除最后一个元素外,序列中的每个元素均只有一个直接后驱。
2、线性表的存储结构
有顺序储存和链式存储两种
一、线性表的顺序存储: 用一组地址连续的存储单元依次存储线性表中的数据元素,从而使逻辑上相邻的两个元素在物理位置上也相邻。元素间的逻辑关系无需占用额外的空间。
优点: 可以随机存取表中的元素。
缺点: 插入和删除操作需要 移动元素。
二、线性表的链式存储: 是用通过指针链接起来的结点来存储数据元素,基本结点结构为:数据域 | 指针域
数据域: 存储数据元素的值。
指针域: 存储当前元素的直接前驱或直接后驱的位置信息(指针)。
特点是结点的地址不要求连续(存储数据元素必须存储元素之间的逻辑关系)、结点空间只有在有需要的时候才申请,无需事先分配。
结点之间通过指针域构成一个链表,若节点只有一个指针域,则称为线性链表(单链表)
三、链式存储结构下的插入和删除
在链式存储结构下插入和删除其实都是对相关指针进行修改,如下:
在P所指节点后插入S元素结点:
图解:
S–>next = P–>next
P–>next = S
先将p所指节点的后继结点指针赋给s所指节点的指针域,然后将p所指结点的指针域修改为指向s所指结点。
在单链表中删除p所指结点的后继结点:
图解:
q = p–>next;
p–>next = p–>next–>next;
free(q)
令临时指针q指向待删除结点,然后修改p所指结点的指针域为指向p所指结点的后继结点的后继结点,完成操作,随后释放q所指结点的空间。
四、头结点:
头结点不存储数据元素,引入头结点是为了简化对链表状态的判定和处理,将其作为链表的第一个结点并令头指针指向该结点。
五、实现过程:
假设L为头结点,现在链表中查找第k个元素。
{ LinkList p; int i;
i = 1; p = L–>next; /初始时,令p指向第一个元素结点,i为计数器/
while(p&&i<k){
p=p–>next; i++;
}
if (p&&i==k) return p;
return NULL;
}
六、总结:
当采用链表作为存储结构时,不能对数据元素进行随机访问,但是具有插入和删除不需要移动元素的优点。
根据结点中指针域的设置方式,还有其他几种链表结构。
- 双向链表。每个结点包含两个指针,分别指出当前元素的直接前驱和直接后继。特点:可以从表中任意结点出发,从两个方向上遍历链表。
- 循环链表。在单向链表(或双向链表)的基础上令表尾结点的指针指向链表的第一个结点,构成循环链表。特点:可以从表中任意结点开始遍历整个链表。
- 静态链表。借助数组来描述线性表的链式存储结构,用数组元素的下标表示元素所在结点的指针。
双向链表的插入操作:
s–>front = p–>front;
p–>front–>next = s;
s–>next = p;
p–>front = s;
双向链表的删除操作:
p–>front–>next = p–>next;
p–>next–>front = p–>front;free(p);