链表


单链表是一种数据结构,包含了一个节点序列,每个节点包含一个对象和链表中下一个节点的引用。
第一个节点被称为head,最后一个节点被称为tail,tail的下一个节点是null。

在双向链表中,每个节点都与它的前驱相连,相似地,一个哨兵节点或者一个自循环可以用来替代null。

链表原型代码:
template<typename T>
struct ListNode {
T data;
shared_ptr<ListNode<T>> next;
};

链表问题常常会有O(n)的空间复杂度的简单粗暴的解法,但是更精妙的解法就是运用已有的链表节点减小空间复杂度到O(1)。
通常来讲,链表的问题在概念上是很简单的,更多的是如何写出干净的代码,而不是如何去设计算法。
考虑用一个伪头指针(有时也叫哨兵)来避免对空链表的检验。这可以简化代码,还可以减少bug发生的可能性。
对于头指针和尾指针,很容易忘记更新next(和双向链表的previous)。
使用两个迭代器,会对单链表的算法操作非常有益,一个在另外一个前面,或者一个比另一个前进的更快。
很多与链表相关的面试问题都会要求我们自己写一个链表的类。
当我们操作C++自带的链表时,我们需要知道list和forward_list这两个类。
list类是一个双向链表,forward_list是一个单向链表。

常用双向链表list的函数:
list插入与删除是push_front(42)(或者emplace_front(42)), pop_front(), push_back()(或者emplace_back(), 和pop_back())。
splice(L1.end(), L2), reverse(), 和sort()函数和forward_list中的函数是类似的。

常用单向链表forward_list的函数:
插入与删除是push_front(42)(或者emplace_front(42)), pop_front(), insert_after(L.end(), 42)(或者emplace_after(L.end(), 42), 和erase_after(A.begin()))。
把元素从一个链表转移到另外一个链表用splice_after(L1.end(), L2)。
翻转元素的顺序用reverse()。
用sort()去给链表排序,会给自己省去很多痛苦。

链表相关问题:

1. 融合两个有序链表:
给定两个有序链表,返回它们的融合。唯一可以改变的是节点的next域。
提示:可以用两个索引来融合两个有序数组。对于链表来说,要考虑什么时候一个迭代器到达尾部。

2. 反转一个单子链表:
给定一个单链表L,和两个整数s和f作为实参,反转从第s个节点到第f个节点间(包括s和f)的节点顺序。数字从1开始,head节点就是第一个节点。不要开辟额外的节点。
提示:关注需要更新的后继域。

3. 测试循环性:
给定一个单链表的头结点,如果有循环则返回循环的开始节点,如果没有循环返回null。
提示:考虑运用两个迭代器,一个快一个慢。我们提前不知道链表的长度。

4. 测试重叠的链表(链表没有循环):
给定两个没有循环的单链表,确定两个链表是否有公共节点。
提示:先处理简单的情况。

5. 测试重叠的链表(链表可能有循环):
与问题4类似,两个链表中可能一个或者全部有循环。如果有这样重叠的节点存在,返回遍历节点时的第一个。
提示:根据情况分析。两个链表都有循环会怎么样?如果它们结束于一个公共的循环会怎么样?如果一个有循环另一个没有会怎么样?

6. 从单链表中删除一个节点:
从一个单链表中删除一个节点。输入的节点保证不是tail节点。
提示:不去删除这个节点,你能够通过删除它的后继,还能够实现功能吗?

7. 从链表中删除倒数第k个元素:
给定一个单链表和一个整数k,从链表中删除倒数第k个元素。
提示:如果你知道链表的长度,你能用两个迭代器找到倒数第k个节点吗。

8. 从有序链表中删除重复元素:
给定一个有序的整数链表,从中删除重复元素。之后链表应该是有序的。
提示:专注于需要更新的后继域。

9. 对单链表进行循环右移:
给定一个单链表和一个非负整数k,返回链表循环右移k位后的链表。
提示:这个问题和旋转数组有什么区别?

10. 实现奇偶融合:
提示:用临时的额外存储。

11. 测试一个单链表是否是回文的:
提示:如果能向前和向后同时遍历链表就会变得简单了。

12. 实现链表的pivoting:
给定一个单链表和一个整数k,对于k对立案表进行pivoting。k前面和后面的节点相对顺序不能变。key等于k的也是一样。
提示:独立地构建三个区域。

13. 基于链表的整数相加:
给定两个数字位单链表,返回它们代表的整数的和对应的链表。最低位出现在前面。
提示:首先先解决两个对应的数字位的和不会超过9的问题。


整数链表排序的c源代码 说明:试按以下给出的排序算法为整数链表编写一个排序函数: 该算法是按表元键值的各位值进行排序。 设有一个整数链表,其中表元的键值为不超过三位数的整数,不妨设键值形式ABC。其中A表示键值的百位数,B为十位数,C为个位数。首先按键值中的个位值C对链表作分拆和链接,先把链表分拆成10个队列链表,然后以C的值从0至9的顺序把分拆后的十个队列链表收集成一个链表。接着依次对键值中的B和A进行同样的分拆和链接操作,则最后收集起来的链表是按键值从小到大排序链接的。如有一个链表按它们的键值其表元的链接顺序依次为: 153 678 56 288 457 653 721 876 433 254 按它们的键值的个位分拆,得到十个队列链表,列出它们的键值顺序有: 0: 空链表 1: 721 2: 空链表 3: 153 653 433 4: 254 5: 空链表 6: 56 876 7: 457 8: 678 288 9: 空链表 顺序将它们收集一起后,链表的键值顺序有: 721 153 653 433 254 56 876 457 678 288 再按它们键值的十位分拆,得到十个队列链表,列出它们的键值顺序有: 略。 顺序将它们收集在一起后,链表的键值顺序有: 略。 再按它们键值的百位分拆,得到十个队列链表,列出它们的键值顺序有: 略。 顺序将它们收集一起后,链表的键值顺序有: 56 153 254 288 433 457 653 678 721 876 要求: 1、 试用C语言编程实现以上功能 2、 10个数字随机生成 3、 程序可读性好 ps:头文件#include 中包含 #include #include #include #include
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值