线性表的链式存储
顺序表的插入、删除操作都需要移动大量的元素,因此引入了线性表的链式存储。它不要求逻辑上相邻的两个元素在物理位置上也相邻,因此,插入、删除操作只需要修改指针。
1、单链表单个节点
data | next |
---|---|
data为数据域,存放数据元素 | next为指针域,存放后继节点的地址 |
节点类型描述如下
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode, *LinkList;//这个节点的名字不仅叫做LNode,也叫做*LinkList。指针也可以表示单链表
通常用头指针标识一个单链表,如单链表L,头指针为NULL时是空表。
单链表是非随机存取的数据结构,在查找特定节点时,必须从头节点开始遍历。
2、单链表的基本操作
头插法建立单链表
LinkList List_HeadInseart(LinkList &L){
LNode *s;int x;//新节点记作s
L=(LinkList)malloc(sizeof(LNode));//创建头节点
L->next=NULL;//初始为空链表,即指针指向NULL
scanf("%d",&x);//输入x的值
while(x!=9999){//若输入X值为9999则结束
s=(LNode*)malloc(sizeof(LNode));//创建新节点
s->data=x;//这个节点的数据域=x
s->next=L->next;//倒腾指针指向
L->next=s;//倒腾指针指向
scanf("%d",&x);
}
return L;
}
尾插法建立单链表
LinkList List_TailInsert(LinkList &L){
int x;
L=(LinkList)malloc(sizeof(LNode));
LNode *s,*r=L;//r为表尾指针,指向表尾
scanf("%d",&x);
while(x!=9999){
s=(LNode *)malloc(sizeof(LNode));
s->data=x;
r->next=s;
r=s;//r指向新的表尾节点
scanf("%d",x);
}
r->next=NULL;//尾节点指针置空
return L;
}
按序号查找
LNode *GetElem(LinkList L,int i){
//取出单链表L(带头节点)中第i个位置的指针
int j=1;//标号
LNode *p=L->next;//头节点指针副给p
if(i==0)
return L;//若i为0,则返回头节点
if(i<1)
return NULL;//若i无效,返回NULL
while(p&&j<i){
p=p->next;//从第一个节点开始查找
j++;
}
return p;
}
按值查找
LNode *LocateElem(LinkList L,ElemType e){//要查找的值为e
LNode *p=L->next;
while(p!=NULL&&p->data!=e){
p=p->next;
}
return p;
}
交换数据是个可以免去遍历的好方法
插入节点
p=GetElem(L,i-1);//必须先按序号找到第i-1个节点
s->next=p->next;
p->next=s;
删除节点
p=GetElem(L,i-1);
q=p->next;
p->next=q->next;
free(q);
单链表在节点位置已知的情况下,进行插入删除操作,时间复杂度为O(1);位置情况下为O(n)