您的位置:首页 > 编程语言 > Java开发

链表的反转(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; } }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: