版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lwl2014100338/article/details/84498333
技巧一:理解指针或者引用的含义
将某个变量赋值给指针,实际上就是将这个变量的地址赋值给 指针,或者反过来说,指针中存储了 这个变量的内存地址,指向了这个变量,通过这个指针就可以找到这个变量
技巧二:警惕指针丢失和内存泄漏
添加节点
x->next = p->next ; //将x的节点的next指针指向b节点
p->next =x;//将p的next指针指向x节点
删除节点
p->next=p->next->next
(1)插入节点时一定要注意操作的顺序,要现将节点x的next指针指向节点b,再把节点a的next指针指向节点x
(2)删除链表节点时,一定要记得手动释放内存地址
技巧三:利用哨兵简化实现难度
(1)针对链表的插入、删除操作,需要对插入第一个节点和删除最后一个节点的情况进行特殊处理
(2)不管链表是不是空,head指针都会一直指向这个哨兵节点。我们把这种有哨兵节点的链表叫带头链表。相反,没有哨兵节点的链表就叫不带头链表
技巧四:重点留意边界条件处理
检查链表代码是否正确的边界条件
- 如果链表为空时,代码是否能正常工作
- 如果链表只包含一个节点时,代码是否能正常工作
- 如果链表只包含两个节点时,代码是否能正常工作
- 代码逻辑在处理头节点和尾节点的时候,是否能正常工作
在写代码的时候,不要只实现了业务正常情况下功能就好了,要多想想,你的代码在运行的时候,可能会遇到哪些边界情况或者异常情况。遇到了应如何应对,这样写出来的代码才够健壮
技巧五:举例画图,辅助思考
当我们写完代码之后,可以举几个例子,画在纸上,照着代码走一遍,很容易发现代码中的bug
技巧六:多写多练,没有捷径
五个常见的链表操作
(1)单链表反转
思路:
pCur是需要反转的节点。
- prev连接下一次需要反转的节点
- 反转节点pCur
- 纠正头结点dummy的指向
- pCur指向下一次要反转的节点
伪代码
1 prev.next = pCur.next;
2 pCur.next = dummy.next;
3 dummy.next = pCur;
4 pCur = prev.next;
循环条件 :pCur is not null
(2)链表中环的检测
思路
P1是慢指针,一次遍历一个节点。
P2是快指针,一次遍历两个节点。
如果链表中没有环,P2和P1会先后遍历完所有的节点。
如果链表中有环,P2和P1则会先后进入环中,一直循环,并一定会在在某一次遍历中相遇。
Java代码实现
// 检测环
public static boolean checkCircle(Node list) {
if (list == null) return false;
Node fast = list.next;
Node slow = list;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
if (slow == fast) return true;
}
return false;
}
(3)两个有序的链表合并
(4)删除链表倒数第n个节点
(5)求链表的中间节点
思路
设置两个指针slow和fast,两个指针同时向前走,fast指针每次走两步,slow指针每次走一步,直到fast指针走到最后一个结点时,此时slow指针所指的结点就是中间结点。
Java代码实现
// 求中间结点
public static Node findMiddleNode(Node list) {
if (list == null) return null;
Node fast = list;
Node slow = list;
while (fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}