链表的反转(java实现)
2017-10-26 14:54
711 查看
链表的反转(java实现)
本文参考博文: http://blog.csdn.net/feliciafay/article/details/6841115本文参考博文:http://blog.csdn.net/ns_code/article/details/25737023
对于给定的链表,
例如,输入: 1 -> 2 ->3 ->4 ->5
输出: 5 -> 4 ->3 ->2 ->1
class ListNode { int val; ListNode next; ListNode(int x) { val = x; } }
笔者在参考了其他博文后给出四种方式
利用数组完成反转
使用3指针进行迭代
从第2个节点到第N个节点,依次逐节点插入到第1个节点(head节点)之后,最后将第一个节点挪到新表的表尾。
递归
方式一
形式简单,直接遍历链表,将每一个节点存储到数组中,然后再反向遍历数组构建出新链表,即完成链表的反转,但至少需要多开辟出等链表长度的数组,因此不划算方式二
对于 1 -> 2 -> 3 ->4 -> 5的链表,head为头节点假使在遍历链表的过程中,有这样的情形
思路:在遍历的过程中,要完成反转,则期望第一趟遍历时,2 ->1, 第二趟遍历时 3 -> 2… 这样最后一个结点指向倒数第二个结点,此时,最后一个结点就成为了头结点
遍历前:
q = head.next,
第一趟:将链表分为(1,2) 和(3,4,5),将2对应的结点的next域指向1对应的结点,那么问题来了,示例的链表中1对应的结点为head结点,可是反转后的链表,head.next必定为null,因此在循环前必须执行语句
head.next = null
第二趟:链表被分为(1,2,3)和(4,5),其中 2 -> 1; 只需要在此时将3对应的结点指向2对应的结点
依次遍历…. 即完成所有结点的指向
备注:笔者说的链表拆分只是形式的认为,这样在长度为n的链表中,在进行第 j 趟排序时,只需要关注(1~ j+1)的数据位置即可
/** * 链表的反转(使用3个指针遍历单链表,逐个链接点进行反转) * @param head * @autho 4000 r Lancelot * @return */ public static ListNode reverse(ListNode head){ ListNode p = head; ListNode q = head.next; head.next = null; ListNode r; while(q != null){ r = q; q = q.next; r.next = p; p = r; } return p; }
方法三
从第2个节点到第N个节点,遍历过程中,都将当前结点插入到头结点后面,最后将头结点移到最后未排序:1 -> 2 -> 3 ->4 -> 5
第一趟:1 -> 3 -> 2 ->4 -> 5
第二趟:1 -> 4 -> 3 ->2 -> 5
第三趟:1 -> 5 -> 4 ->3 -> 2
第四趟:5 -> 4 -> 3 ->2 -> 1
/** * 从第2个节点到第N个节点,依次逐节点插入到第1个节点(head节点)之后,最后将第一个节点挪到新表的表尾 * @author Lancelot * @param head * @return */ public static ListNode reverse2(ListNode head){ if(head == null) return null; if(head.next == null) return head; ListNode p = null; ListNode q = head.next; while(q.next != null){ p = q.next; q.next = p.next; p.next = head.next; head.next = p; } q.next = head; head = q.next.next; q.next.next = null; return head; }
方法四(递归)
使用递归首要的任务就是构建相似性,对于1 -> 2 -> 3 ->4 -> 5这样的链表,如果把(2,3,4,5)看成整体,则只需要考虑(2,3,4,5)和 1 的指向问题,那么同理,对于(2,3,4,5),则只需要考虑 2 和(3,4,5)的指向问题。这样,相似性就被找到了,就可以很容易写出相应的代码(备注:*此处思路参考博文*)static ListNode reverse = null; //新链表的头结点,即原链表的尾结点 /** * * @author Lancelot * @param head * @return */ public static ListNode reverse3(ListNode head){ if(head == null) return null; if(head.next == null){ reverse = head; return head; } ListNode newTail = reverse3(head.next); newTail.next = head; head.next = null; return head; }
最后,附上三种思路的所有代码
/**
* 反转链表
* @author Lancelot
*
*/
public class ReverseListNode {
public static void main(String[] args) {
ListNode head = new ListNode(1);
ListNode node2 = new ListNode(2); head.next = node2;
ListNode node3 = new ListNode(3); node2.next = node3;
ListNode node4 = new ListNode(4); node3.next = node4;
ListNode node5 = new ListNode(5); node4.next = node5;
//方法二
// ListNode reverse2 = reverse(head);
// print(reverse2);
//方法三
ListNode reverse3 = reverse2(head);
print(reverse3);
//方法四
// reverse3(head);
// print(reverse);
}
static ListNode reverse = null; //新链表的头结点,即原链表的尾结点
/**
* @author Lancelot
* @param head
* @return
*/
public static ListNode reverse3(ListNode head){
if(head == null)
return null;
if(head.next == null){
reverse = head;
return head;
}
ListNode newTail = reverse3(head.next);
newTail.next = head;
head.next = null;
return head;
}
/** * 从第2个节点到第N个节点,依次逐节点插入到第1个节点(head节点)之后,最后将第一个节点挪到新表的表尾 * @author Lancelot * @param head * @return */ public static ListNode reverse2(ListNode head){ if(head == null) return null; if(head.next == null) return head; ListNode p = null; ListNode q = head.next; while(q.next != null){ p = q.next; q.next = p.next; p.next = head.next; head.next = p; } q.next = head; head = q.next.next; q.next.next = null; return head; }
/**
* 链表的反转(使用3个指针遍历单链表,逐个链接点进行反转)
* @param head
* @author Lancelot
* @return
*/
public static ListNode reverse(ListNode head){
ListNode p = head;
ListNode q = head.next;
head.next = null;
ListNode r;
while(q != null){
r = q;
q = q.next;
r.next = p;
p = r;
}
return p;
}
/**
* 计算链表的长度
* @param li 1, 2, 3, 4, 5,
* @return
*/
public static int getLength(ListNode li){
int x = 0;
while(li != null){
x ++;
li = li.next;
}
return x;
}
/**
* 打印链表
* @param node
*/
public static void print(ListNode node){
while(node != null){
System.out.print(node.val + " ");
node = node.next;
}
}
}
class ListNode { int val; ListNode next; ListNode(int x) { val = x; } }
相关文章推荐
- Java中单链表的实现和单链表的反转(倒置)
- 反转链表的Java实现
- java实现链表反转
- Java实现反转单链表
- JAVA实现链表的反转(《剑指offer》)
- java-实现链表反转-递归和非递归实现
- 不依赖堆栈的链表反转——java实现
- java实现单链表反转(递归方式)
- Java实现的单链表反转方法(1)
- 反转链表 - java和rust的不同实现
- (整理)Java实现链表----链表的反转
- 单链表的反转java实现
- java实现链表反转
- 用java实现反转链表
- 链表、反转链表操作,Java实现
- java实现链表反转
- 反转链表_Java实现
- java 实现反转链表
- java 使用头插法实现反转链表
- 【LeetCode-面试算法经典-Java实现】【025-Reverse Nodes in k-Group(单链表中k个结点一组进行反转)】