【数据结构复习】链表相关

【数据结构复习】是学习、复习常用数据结构系列文章。数据结构与算法密不可分,是程序实现功能的重要组成部分。优秀的数据结构可以提高算法的时间及空间效率。反之,将增加算法复杂度,甚至妨碍程序的正确执行。

一、引言

链表是一种在存储空间上非连续的数据结构。每一个节点之间以指针连接,因此具有较大的灵活性。

二、基本构成与分类

1、基本构成
本节点的值(元素):
m_element
指向上节点的指针:
CNode* m_pPrev
指向下节点的指针:
CNode* m_pNext
首节点:整条链表的第一个节点。取得它以后即可以遍历整条链表。
firstNode
{
  m_element;
  m_pPrev = NULL; // 关键
  m_pNext;
}
尾节点:通常以空指针NULL结尾,既是一个重要的判定标准,也是自己创建链表时常常易忘的一项。
lastNode
{
  m_element;
  m_pPrev;
  m_pNext = NULL; // 关键
}
2、分类
双向链表:普通包含上述全部成员的链表。
template <typenema T>
class CNode
{
  T m_element;
  CNode* m_pPrev;
  CNode* m_pNext;
}

向后单向链表:每个节点只有指向下节点的指针。对于这类链表,首节点十分重要(因为无法回溯)。
向前单向链表:虽然出现得不多,但是难免有一些偏题怪题会提到。


三、基本操作
链表的基本操作实际上都指针操作,一定注意给涉及到的节点的“所有指针”安排好指向。常见错误是出现忘了赋值,仍然指向旧址,尾节点的下个指针不为NULL,头节点的上个指针不为NULL...
另一方面,链表的元素也可以操作,有时候链表结构无法更改时,通过元素互换达到目的(例如排序、无头节点时删除单向链表某节点)
1、插入


2、删除


四、双向链表问题收集(持续更新)
4.1、

五、单向链表问题收集(持续更新)
5.1、判断一个单向链表是否带环。
所谓带环,是指单向链表的一部分或全部处于循环之内。这是由于链表中有两个或以上节点的m_pNext指针指向了同一个节点。如图
解法:
创建两个指针,一个每次前进一步,记为pSlow,另一个每次前进两步,记为pFast。同时前进。如果两指针相遇,证明链表带环。如果至pFast到达链表尾都一直不相遇,证明无环。

5.2、判断链表是否相交。
分析:所谓相交,是指链表A和B有部分相同的节点。
解法:
首先要判断是否带环。
(1)如果两个链表都不带环,就判断尾节点是否相等,如相等则相交,如否则不相交。
(2)如果一个链表带环,另一个不带环。
(3)如果两个都带环。

5.3、不知道首节点,删除节点P
分析:由于首节点未知,无法取得节点P的前节点(设为Q)。如果直接删除P,Q->m_pNext将变成NULL,链表断裂。
解法:
(1)设R = P->m_pNext // 取P的后节点R
(2)P->m_element = R->m_element 
(3)删除节点R
5.4、求中央节点
解法:类似于5.1,一快一慢两指针,每次分别前进两步和一步。当pFast到达结尾,pSlow在中间。注意奇偶判断。

5.5、两有序链表,要求合并后仍然有序。
分析:以升序为例
解法1:递归解法
源码:
CNode* recursive_merge(CNode* a, CNode* b)
{
  if(NULL == a) return b;
  if(NULL == b) return a;
  if(a->m_element < b->m_element)
  {
    a->m_pNext = recursive_merge(a->m_pNext, b);
    return a;
  }
  else
  {
    b->m_pNext = recursive_merge(a,b->m_pNext);
    return b;
  }
}
5.6、寻找倒数第k个节点
解法:
(1)生成两个指针pFast和pSlow。
(2)pFast先走k-1步。
(3)pFast和pSlow一同前进,当pFast到达尾结节点时,pSlow所指就是倒数第k个节点
补充:对于这种第k个节点的问题,事先还要判断节点个数是否有k个。



参考资料

http://blog.csdn.net/luxiaoxun/article/details/7538217
http://blog.csdn.net/xitijie/article/details/7639028
http://blog.csdn.net/yang6512/article/details/7393109

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值