1. “链表”表明这种数据结构是一种链式存储结构,它不同于线性表的顺序存储结构。链表的相邻元素在物理内存中不连续,所以这种结构可以充分利用一些系统的内存碎片来完成一些事务,即如果采用链表结构有时可以解决当连续内存分配不足时的问题。链表支持插入和删除这两种操作,并且删除/插入链表头部/尾部结点的时间复杂度通常都是常数级别的,链表的不足在于不支持高效的random access(随机访问)。常用于组织删除、检索较少,而添加、遍历较多的数据。
2. 链表和数组的区别:
(1)数组在内存中是逐个存放的,而链表的相邻元素在物理内存中不连续,呈现一种随机的状态;
(2)数组一旦显式的被申明后,其大小就固定了,不能动态进行扩充,而链表则可以;
(3)链表灵活,但是空间和时间额外耗费较大;数组大小固定,元素位置固定,但是操作不灵活,且容易浪费空间,但是时间耗费较小。双向链表比单向的更灵活,但是空间耗费也更大。
(4)从内存存储来看,(静态)数组从栈中分配空间,链表从堆中分配空间, 自由度大但是申请管理比较麻烦
3. 删除结点:
当需要删除一个节点p时,只需要将p的前一个节点的next赋为p->next,但是由于是单向的,只知道p,无法知道p前一个节点,所以需要转换思路。将p下一个的节点覆盖到p节点即可,这样就等效于将p删除了。
void deleteNode(Node*p){
p->value = p->next->value;
p->next =p->next->next;
}
4. 链表逆置:
包括head一共要维护3个指针, p是原链表中head的下一个,temp是原链表中head的上一个。
5. 链表中间结点(不知链表长度):
用快慢指针,快的移动2个位置,慢的移动1个位置,快的到最后一个结点,慢的就到中间
6. 找倒数第k个结点(不知链表长度):
用slow和fast指针标记,fast指针事先走k步,然后slow和fast同时走,当fast到达末节点时,slow在fast的前k个节点,即为倒数第k个节点。
7. 反向遍历链表:
8. 链表排序:
第一种方法:转为数组,用sort后再赋值给链表结点
第二种方法:借助multimap的自动排序功能
第三种方法:归并排序
Merge的非递归实现:
9. 链表相交问题:
方法一:如果两个链表相交,其形状必为y形,而不可以能为x形,即两条链表必有相同的尾节点。首先,计算得到两个链表的长度:m,n,求得两个链表长度之差distance=|m-n|,让较长得那个链表事先走distance步,这样,若是链表相交得话,二者指针必相撞,相撞点即为相交点。
方法二:同时走,走完自己的走另一条,没有交点则都会走m+n,若有交点,则会在交点处相遇。
10. 链表环问题: