1.线性表(List):由零个或多个数据元素组成的有序序列,
类似于排队~~在一个队伍中,只要每个人记住他前面队员就可以了,
(线性表的顺序存储结构即是数组了,数组因为在内存中是连续的,所以每个元素之间也是有前后关系的)
2对于线性表来说,n=0 时为空表,(空表也是有意义的,就像一个队伍解散了,但是队伍名还存在,下次还能把人集合起来)
3.C语言有两大数据类型:
(1)原子类型:不可以再分解的基本数据类型,eg:整形、字符型、浮点型等
(2)结构类型:由若干个类型组成,是可以再分解的,eg:整形数组,是由若干个整形数据组成的
4.线性表的常见操作:
InitList( *L ) :初始化操作,建立一个空的线性表L
ListEmpty(L) : 线性表置空
ClearList( * L) :将线性表清空
GetElem( L,i,*e) : 获取线性表L中第 i 个元素,并保存在指针e中
LocateElem(L,e) : 查找操作
ListInsert(*L,i,e): 插入操作~~
ListLength(L) : 获取元素个数
(要注意,上面的 i 都是从0 开始的,因为线性表是数据结构,是写给人看的,不是写给机器看的,所以不用从0 开始)
************************************************************************************************************************************
线性表的顺序存储结构
1.线性表的顺序存储结构其实和我们在C语言中接触到的数组是一样的,但是在数据结构中表示方式不太一样
2.顺序存储结构容易定位多少号元素,时间复杂度是O(1),但删除和插入比较麻烦,
删除最后一个元素,时间复杂度是O(1),删除第一个元素,时间复杂度是O(n),平均的是O(n/2),
但根据时间复杂度的定义,时间复杂度应该还是O(n)
3.插入一个元素的思路
for( k=L->length-1 ; k>=i ; k--)
L->data[k+1] = L->data[k];
在第 i 号元素处插入元素a ,则 i 后面的元素都要后移一位
(后移就是把原来第K+1号位置的数,用第K号元素替代)
4.删除操作
只需把第K号元素的值用第K+1号替代即可(也是用for循环)
5.注意,线性表的长度和数组的长度不一样,定义 的数组长度要大于线性表实际元素个数
************************************************************************************************************************************
线性表的链式存储结构
1.线性表的链式存储结构即是链表,包括单链表,双链表、循环链表等
对于线性表来说,考查最多的就是其链式存储结构,而链式存储结构里最重要的就是单链表了
2.链式存储结构每个元素多用一个位置来存放指向下一个元素的位置的指针,这样,从第一个元素可以找到
第二个元素,第二个可以找到第三个……这样就能遍历了
3.链式存储结构每个元素称为一个结点,结点包括数据域、指针域。
n个结点链接成一个链表,即为线性表(a1 ,a2,a3,……an)的链式存储结构~~
因为链表的每个结点中只包含一个指针域,所以叫做单链表
4.对于线性表来说,总得有个头和尾,链表也不例外,
我们把链表中的第一个结点的存储位置叫做头指针,最后一个结点指针为空NULL
5.头指针和头结点的异同
头指针:
(1)头指针是指链表指向第一个结点的指针,若链表有头结点,则是指向头结点的指针
(2)头指针具有标识作用,所以常用头指针冠以链表的名字(指针变量的名字)
(3)无论链表是否为空,头指针均不为空
头结点:
(1)头结点是为了操作的统一和方便而设立的,放在第一个元素的结点之前,其数据域一般无意义(但也可以用来存放链表的长度)
(2)有了头结点,对在第一元素结点前插入结点和删除第一结点,其操作与其他结点的操作就统一了
(3)头结点不一定是链表的必须元素
6.单链表的获取(查询链表中某个元素):
获得链表第 i 个数据的算法思路:
---声明一个结点p 指向链表第一个结点,初始化 j 从从 1 开始
---若 j<i 时,就遍历链表,让 p 的指针向后移动,不断指向下一个结点,j+1
---若到链表末尾p为空,则说明第 i 个元素不存在,否则查找成功,放回结点 p 的数据
注:
---说白了,就是从头开始找,知道第 i 个元素为止
---由于这个算法的时间复杂度取决于 i 的位置,当 i= 1 时,则不需要遍历,而 i=n 时则遍历 n-1 次才可以。因此最坏情况的时间复杂度为 O(n)
---由于单链表的结构中没有定义表长,所以不能实现知道要循环多少次,因此也就不方便使用 for 来控制循环
---其核心思想叫做“工作指针后移”,这其实也是很多算法的常用技术。
7.单链表的结构指针描述(C语言版)
typedef struct Node
{
ElemType data; // 数据域
struct Node* Next; // 指针域
} Node;
typedef struct Node* LinkList; // 相当于用 LinkList 来表示单链表指针
单链表中,由于每个结点中保存一个数据和一个指针,由于指针指向的是下一个结点,即指向的元素是结点类型的,所以返回值也是结点类型的,
所以Next 的数据类型是 struct Node* 类型的
(eg: char* p; 这里p为什么是是char* 类型呢?因为p 指向的是一个字符串;同样的,上面Next指向的是一个结点,所以也是Node*类型的)