线性表的链式存储
线性表的链式表示又称为非顺序映像或链式映像
结点在存储器中位置是任意的,即逻辑上相邻的数据元素在物理上不一定相邻;链表中的逻辑次序和物理次序不一定相同;访问时只能通过头指针进入链表,并通过每个结点的指针域依次向后顺序扫描其他结点(顺序存取法),因此访问各个结点时间不同
用一组物理位置任意的存储单元来存放线性表的数据元素
链表:n个结点由指针链组成一个链表
结点:数据元素的存储映像
- 数据域:存储元素数值数据
- 指针域 :存储直接后继的存储位置
单链表/线性链表:结点只有一个指针域(后继结点地址)的链表;单链表由头指针唯一确定,因此单链表可以用头指针名字来命名
双链表:结点有两个指针域的链表(一个存放后继结点地址,一个存放直接前驱地址)
循环链表:首尾相连的链表
头指针:指向链表第一个结点的指针
首元结点:链表中存储第一个数据元素a1的结点
头结点:在链表的首元结点之前附设的一个结点;数据域内可以为空,也可以存放线性表长等附加信息,但此结点不能计入链表长度值
优:
-
便于首元结点的处理
-
便于空表和非空表的统一处理
空表:
-
带头结点
-
不带头结点
例:26个英文字母小写存储结构
逻辑结构(a,b,c,d,...,z)
链式存储结构
若使用链式存储结构:
单链表的定义
typedef struct Lnode{
int data;
struct Lnode *next;
}LNode,*LinkList;
单链表的初始化
int InitList_L(LinkList L){
L= (LinkList)malloc(sizeof(LNode));
L->next=NULL;
return 1;
}
单链表的是否为空
int ListEmpty(LinkList L){
if(L->next){
return 0;
} else return 1;
}
单链表的销毁(销毁头结点)
从头指针开始依次释放所有结点:P=L;L=L->next;free(P)
结束条件:L==NULL
int DestroyList_L(LinkList L){
LinkList p;
while (L){
p=L;
L=L->next;
free(p);
}
return 1;
}
清空单链表(保留头结点)
结束条件:p==NULL
int ClearList(LinkList L){
LinkList p,q;
p=L->next;
while(p){
q=p->next;
free(p);
p=q;
}
L->next=NULL;
return 1;
}
求单链表的表长
int ListLength_L(LinkList L){
LinkList p;
p=L->next;
int i=0;
while (p){
i++;
p=p->next;
}
return i;
}
单链表的取值(第i个元素的内容)
循环中的i++, ++i结果一样,但大量数据时++i性能比i++好,i++由于是在使用当前值之后再+1,需要一个临时的变量来转存;而++i则是在直接+1,省去了对内存的操作的环节
int GetElem(LinkList L, int i,int *e){
LinkList p;
p=L->next;
int j=1;
while(p&&j<i){
p=p->next;
j++;
}
if(!p||j>i){
return 0;
}
e=p->data;
return 1;
}
单链表的按值查找(返回地址)
LinkList LocateElem_L(LinkList L,int e){
LinkList p;
p=L->next;
while (p&&p->data!=e){
p=p->next;
}
return p;
}
单链表的按值查找(返回位置序号)
int LocatedElem_L(LinkList L,int e){
LinkList p;
p=L->next;
int j=1;
while (p&&p->data!=e){
p=p->next;
j++;
}
if(p){
return j;
}else return 0;
}
单链表的插入操作
在第i个结点前插入值为e的新结点:s->next=p->next;p->next=s;
int ListInsert_L(LinkList L,int i,int e){
LinkList p,s;
p=L;
int j=0;
while (p&&j<i-1){
p=p->next;
j++;
}
if(!p||j>i-1) return 0;
s->data=e;
s->next=p->next;
p->next=s;
return 1;
}
单链表删除第i个元素
p->next=p->next->next; 保存删除结点的数据域
int ListDelete(LinkList L,int i,int *e){
LinkList p,q;
p=L;
int j=0;
while (p&&j<i-1){
p=p->next;
j++;
}
if(!(p->next)||j>i-1) return 0;
q=p->next;
p->next=q->next;
*e=q->data;
free(q);
return 1;
}
单链表的插入和删除:不需要移动元素,只需要修改指针,时间复杂度为O(1),如果从头查找前驱结点时间复杂度为O(n)
单链表的查找:因只能顺序存取,在查找时要从头指针开始,查找时间复杂度为O(n)
头插法建立单链表
从一个空表开始将最后一个结点依次重复将各结点插入链表的头部(倒位序):p->next=L->next;L->next=p;
void CreateList_H(LinkList L,int n){
L=(LinkList)malloc(sizeof(LNode));
L=NULL;
for (int i = n; i >0 ; i--) {
LinkList p;
p=(LinkList)malloc(sizeof(LNode));
scanf((const char *) p->data);
p->next=L->next;
L->next=p;
}
}
算法时间复杂度是O(n)
尾插法建立单链表
从一个空表开始将最后一个结点依次重复将各结点插入链表的尾部,尾指针r指针链表的尾结点(正位序):p->data=ai;p->next=NULL;r->next=p;r=p;
void CreateList_R(LinkList L,int n){
LinkList r;
L=(LinkList)malloc(sizeof(LNode));
L->next=NULL;
r=L;
for (int i = 0; i <n ; i++) {
LinkList p;
p=(LinkList)malloc(sizeof(LNode));
scanf((const char *) p->data);
p->next=NULL;
r->next=p;
r=p;
}
}
算法时间复杂度是O(n)
标签:链表,结点,单链,int,next,LinkList From: https://www.cnblogs.com/yuanyu610/p/17076740.html