单链表引言
✈️ 定义:
单链表是一种由多个节点组成的线性结构,每个节点包含两个部分:
数据域(data):存储具体的数据元素;
指针域(next):存储指向下一个节点的指针。
整个链表通过首节点开始,逐个指向后继节点,最后一个节点的
next
指针为空(NULL),表示链表结束。
操作 | 描述 | 时间复杂度 |
---|---|---|
初始化 | 创建一个空链表(通常建立头结点) | O(1) |
插入 | 在指定位置插入新节点 | O(n) |
删除 | 删除指定位置的节点 | O(n) |
查找 | 查找第一个匹配值的节点 | O(n) |
遍历 | 从头到尾依次访问每个节点 | O(n) |
适用场景
1)元素数量不固定、需频繁插入/删除的场景;
2)空间受限,无法一次性分配大块内存的情况;
3)操作顺序与访问方向固定(从头到尾)的应用。
⏰优点:
插入、删除操作灵活,只需改变指针,不需要移动元素;
空间利用率高,不需要预分配连续内存;
易于实现动态扩展。
⌛️缺点:
不能随机访问,访问某个位置的元素必须从头遍历;
指针域额外占用存储空间;
操作复杂性较高,容易出错(尤其是指针操作)。
1.单链表的创建
【问题描述】随机输入一些数据,请采用尾插法创建一个带头结点的单链表,将数据存入,然后顺序遍历该单链表并输出数据,以查看是否创建成功。
【样例输入】6 3 5 2 9 0
【样例输出】6 3 5 2 9
备注:0代表输入结束
#include<iostream>
#include<stdlib.h>
#define Size 10
using namespace std;
typedef struct LNode
{
int data;
struct LNode *next;
}LNode,*LinkList;
int add(LinkList &L)
{
L=(LinkList)malloc(sizeof(LNode));
LNode *s,*r;
r=L;
int flag=0;
while(1)
{
int x;
cin>>x;
if(x==0)
break;
s=(LinkList)malloc(sizeof(LNode));
s->data=x;
r->next=s;
r=s;
flag++;
}
return flag;
}
void shuchu(LinkList &L,int i)
{
LNode *p;
int j=0;
p=L;
while(p!=NULL&&j<i)
{
cout<<p->next->data<<' ';
p=p->next;
j++;
}
}
int main()
{
LinkList L;
int i=add(L);
shuchu(L,i);
return 0;
}
2.单链表的变化
【问题描述】设线性表L={a1,a2,a3,...,an-2,an-1,an}采用带头结点的单链表保存,请设计一个空间复杂度为O(1)且时间上尽可能高效的算法,重新排列L中的各结点,得到线性表L'={a1,an,a2,an-1,a3,an-2,...)
【样例输入】1 2 3 4 5 0
【样例输出】1 5 2 4
#include<iostream>
#include<stdlib.h>
using namespace std;
typedef struct LNode
{
int data;
struct LNode *next,*prior;
}LNode,*LinkList;
int creat(LinkList &L)
{
L=(LNode*)malloc(sizeof(LNode));
L->next=L;
L->prior=L;
LNode *r,*s;
r=L;
int flag=0;
while(1)
{
int x;
cin>>x;
if(x==0)
break;
s=(LNode*)malloc(sizeof(LNode));
s->data=x;
r->next=s;
s->prior=r;
r=s;
flag++;
}
r->next=L;
L->prior=r;
return flag;
}
void pailie(LinkList &L,int flag)
{
LNode *r,*p;
p=L->next;
r=L;
while(r->next!=L)
r=r->next;
for(int i=0;i<flag/2;i++)
{
cout<<p->data<<' '<<r->data<<' ';
p=p->next;
r=r->prior;
}
if(flag%2==1)
cout<<p->data;
}
int main()
{
LinkList L;
int flag=creat(L);
pailie(L,flag);
return 0;
}
3.等值字串
【问题描述】如果字符串的一个子串(其长度大于1)的各个字符均相同,则称之为等值子串。试设计一算法,求出串S中一个长度最大的等值子串;如果串S 中不存在等值子串,则输出信息no
【输入形式】输入一个字符串,并以!结束
【输出形式】输出第一个出现的最长字符串,如果没有输出no
【样例输入】aabc123abc123cc!
【样例输出】aa
#include<iostream>
#include<stdlib.h>
using namespace std;
typedef struct LNode
{
char data;
struct LNode *next;
}LNode,*LinkList;
void init(LinkList &L)
{
L=(LNode *)malloc(sizeof(LNode));
L->next=NULL;
}
int input(LinkList &L)
{
char x;
LNode *s,*r;
r=L;
int flag=0;
while(1)
{
cin>>x;
if(x=='!')
break;
s=(LNode *)malloc(sizeof(LNode));
s->data=x;
r->next=s;
r=s;
flag++;
}
return flag;
}
void found(LinkList &L,int flag)
{
LNode *r,*s;
r=L->next;
int n=flag;
int a[10000];
for(int i=0;i<n;i++)
{
s=r->next;
int x=1;
for(int j=0;j<n-i-1;j++)
{
if(r->data==s->data)
{
x++;
s=s->next;
}
else
{
break;
}
}
a[i]=x;
r=r->next;
}
int max=a[0];
int y=0;
for(int i=0;i<n;i++)
{
if(a[i]>max)
{
max=a[i];
y=i;
}
}
r=L;
for(int i=0;i<y+1;i++)
{
r=r->next;
}
if(max!=1)
{
for(int i=0;i<max;i++)
cout<<r->data;
}
else
cout<<"no";
}
int main()
{
LinkList L;
init(L);
int flag=input(L);
found(L,flag);
return 0;
}
4.单链表结点的删除
bool delete(LNode *p) //删除指定结点p
{
if(p==NULL)
return false;
LNode *q=p->next; //q指向*p的后继结点
p->data=p->next->data; //和后继结点交换数据域
p->next=q->next; //将*q结点从链中“断开”
free(q);
return true;
}
5.单链表的按值查找
LNode *locate(LinkList L,int e) //寻找数据为e的结点
{
LNode *p=L->next; //从第一个结点开始查找数据为e的结点
while(p!=NULL&&p->data!=e)
p=p->next;
return p; //找到后返回该结点的指针,否则返回NULL;
}
6.头插法建立单链表
LinKList create(LinkList &L) //头插法本质——元素逆置
{
LNode *s;
int x;
L=(LinkList)malloc(sizeof(LNode)); //创建头结点
L->next=NULL;
while(1)
{
cin>>x;
if(x==0)
break; //输入0表示结束
s=(LNode*)malloc(sizeof(LNode));
s->data=x;
s->next=L->next;
L->next=s; //L为头指针
}
return L;
}
⛳ 你好哇,我是小瑾,是一名在校大学生~
⛵目前博文包含课程设计、csp刷题、算法介绍、当下科技热点分享、网站软件推荐等等哦,还会更新学习到的深度学习、视觉等方面的知识~(如果发现你和博主是一个学校,那么仔细找找,也许会找到许多你需要的东西✌️)
⛄一个希望与大家携手共进的小博主
✍关注我,让你的代码之旅不再孤独!