只谈一下单链表, 链表实在是太重要, 是前面两篇说算法博客的基础, 了解了其应用和衍生, 再去了解其本身就有动力了
这是一篇偏向单链表进阶的博客, 并不会讲单链表的建立/增加/删除等等, 而且这篇博客大多数只说思想不写代码(因为其实蛮简单的..)
存储结构
typedef struct Node
{
DataType data;
struct Node *next;
}Node, *Node_Ptr;
1.找一个单链表的中间结点
算法思想 :
(快慢指针的使用)设置两个指针,一个每次移动两个位置,一个每次移动一个位置,当第一个指针到达尾节点时,第二个指针就达到了中间节点的位置
2.判断链表中是否有环
算法思想 :
(快慢指针的使用)链表中有环,其实也就是自相交. 用两个指针pslow和pfast从头开始遍历链表,pslow每次前进一个节点,pfast每次前进两个结点,若存在环,则pslow和pfast肯定会在环中相遇,若不存在,则pslow和pfast能正常到达最后一个节点
3.判断两个链表是否相交, 假设两个链表均不带环
算法思想 :
如果两个链表相交于某一节点,那么在这个相交节点之后的所有节点都是两个链表所共有的。也就是说,如果两个链表相交,那么最后一个节点肯定是共有的。先遍历第一个链表,记住最后一个节点,然后遍历第二个链表,到最后一个节点时和第一个链表的最后一个节点做比较,如果相同,则相交,否则不相交。
4.链表反转
比如一个链表:
A->B->C->D->E
反转成为:
E->D->C->B->A
算法思想 :
取一个指针指向A的后面那个元素elem, 每次把element放到链表的第一个位置, 遍历完毕之后就反转完毕了,过程如下:
第一轮 : A->B->C->D->E, 把A后面的B设置为element
第二轮 : B->A->C->D->E, 把当前的element(即为B)放到链表的第一个位置, 并把A后面的C设置为element
第三轮 : C->B->A->D->E, 把当前的element(即为C)放到链表的第一个位置, 并把A后面的D设置为element
第四轮 : D->C->B->A->E, 把当前的element(即为D)放到链表的第一个位置, 并把A后面的E设置为element
第五轮 : E->D->C->B->A, 把当前的element(即为E)放到链表的第一个位置, 遍历完毕