单链表的基本操作
1、单链表的初始化
构造一个空的单链表(带头节点的单链表)
头节点的指针域为空
算法步骤:
(1)生成新结点作头节点,用头指针L指向头节点
(2)将头节点的指针域置空
Status InitList(LinkList &L){ //L是一个指向结点的指针,头节点分配好空间后,L就有值了 L头指针
L = new LNode; //或L=(LinkList)malloc(sizeof(LNode)); 找到头节点空间,将头节点的地址赋给L
L->next = NULL; //指针变量操作成员->(L是头节点的指针)
return OK;
}
2、判空
空表:链表中无元素,称为空链表(头指针和头结点仍然在)
分析:判断头节点的指针域是否为空
int ListEmpty(LinkList L){ //若L为空表,则返回1,否则返回0
if(L->next) //有内容,非空 L头指针
return 0;
else //无内容,空
return 1;
}
3、销毁
分析:从头指针开始,包括头结点,依次释放所有结点
若直接删掉p,L就没了,找找不到下一个地址了
L = L->next; L指向下一个结点
delete p; 或 free§;
Status DestroyList_L(LinkList &L){
Lnode *p; //或LinkList p;
while(L){ //L非空时执行
p = L;
L = L->next;
delete p;
}
return OK;
}
4、清空
链表仍存在,但链表中无元素,成为空链表(头指针和头结点仍然在)
思路:依次释放所有结点,并将头结点指针域设置为空
Status ClearList(LinkList &L){ //将L重置为空表
Lnode *p,*q; //或LinKList p,q;
p = L->next;
while(p){ //没到表尾 p有内容,执行;p没有内容(空),不执行
q = p->next;
delete p;
p = q;
}
L->next = NULL; //头结点指针域置为空
return OK;
}
5、求表长
思路:从首元结点开始,依次计数所有结点
int ListLength_L(LinkList L){ //返回L中数据元素个数
Lnode *p;
p = L->next; //p指向第一个结点
i = 0;
while(p){ //遍历单链表,统计结点数
i++;
p = p->next;
}
return i;
}
链表代码总结
类型定义:
typedef struct Lnode{
ElemType date;
struct Lnode *next;
}Lnode, *LinkList;
变量定义:
LinkList L; //定义链表L
Lnode *p,*s; //定义结点指针p
重要操作:
p = L; //p指向头结点
s = L->next; //s指向首元结点
p = p->next; //p指向下一节点
6、取值
取单链表中第 i 个元素的内容 例如:i = 3查找第3个元素√ i=0,-1 ╳ i = 15 ╳
(从链表的头指针出发,顺着next逐个结点往下搜索,直至搜索到第 i 个结点为止)
分析:
1.从首元结点开始顺链扫描 L = L->next
2.j做计数器,j初值为1
3.当p指向扫描到下一节点时,计数器 j 加1
4.当 j == i 时,p所指向的结点就是要找的第i个结点
Status GetElem_L(LinkList L, int i, ElemType &e){ //获取线性表中第i个数据元素,用e返回
p = L->next;//??
j = 1;
while(p && j<i){
p = p->next;
j++;
}
if(!p || j>i) return ERROR;//当第i个元素不存在时、i=0/-1时
e = p->data;
return OK;
}
7、按值查找
返回地址:
Lnode *LocateElem_L(LinkList L, ElemType e){
p = L->next;
while(p && p->data!=e)
p = p->next;
return p; //找到返回值为e的数据元素的地址,查找失败p为空 返回NULL
}
返回位置序号:
int LocateElem_L(LinkList L, ElemType e){
p = L->next;
j = 1;
while(p && p->data!=e){
p = p->next;
j++;
}
if(p) return j;//查找成功,返回j序号
else return 0;//查找失败返回0
}
时间复杂度:O(n) 1+…+n
8、插入
在第 i 个结点前插入值为e的新结点
Status Listlnsert_L(LinkList &L, int i, ElemType e){ //在L中第i个元素之前插入数据元素e
p = L; j = 0;
while(p && j<i-1){p = p->next; j++;} //寻找第i-1个结点,p指向i-1结点
if(!p || j>i-1) return ERROR; //i大于表长+1或者i=0、-1... 插入位置非法
s = new Lnode; s->data = e; //生成新结点s,将结点s的数据域置为e
s->next = p->next;
p->next = s; //将结点s插入L中
return OK;
}
9、删除
删除第 i 个结点
Status ListDelete_L(LinkList &L, int i, ElemType &e){ //用e返回删去的第i个值
p = L;
j = 0;
Lnode *q;
while(p->next && j<i-1){ //寻找第i个结点,并令p指向其前驱
p = p->next;
j++;
}
if(!(p->next) || j>i-1) return ERROR; //删除位置不合理
q = p->next; //临时保存被删除节点的地址以备释放
p->next = p->next->next;//或p->next = q->next;改变删除结点前驱结点的指针域
e = q->data; //保存删除结点的数据域
delete q; //释放删除结点的空间
return OK;
}
重要步骤: p->next = p->next->next;
p->next = q->next;
时间复杂度:
10、单链表的建立
头插法
头插法:元素插入在链表头部,也叫前插法
①生成头结点L,并将头结点的指针域置空
L = new LNode;
(C++) L-next = NULL;
L=(LinkList)malloc(sizeof(LNode));
(C语言) 分配结点大小的一块空间,将它转成指向这种结点的指针类型