- 线性表是由n(n>=n)个数据元素(结点) a1,a2,a3,a4…an组成的有限序列.数据元素的个数n定义为表的长度.
当n=0时,称为空表. - 非空的线性表(n>0)记作:L=(a1,a2,a3,a4,a5,a6,…,an)
a1:起始结点,an终止节点
a1为a2的直接前驱,a3为a2的直接后继
例子:
线性表:L=(1,2,3,4,5,6,7,8,9,10)
起始结点:1终端结点:10.
2是3的直接前驱,4为3的直接后继
注意: 线性表中只有1个起始结点,1个终端结点,
起始结点没有直接前驱,只有1个直接后继,
终端结点没有直接后继,只有1个直接前驱,
除了这两个结点外 每个节点有且只有1个直接前驱1个直接后继.
线性表顺序存储的方法:将表中的节点依次存放在计算机内存中 一组连续的存储单元中
特点:
- 数据元素在线性表中的邻接关系决定骑在空间中的存储位置.
- 即逻辑结构中相邻的节点,其存储位置也相邻.
- 顺序存储实现的线性表称为顺序表
顺序表的基本运算
插入(insert) 删除(Delete) 定位(Locate)
注意:当表空间已满,不可再做插入操作.
当插入位置是非法位置,不可做正常的插入操作.
顺序表插入操作过程
- 将表中位置为n,n-1,…,i上的节点,依次后移到位置n+1,n,…,i+1上,空出位置i.
- 在位置i上插入新节点x.(当插入位置为i=n+1时,无须移动节点,直接将x插入表的末尾)
- 该顺序表长度加1
顺序表插入算法的分析
假设线性表中含有n个数据元素,在进行插入操作时,有n+1个位置可插入;在位置i插入时,要移动n-i+1个数据
顺序表删除算法的过程分析
- 若i=n,则只要删除终端结点,无须移动节点;
- 若1=<i<=n-1,则必须将表中位置i+1,i+2,…,n的节点,依次前移到位置i,i+1,…,n-1上,以填补删除造成的空缺.
- 该表长度减1
顺序表删除算法的分析
线性表的删除运算是计算公式 n-i
注意:当要删除元素的位置i不在表长范围时,为非法位置,不能做正常的删除操作.
结论:
顺序存储结构表示的线性表,在做插入或删除操作时,平均需要移动大约一半的数据元素.当线性表的元素量较大,并且经常要对其做插入或删除操作时,这一点需要考虑.
定位
从第一个元素a1起,依次和x比较,直到找到一个与x相等的数据元素,则返回它在顺序表中的下标或序号;当查遍整个表都没有找到与x相等的元素,返回0.
定位运算的分析
定位运算的功能是查找出线性表L中值等于x的结点序号的最小值,当不存在在这种结点时,结果为0.
i从0开始,作为扫描顺序表时的下标:
最好情况,第1个元素的就是x值,此时查找比较次数为1.
最坏情况下,最后1个元素是x值,此时查找比较次数为n
故平均查找长度为(n+1)/2
顺序表算法 | 移动次数 | 平均移动次数 | 时间复杂度 |
---|---|---|---|
插入 | i=n+1时,次数0 ,当n=1时,次数n,一般移动n-i+1 | n/2 | O(n) |
删除 | 最少0,最多n-1,一般n-i | (n-1)/2 | O(n) |
定位 | x是第一个 次数1,x最后一个,查找次数n | (n+1)/2 | O(n) |
线性表的存储
方式:
数据项 | 指针项 |
---|
链表(Link List):链接方式存储的线性表
链表的具体存储表示为:
- 用一组任意的存储单元来存放
- 链表中结点的逻辑次序和物理次序不一定相同,还必须存储指其后继结点的地址信息.
数据项 | 指针项 |
---|---|
data | next |
data域—存放结点的数据域
next域—存放结点的直接后继的地址(位置)的指针域(链域)
- 单链表:所有结点通过指针链接而组成.
- NULL:空指针.
- Head:头指针.
- 尾指针:指向最后一个元素(尾结点)的指针.
单链表的一般图示法
由于我们常常只注重结点间的逻辑顺序,不关心每个结点的实际位置,可以用箭头来表示链域中的指针.
头结点:一般不存数据,利用Head存放该结点地址.
单链表特点总结:
- 链表由头指针唯一确定,单链表可以用头指针的名字来命名.头指针名是head3的链表可称为表head3.
- 起始结点又称为首结点,无直接前驱,故在无头结点时,设头指针head指向首结点.
- 总段结点又称尾结点,无直接后继,故终端结点的空指针域为空,即NULL.
- 除头结点之外的结点为表结点,为方便操作方便,头结点中不存数据.
初始化
- 建立一个空的单链表L,lnitiateLinkList(L);
- 一个空的单链表是一个头指针和一个头结点构成的.
初始化的算法
单链表的类型定义
typedef struct node
{
DataType data;//数据域
struct node *next;//指针域:存放存放直接后继结点的地址
}Node,*LInkList;
初始化的算法
空表由一个头指针和一个头结点组成.算吗描叙:
LinkList initiateLinkList()//建立一个空的单链表
{
LinkList head;//头指针
head=malloc(sizeof(Node));//动态构建一结点,它是头结点
head->next=NULL;
return head;
}
malloc 函数:产生头结点.
malloc函数的使用格式及作用:
(数据类型*)malloc (sizeof (数据类型))
如:int p;
p=(int *) malloc (sizeof(int))
求表长:在单链表存储结构中,表长等于单链表中所含结点的个数(不含头结点).
求表长的算法
int lengthLinklist(LinkList head)
{
Node *p;
p=head;j=0;
while(p->next!=NULL)
{
p=p->next;
j++;
}
return (j)
}
读表元素,定位
定位
- 在线性表的定位运算中,就是给定表元素的值,找出这个元素的位置.
- 在单链表的实现中,则是给定一个结点的值,找出这个结点是单链表的第几个结点.定位运算又称作按值查找.
插入
将值为x的新节点插入到表的第i个结点的位置上,即插入到ai-1与ai之间.
p=malloc(sizeof(Node));p->data=x;//生成新节点
p->next=q->next;//新节点链域指向*q的后继节点
q->next=p;//修改*q的链域
注意:链接操作p->next=q->next和q->next=p两条语句的执行顺序不能颠倒!