考研数据结构算法学习笔记整理 Day9-Day12 链表
前言
本文部分整理自up主 计算机考研大师兄,仅留作个人学习记录,侵删。
往期文章
目录
Day9 试编写从带头结点的单链表L中删除一个最小值结点的高效算法(假设最小值结点是唯一的)。
王道P47-4
void Del_min(LinkList &L){
LNode *pre = L, *p = L->next; //p为工作指针,pre指向p的前驱
LNode *minpre = pre, *minp = p; //标记最小值
while(p != NULL){ //循环找到最小值
if(p->data < minp->data){ //如果找到更小的值,赋值给minp和minpre
minp = p;
minpre = pre;
}
pre = p; //否则,继续向后扫描
p = p->next;
}
//删除最小值
minpre->next = minp->next;
free(minp);
return L;
}
Day10 请使用头插法建立单链表。
王道P29-2.3.2-1
void ListHeadInerst(LinkList &L){
LNode *s, int x; //s是新插入的结点指针,x是结点值
L = (LinkList)malloc(sizeof(LNode)); //申请头结点空间
L->next = NULL; //初始化链表
scanf("%d", x); //输入结点值
while(x != -1){ //当x输入为-1时跳出循环
s = (LNode *)malloc(sizeof(LNode)); //创建新结点
s->data = x;
s->next = L->next; //头插
L->next = s; //头插
}
return L;
}
Day11 请使用尾插法建立单链表。
王道P30-2.3.2-2
void ListTailInsert(SqList &L){
Lnode *s, *r; //s是新插入的结点指针,r是尾指针
int x;
L = (LinkList)malloc(sizeof(LNode)); //创建头结点
L->next = NULL; //初始化链表
r = L; //r始终指向尾结点
scanf("%d", x);
while(x != -1){ //当x输入为-1时跳出循环
s = (LNode*)malloc(sizeof(LNode)); //创建新结点
s->data = x;
r->next = s; //尾插
r = s; //尾插
}
r->next = NULL; //尾结点的后继置空
return L;
}
Day12 试编写算法将带头结点的链表就地逆置,所谓“就地”是指辅助空间的复杂度为O(1)。
王道P48-5
- 头插法(逆置)
void Reverse(LinkList &L){
LNode *p = L->next, *r; //r标记断点防止断链
L->next = NULL; //断开头结点
while(p != NULL){
r = p->next; //标记断点位置,防止断链
p->next = L->next; //头插
L->next = p; //头插
p = r; //恢复断点
}
return L;
}
时间复杂度:O(n)
空间复杂度:O(1)
- “原地掉头”
void Reverse(LinkList &L){
LNode *pre = L->next, *p = pre->next, *r = p->next;
while(r != NULL){ //当p没有后继时跳出循环
p->next = pre; //从头结点的后继开始,将p的后继指向p的前驱结点,即“原地掉头”
pre = p; //依次后移
p = r; //依次后移
r = r->next; //依次后移
}
L->next = p; //逆置结束后将头结点指到p现在的位置,此时p应该是最后一个结点
return L;
}
时间复杂度:O(n)
空间复杂度:O(1)