链表知识点总结(二)双链表、循环链表的总结以及一些LeetCode的链表题目推荐

接上一篇 链表知识点总结(一) 这次讲讲单链表的扩展——双链表、循环链表,以及推荐一些我个人认为比较好的链表练习题LeetCode。

 

双链表的简单总结

双链表其实就是节点的定义里多了一个prev指针指向上一个节点,对于带头节点的双链表来说,头节点的prev指针是指向NULL的(与此对应的是尾结点的next指针指向NULL),对于双链表来说,增删改查的操作与单链表没什么不同,只是多一个prev指针需要修改,这里就不再一一列出各种实现了。

值得一提的是,对双链表来说,可以定义一个函数link(Node* l,Node * r),功能是连接节点l和节点r,代码实现:

inline void link(Node *l, Node *r)
{
	if (l)
		l->next = r;
	if (r)
		r->prev = l;
}

假如我们有这样一个链表  a->b->c ,我要在b的位置(也就是a的后面)插入元素newNode,如果我们使用link函数的话,我们就需要非常简洁地调用两次link函数:

link(newNode,a->next);//连接新结点和b
link(a,newNode);//连接a和新节点

对于上面两行代码,如果a是尾结点的话link也是不会出错的,因为link的实现里对l和r有判空的逻辑,所以不管l和r是否为NULL都不会出错。使用link函数分离逻辑,可以让代码的逻辑更加清晰,特别是在后面写循环双链表的时候,只需要按逻辑调用link函数就可以完成繁杂的连接操作。

 

循环链表的简单总结

循环链表就是尾结点不指向NULL,而是指向头节点的链表,循环链表可以用于解决一些带有“循环”概念的问题,如约瑟夫问题等。循环链表的各种操作的实现和单链表的实现差不多,只是要注意的是,对于带头节点的循环链表,遍历时应从第一个数据节点开始,以指针扫一圈后指向头节点为终止条件,以循环链表的遍历输出为例,其实现代码如下:

void print(Node* header)
    {
        Node *cur = header->next;//开始时指向第一个数据节点
        while (cur != header)//cur重新回到header时结束
        {
            cout << cur->data << " ";
            cur = cur->next;
        }
        cout << endl;
    }

循环双链表相比起简单的单链表来说,它可以以O(1)的时间复杂度得到某个节点的前一个节点(利用prev指针),而简单单链表的话需要O(n)的时间复杂度(重新从头遍历一次得到),除此之外,如果要在链表中寻找某个位置的节点的话,循环双链表可以根据索引离两端的远近来选择从头向尾遍历或者是从尾向头遍历,这样实际查找元素的时间复杂度就变成了O(n/2),比单链表只能从头遍历要好一些,但总归是O(n)。实际开发中要用链表的话,一般都会选择循环双链表来代替简单的单链表以提高效率。

 

 LeetCode上链表相关的题目推荐

我所推荐的题目都是中文LeetCode网站上的题目,网址:力扣,并且推荐的都是难度 简单-中等的练手题目,可以认为我推荐的都是有一定的思考量且需要一定的编码能力才能解决的题目,但不会太难,初学者也能做,我个人认为这类题目更多地是要去学习如何写出高效又简洁的代码解决问题,也就是略微偏重于编码能力的题目,毕竟是侧重链表知识点的题目。

 

2. 两数相加

这道是模拟加法计算的题,仔细阅读题目所给的链表顺序,先试着用自己的代码实现,然后着重练习如何将代码写到最简洁的形式。

 

147. 对链表进行插入排序

链表的插入排序问题。

 

237. 删除链表中的节点

简单题,但是需要拐点弯,需要抛弃定势思维才能想到解决办法。

 

141. 环形链表

判断链表有无环的模板题,比较经典。

 

21. 合并两个有序链表

链表的二路归并,较为简单,需要一定的编码能力。

 

206. 反转链表

反转链表的模板题,题目本身很简单,推荐尝试用递归来解决。

 

24. 两两交换链表中的节点

中等题,需要一定的编码能力。

 

876. 链表的中间结点

面试中的常见问题,快慢指针的经典问题。

 

以上题目就是我做过的比较经典的、同时又不会太难的题目,适合初学者练习,如果还想继续做题的话可以自行上LeetCode刷题,多刷题多总结,才能更快地提升自己的能力。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值