C++链表和list

链表:用链式存储实现的线性表。

链式存储:在内存中,不仅存储当前元素信息,还存储前继或后继节点的地址。通过地址实现元素与元素之间的关系。

单链表:动态实现:通过new动态的申请链表中的节点,通过delete来释放节点。静态实现:两个足够大的数组,一个数组elem存储数据,充当数据域,另一个数组next 存储下一个元素的下标,充当指针域。

模板:int eN,neN,h,id;

int main()

{

return 0;

}

链表的头插操作:id++,标记新节点的位置,同时存储新节点的值:eid = x;

再修改新节点的指针域,让其指向哨兵位的下一个位置:neid = neh;

最后修改哨兵位的指针域,让其指向新节点:neh = id;

头插

void push_front(int x)

{

id++;

aid = x;

//先让新节点指向头节点的下一个位置

//然后让头节点指向新来的节点

neid = neh;

neh = id;

}

遍历链表

void push_front(int x)

{

for(int i = neh; i ; i = nei)

{

//ei 就是当前元素

cout << ei << " ";

}

cout << endl;

}

按值查找:

方法一:遍历整个链表,一个一个对比

int find(int x)

{

for(int i = 1; i <= 5; i++)

{

if(ei = x)

return i;

}

cout << find(1) << endl;

cout << find(2) << endl;

cout << find(3) << endl;

return 0;

}

方法二:重新创建一个数组mp,标记,每一个元素存储的下标位置,此时mpi表示:i这个元素,存储的位置。缺点:就是不能有重复的数

void push_front(int x)

{

id++;

eid = x;

mpx = id; 标记x存储的位置

//先让新节点指向头节点的下一个位置

//然后让头节点指向新来的节点

neid = neh;

neh = id;

}

在任意位置插入元素:在任意位置为p的元素后面,插入新的元素x

先id++ ,标记新节点的位置,同时存储新节点的值:eid = x

然后 修改新节点的指针域,让其指向p的下一个位置:neid = nep

最后 修改p位置的指针域,让其指向新节点:nep = id

void insert(int p,int x)

{

id++;

eid = x;

mpx = id;

nex = nep;

nep = id;

}

int main()

{

insert(i,10);

insert(2,100);

return 0;

}

删除任意位置之后的元素:删除存储位置为p后面的元素

方法:直接让p指向下一个元素的下一个元素即可 nep = nene\[p]; 此方法的缺点是:删除链表中的最后一个元素后面的元素时:nep = nene\[p] 会找到哨兵位的下一个结点,此时再去赋值就会让链表成环,破坏了实际的结构。

void erease(int p)

{

if(nep) 当p不是最后一个元素的时候

{

mpe\[ne\[p]] = 0;

nep = nene\[p];

}

}

遗留问题:单链表为什莫不实现尾插、尾删、删除任意位置等操作:能实现,但是没有必要,因为时间复杂度较高。

双向链表:静态实现:创建三个做够大的数组:第一个数组存储数据,第2个数组存储前一个元素的存储下标,第三个元素存储下一个元素的存储下标

const int N = 1e5 + 10;

int eN,neN,preN,id,h;

int mian()

{

return 0;

}

头插:将x插入哨兵位与y的中间,先修改新节点x的左右指针,然后修改结点y的左指针,最后修改哨兵位的右指针

先将id++,标记新节点存储的位置,把新的元素存储下来:eid = x;

修改新节点的前驱指针,让其指向哨兵位: preid = h;

修改新节点的后继指针,让其指向哨兵位的下一个位置: neid = neh;

修改y结点的前驱指针,让其指向新的结点: prene\[h] = id;

修改哨兵位的后继指针,让其指向新的结点: neh = id;

遍历链表:直接无视prev数组,与单链表的遍历方式一致

void print()

{

for(int i = neh;i;i = nei)

{

cout << ei << " ";

}

cout << endl << endl;

}

int main()

{

for(int i = 1; i <= 5; i++)

{

push_front(i);

print();

}

return 0;

}

按值查找:直接使用mp数组优化了

int find(int x)

{

return mpx;

}

int main()

{

for(int i = 1;i <= 5; i++)

{

push_front(i);

print();

}

cout << find(3) << endl;

cout << fint(5) << endl;

return 0;

}

在任意位置之后插入元素:在存储位置为p的元素后面,插入新的元素,操作与头插操作类似,注意最后修改p的后继指针即可

先id++,标记新结点存储的位置,把新的元素存储下来:eid = x;

修改新结点的前驱指针,让其指向p位置:preid = p;

修改新结点的后继指针,让其指向p位置的下一个位置:neid = nep;

修改p的下一位置的前驱指针,让其指向新的结点:prene\[p] = id;

修改p的后继指针,让其指向新的结点:nep = id;

在任意位置之前插入元素:在存储位置为p的元素前面,插入新的元素x。注意要最后修改p的前驱指针

id++,标记新结点存储的位置,把新的元素存储下来:eid = x;

修改新结点的前驱指针,让其指向p的前一个位置:preid = prep

修改新结点的后继指针,让其指向p位置:neid = p;

修改p前一个位置的后继指针,让其指向新的结点:nepre\[p] = id;

修改p的前驱指针,让其指向新的结点:prep = id;

删除任意位置的元素:删除存储位置为p的元素

让p的前驱结点的后继指针指向p的后继结点:prepre\[p] = nep;

让p的后继结点的前驱指针指向p的前驱结点:prene\[p] = prep;

循环链表:就是单项链表的一种特殊情况

相关推荐
白杨尚青10 分钟前
C++进阶篇(六):map 和 set 的模拟实现——用红黑树封装 mymap/myset(迭代器 + operator[])
开发语言·c++·迭代器·stl·set·map·红黑树
kloc3 小时前
聊天室项目入口网关子服务的实现
linux·c++
csdn_aspnet6 小时前
C++ 3个有序点的方向(Orientation of 3 ordered points)
c++·算法
小七在进步7 小时前
string的使用(2)
c++
青少儿编程课堂8 小时前
蓝桥杯·全国青少年信息素养大赛·电子学会Python/C++考级:折半搜索优化子集枚举(Meet in the Middle)解析
c++·python·算法·bfs·信息学竞赛
wo_jack9 小时前
C++ 入门笔记(十七):list 入门 —— 为什么 list 不能 sort?
数据结构·c++·面试·stl·list
青少儿编程课堂11 小时前
蓝桥杯青少组图形化 + 全国青少年信息素养大赛 + 电子学会Scratch考级:校园连连看解析
c++·python·算法·bfs·信息学竞赛
草莓熊Lotso11 小时前
【C++ 基于微服务的即时通讯系统】文件存储子服务实战:UUID生成、文件IO封装与全接口单元测试
开发语言·网络·数据库·c++·微服务·架构·单元测试
David猪大卫1 天前
【C++修炼】map 和 set 的使用
c语言·开发语言·数据结构·c++·经验分享·笔记·学习
HPtiger1 天前
C++ 入门笔记:从 C 到 C++ 的核心过渡(命名空间、输入输出、缺省参数、重载、引用、内联)
c语言·c++·学习