数据结构和算法之单向链表六:链表的反转以及链表节点的删除
在前面介绍了关于链表的一系列问题,这里我们在介绍一下关于单向链表的反转这个比较具有代表性的算法。在进行反转的时候一定要记住多画图,多去理解在链表进行反转的时候它对于地址的改变,这和数组的数据对换具有很大的不一致。
public Node reverseList(Node head){ //判断链表是否为空或者只有一个节点 if(head == null || head.next == null){ return head; } //准备三个节点 Node next = null;//保存当前节点的下一个节点 Node reverse = null;//反转以后链表的头节点 Node current = head;//当前正在进行反转的节点 while(current != null){ //保存当前节点的下一个节点 next = current.next; //将头结点转换给当前节点的下一个节点 current.next = reverse; //给头结点赋值 reverse = current; //将当前节点后移 current = next; } return reverse; }
重要的事情说三遍,地址转换很重要!地址转换很重要!地址转换很重要!
关于单向链表的删除问题为什么我会在这里单独拿出来进行说一下,这是属于单向链表的基本操作,但是我们可不可以思考一个问题。在前面我们说了地址转换这个东西,如果我们在进行删除的时候,将要删除的节点的下一个节点赋值给删除的节点,然后再把下一个节点变为空,那么我们是不是就实现了删除的操作。代码如下:
public boolean deleteNode(Node delete){ //判断链表是否为空 if(head == null){ return false; } //判断该节点是否是尾节点 if(delete.next == null){ delete = null; return true; } //找到需要删除节点的下一个节点 Node next = delete.next //将下一节点的值赋给删除节点,并清空删除节点信息 delete = next; next = null; return true; }
删除的代码只是提供了思路,代码需要自己去重写。关于这么写的好处那是显而易见的,我们可以在删除的时候只花销O(1)的时间,如果常规思路我们去获取删除节点的前一个节点我们花费的时间可远远不止这些。当然这是建立在链表里必有这个节点的前提下,如果链表节点是否存在需要我们自己去判断那自然是无法完成,因为这样便利一个链表的时间是O(N)。