数据结构与算法之链表
Posted 乞力马扎罗的雪CYF
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构与算法之链表相关的知识,希望对你有一定的参考价值。
链表的分类:
(1)单链表
头插法:只需要维护一个头结点即可,常用来模拟堆栈;
尾插法:需要维护头结点和尾结点,常用来模拟队列。
(2)双向链表
双向遍历,可以用来保存网页的历史记录等;
(3)循环链表
经常出现在面试题中,判断链表是否有环。
链表的删除
方式一:维护两个指针,current(表示当前节点)和previous(表示当前节点的前一个节点)。当current遍历到要删除的元素时,执行previous->next = current->next,并删除current。在删除时,需要判断current是否等于head节点。
方式二:维护一个二级指针,Node ** current和一个临时变量entry。删除时只需要执行*current = entry -> next. 并删除entry即可,无需判断是否为head节点。
基于内存池的链表
传统链表的缺点:链表在插入过程中会调用系统函数分配内存,然后将该块内存链接到链表中。插入操作有三个缺点:
(1)进行频繁的系统调用,会浪费不少时间;
(2)在链表节点分配释放的过程中会产生很多内存碎片,不利于分配整块内存;
(3)可能会导致频繁的cache缺失;
解决方案:
构造一个内存池,每次插入都从内存池中获取一个节点,每次删除都将节点放回内存池。这样做的优点是不存在内存碎片,也不进行系统调用。
链表的反转(面试常考)
(1)思路一:在从前往后遍历的过程中进行反转。维护三个指针,分别指向当前节点以及当前节点的前后节点。
(2)思路二:将第三个节点到第N个节点,依次逐节点插入到第一个节点(head节点)之后,最后将第一个节点挪到新表的表尾。
(3)思路三:递归的处理head后面的节点,然后再修改head和head后面节点的指向。
倒序打印链表
(1)递归:倒序打印意味着先最后的元素,然后依次往前打印,可以用递归实现这个过程。递归的打印head后面所有的节点,然后打印head节点。
(2)栈模拟:递归使用系统栈(活动记录),我们可以用STL中的栈来模拟上述递归过程。首先顺序遍历一遍链表,将元素放入堆栈,然后依次出栈打印元素。
判断链表是否有环
(1)如何判断是否存在环?
解法:设置一对快慢指针,同时从链表的头开始往前遍历。慢指针一次前进一步,快指针一次前进两步,如果有环则两个指针会相遇。
(2)如何知道环的长度?
解法:记录下问题(1)的碰撞点,快慢指针再从该位置遍历一遍环。下次碰撞慢指针走过的距离就是环的长度。
(3)如何找出环的连接点在哪里?
解法:碰撞点到连接点的距离 = 头指针到连接点的距离,再次从两点遍历即可。
(4)带环链表的长度是多少?
解法:问题2+问题3.
间接寻址的基本概念
间接寻址简单描述就是二级指针的应用。二级指针有三个含义:指向指针的指针、一维数组、二维数组。间接寻址在此特指其一维数组的含义。
间接寻址是数组和链表的组合。既保留了数组的许多优点,又获得了链表的重要特色。首先,可以根据索引在O(1)的时间内访问每个元素。其次,可以采用二分在对数时间内对一个有序表进行搜索。最后,在诸如插入和删除操作期间不必对元素进行实际的移动。间接寻址使用指针数组来跟踪每一个元素,对元素本身如何分配不设限制(可离散可连续)。
间接寻址的应用
(1)内存池
自构建等块内存池,每一个指针分别指向每一块内存的首地址。内存池可以避免内存碎片和系统调用。
(2)散列链表
如果指针指向的元素包含next指针,则间接寻址变成了散列链表。
模拟指针的基本概念
模拟指针简单描述就是利用数组的下标当指针。模拟指针的最大用途是解决并查集问题。
(1)实现一:首先构造一个节点数组,节点包含两个域:data和link。link域指向数组中的其他节点。和间接寻址有相似之处。
(2)实现二:数组只包含link域,可以用来模拟树。
等价类的定义
定义:假定有一个具有n个元素的集合U,另有一个具有r个关系的集合R。如果(a,b)属于R,则元素a和b是等价的。等价类是指相互等价元素的最大集合。换句话说,将集合U根据关系进行划分,类内的元素等价,可以看做是一种聚类。
离线等价类:已知n和R,确定所有的等价类。
在线等价类:初始时有n个元素,每个元素都属于一个独立的等价类。然后不停的执行Find和Union操作向R中添加新关系。通常被称为并查集问题。
并查集的基本概念
并查集的操作:
(1)Find:查询元素a和b是否属于同一类;
(2)Union:合并元素a和b所在的类。
并查集的实现:
采用方式二的模拟指针。数组的下标即表示指针,指针的指向使并查集构成了一棵虚拟的森林。但是并查集不关注每棵树的形状以及相互指向关系,只关注最终的根节点以及该树的元素个数或者高度。
并查集的优化:
可以根据重量规则或者高度规则对并查集的操作进行优化。
以上是关于数据结构与算法之链表的主要内容,如果未能解决你的问题,请参考以下文章