线性表
定义:线性表表示是具有相同特性数据元素的有限序列。
相同特性:把同一类事物归类,方便处理
有限:表中元素个数为n,n有限大可为0
序列:表中元素排成一列,体现了一对一的逻辑特性(一个元素仅有一个前驱和一个后继)
存储结构
1.顺序存储结构
以元素在计算机内“物理位置相邻”来表示线性表当中数据元素之间的逻辑关系;确定了存储线性表的起始位置,线性表当中任一数据元素都可以随机存取。
C语言中可用数组来实现此结构,线性表的长度可变,需要的存储空间随问题不同而不同,可使用动态分配的一维数组。
#define init_size 100
#define size 10
#define Type int
typedef struct {
Tpye *elem;
int length;
int listsize;
}SqList;
int main()
{
SqList L;
L.elem = (Type *)malloc(init_size * sizeof(Type));
if(!L.elem)
{
exit(0);
}
}
2.链式存储结构
用一组任意的存储单元存储线性表的数据元素,存储单元可以连续也可以不连续;数据元素的存储映像称为节点,包括两个域:存储数据元素信息的域称为数据域,存储直接后继存储位置的域称为指针域。
(1)单链表
Head->头节点->开始节点->…->尾节点(好用)
Head->next == NULL 为空
Head->开始节点->…->尾节点
Head == NULL 为空
typedef struct LNode{
int data;
struct LNode *next;
}LNode;
LNode *L;
L = (LNode*)malloc(sizeof(LNode));
(2)双链表
typedef struct DLNode{
int data;
struct LNode *next;
struct LNode *prior;
}DLNode;
DLNode *L;
L = (DLNode*)malloc(sizeof(DLNode));
Head->next为空时,链表为空
(3)循环链表
Head->next == Head 链表为空
Head->next == Head 或 Head->prior == Head 链表为空
3.题目汇总
(1)单链表L(带头结点)为空的条件:
L->next == NULL
(2)非空的单循环链表(带头结点)的终端结点(p指向)满足:
p->next == L && p!=L
(3)带头结点的双循环链表L为空的条件是
L->prior == L && L->next == L
------循环链表没有空指针------
(4)线性表采用链表存储时,其结点地址连续与否均可
顺序存储结构与链式存储结构的特性对比
1.顺序表的插入和删除元素可能会导致移动大量元素的连带操作,而链表不会。
2.在单链表中任意一个节点的位置,顺序表支持随机存取,而链表不行
3.双链表、循环单链表、循环双列表等,仅知道任一结点地址的情况下推知其余结点的地址,但不支持随机存取
4.链表可能会定义一个额外的指针,最常见的尾指针。
5.线性表用顺序存储结构,必须占用一片连续的存储空间。链式存储结构则不需要这样。
6.从表的整体来看,一般顺序表存储空间利用率低于链表;从单个存储单元来看,顺序表存储空间利用率要高于链表
6.顺序存储结构的优点为存储密度大
存储密度为结点数据本身所占的的存储量和整个结点结构所占的存储量之比。
7.数据项构成数据元素,数据元素构成线性表
8.静态链表需要分配大量的连续空间,插入和删除不需要移动元素,为线性表
静态链表结构
typeddef struct
{
int data;
int next;
}SLNode;
SLNode SLink[size];
SLink[p].next = SLink[p].next;
//类比于链表p->next = p->next
9.第i个元素的前驱结点:顺序表
元素移动次数计算
1.顺序表插入元素
在任一位置插入元素概率:p = 1 / (n+1) n+1个空
在i位置之前插入元素,需移动n-i个元素
插入元素平均移动元素个数为:n/2 (1/(n+1)) * (n*(n+1)/2)
2.顺序表删除元素
在任一位置删除元素概率:p = 1 / n
在i位置之前删除元素,需移动n-i-1个元素
删除元素平均移动元素个数为:(n-1)/2
静态链表
链表结构:
typedef struct
{
int data;
int next;
}SLNode;
SLNode SLink[maxsize];
int p = Ad0; //类似于定义一个指针
SLink[p].data;
SLink[p].next;
//p后插入结点q
SLink[q].next = SLink[p].next;
SLink[p].next = q;
静态链表中指针指示的是链表中下一元素在数组中的地址