静态链表C/C++
什么是静态链表
与常见的数据结构的链表不同,想想常见的链表,每次新增数据都要重新开辟内存,这对有时间限制的算法程序来说每次插入新的数据就malloc是绝对会TLE的(除非从一开始就新开辟连续的堆空间当然这种情况下就不是动态链表了).
所谓静态链表,指的是:
静态链表是一种使用数组来实现链表的数据结构。它是在数组的基础上,通过将每个节点中的指针指向它在数组中的位置来表示链表中的连接关系。通常情况下,静态链表的数组大小需要事先确定,并且不能随意修改,因此其空间利用率较低,但在某些特定场景下,如内存受限或者需要频繁的插入和删除操作时,静态链表可以发挥比较好的优势。
特点
- 链表的长度固定.
- 每次插入和删除只改变指针位置.
- 若是只对第K个插入的数做操作,时间复杂度可以达到O(1)
- 它的实现在空间存储上可以是不连续的,但逻辑上的连续的,通过
ne[x]
得到下一个值.正因为它的这种不连续性,在插入数据时,x后继节点应该是qs[ne[x]]
而不是qs[x+1]
.
对第K个数的插入模板
对第K个插入的数的增,删的时间复杂度为O(1)
来源于acwing
https://www.acwing.com/blog/content/404/
// head存储链表头,e[]存储节点的值,ne[]存储节点的next指针,idx表示当前用到了哪个节点
int head, e[N], ne[N], idx;
// 初始化
void init()
{
head = -1;
idx = 0;
}
// 在链表头插入一个数a
void insert(int a)
{
e[idx] = a, ne[idx] = head, head = idx ++ ;
}
// 将头结点删除,需要保证头结点存在
void remove()
{
head = ne[head];
}
静态链表实现对第K个位置的增删查改(数据结构书上的朴素要求)
思想
通过朴素的暴力做法找到第K-1个位置,然后更改
ne[]
数组的下标值.
给出不带头节点的代码(第一个节点的操作需要判断,其他节点操作相同)
const int N = 100010;
int qs[N], ne[N];
int idx, head; //idx 当前可用的点
void init() {
idx = 0;
head = -1;
}
void headInsert(int x) //头节点插入
{
qs[idx] = x;
ne[idx] = head;
head = idx;
idx++;
}
int findKnum(int k) //查找第K个位置的数
{
int temp = head;
k = k - 1;
while (temp != -1 && k--)
{
temp = ne[temp];
}
if (temp == -1)return -1;
return qs[temp];
}
int addinKpoi(int k, int x) //在第K个位置新增元素
{
int temp = head;
k = k - 2;
qs[idx] = x;
while (temp != -1 && k--)
{
temp = ne[temp];
if (temp == -1)return -1;
}
ne[idx] = ne[temp];
ne[temp] = idx;
idx++;
return 0;
}
int delinKpoi(int k) //在第K个位置删除元素
{
int temp = head;
k = k - 2;
//找到第K-1个元素
while (temp != -1 && k--)
{
temp = ne[temp];
if (temp == -1)return -1;
}
ne[temp] = ne[ne[temp]];
}
void show()
{
int t = head;
while (t != -1)
{
cout << qs[t] << " ";
t = ne[t];
}
cout << endl;
}
int main()
{
init();
int op = 0;
do
{
cin >> op;
switch (op)
{
case 1: {
int x;
cout << "头节点插入" << endl;
cin >> x;
headInsert(x);
break;
}
case 2:
{
int x;
cout << "查询第K的位置的元素" << endl;
cin >> x;
int ret= findKnum(x);
if (ret != -1) cout << "第K个位置的数为:" << ret << endl;
break;
}
case 3:
{
int x, k;
cout << "在第K个位置新增元素" << endl;
cin >> k >> x;
if (k == 1)
{
headInsert(x);
cout << "插入元素成功" << endl;
}
else {
int ret = addinKpoi(k, x);
if (ret != -1) cout << "插入元素成功" << endl;
}
break;
}
case 4:
{
cout << "删除第K个位置的元素" << endl;
int k = 0;
cin >> k;
if (k == 1)
{
head = ne[head];
cout << "删除元素成功" << endl;
}
int ret =delinKpoi(k);
if (ret != -1)cout << "删除元素成功" << endl;
}
break;
case 7:
{
cout << "打印数据" << endl;
show();
break;
}
case 0:
cout << "退出程序" << endl;
break;
default:
cout << "重新输入" << endl;
}
} while (op!=0);
}
给出带头结点的代码( 头指针->头节点 ->第一个节点->第二个节点.所有节点的操作都相同)
const int N = 100010;
int qs[N], ne[N];
int idx, head; //idx 当前可用的点 head头指针指向头节点
void init() {
idx = 1; //带一个空的头节点 可用节点从1开始
head = 0;
ne[head] = -1;
}
void headInsert(int x) //头节点后插入 头指针->头节点 ->第一个节点->第二个节点
{
qs[idx] = x;
ne[idx] = ne[head];
ne[head] = idx;
idx++;
}
int findKnum(int k) //查找第K个位置的数
{
int temp = head;
while (temp != -1 && k--)
{
temp = ne[temp];
}
if (temp == -1)return -1;
return qs[temp];
}
int addinKpoi(int k, int x) //在第K个位置新增元素
{
int temp = head;
k = k - 1;
qs[idx] = x;
while (temp != -1 && k--)
{
temp = ne[temp];
if (temp == -1)return -1;
}
ne[idx] = ne[temp];
ne[temp] = idx;
idx++;
return 0;
}
int delinKpoi(int k) //在第K个位置删除元素
{
int temp = head;
k = k - 1;
//找到第K-1个元素
while (temp != -1 && k--)
{
temp = ne[temp];
if (temp == -1)return -1;
}
ne[temp] = ne[ne[temp]];
}
void show()
{
int t = ne[head]; //越过第一个头节点
while (t != -1)
{
cout << qs[t] << " ";
t = ne[t];
}
cout << endl;
}
int main()
{
init();
int op = 0;
do
{
cin >> op;
switch (op)
{
case 1: {
int x;
cout << "头节点插入" << endl;
cin >> x;
headInsert(x);
break;
}
case 2:
{
int x;
cout << "查询第K的位置的元素" << endl;
cin >> x;
int ret= findKnum(x);
if (ret != -1) cout << "第K个位置的数为:" << ret << endl;
break;
}
case 3:
{
int x, k;
cout << "在第K个位置新增元素" << endl;
cin >> k >> x;
int ret = addinKpoi(k, x);
if (ret != -1) cout << "插入元素成功" << endl;
break;
}
case 4:
{
cout << "删除第K个位置的元素" << endl;
int k = 0;
cin >> k;
int ret =delinKpoi(k);
if (ret != -1)cout << "删除元素成功" << endl;
}
break;
case 7:
{
cout << "打印数据" << endl;
show();
break;
}
case 0:
cout << "退出程序" << endl;
break;
default:
cout << "重新输入" << endl;
}
} while (op!=0);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?