首先我们要搞清楚链表是啥玩意儿?先看看定义:
讲链表之前我们先说说Java内存的分配情况:我们new对象的时候,会在java堆中为对象分配内存,当我们调用方法的时候,会将方法加载到方法区,在方法区保存了加载类的信息,常量,静态变量等等。搞明白这个我们再来讲链表。
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 这个定义估计太过书面化,对初学者来说,不好理解,其实简单点说就是酱紫的。我们创建了一个类Node,这个类当中有两个变量,一个data用于存储数据,还有一个Node类型的变量next用于存储另一个对象在java堆中的地址。然后new了很多个Node类的对象,我们通过setNext方法将第二个对象node2的地址给node1保存起来,同样的将第三个对象node3的地址交给node2保存起来。通过这种方式,我们就将很多个对象连成串了,形成了一种链状。这就是链表了。
这儿着重声明:在Java中,没有地址一说,只有hashCode。其实hashCode就是通过算法,将每一个对象的地址算成一个code转成一个特有的字符串。当我们没有复写Object类的toString方法的时候,该类的对象调用toString方法,打印出来,或者不调用toString方法,直接打印该类的对象,其实就是将hashCode打印出来了。这个hashCode就相当于是内存了。
先上一张图片:
可能不是很好理解:
迭代法。先将下一节点纪录下来,然后让当前节点指向上一节点,再将当前节点纪录下来,再让下一节点变为当前节点。
代码:
1 package com.atguigu.reverse; 2 3 public class LinkedList { 4 public static void main(String[] args) { 5 Node node = new Node(1); 6 node.next = new Node(2); 7 node.next.next = new Node(3); 8 node.next.next.next = new Node(4); 9 Node res = reverse(node);10 System.out.println(res);11 }12 13 public static Node reverse(Node node){14 //如何链表没有元素,返回null值。15 if(node == null){16 return null;17 }18 19 //如果链表只有一个元素,不必要反转,返回链表本身就行。20 if(node.next == null){21 return node;22 }23 24 //当链表超过两个及以上就需要反转25 Node pre = null;//用于保存当前节点的前一个节点26 Node cur = node;//cur保存当前节点27 28 while(cur != null){29 Node next = cur.next;//获取当前节点的下一个元素30 cur.next = pre;//把当前节点的next指向前一个元素31 pre = cur;//把当前节点改为前一个节点(其实就是前一个元素后移一位)。32 cur = next;//把当前节点的下一个节点改为当前节点(其实就是前一个元素后移一位)。33 }34 35 //因为反转后pre是第一个节点,所以返回pre.36 return pre;37 }38 }39 40 class Node{41 public Integer data;42 public Node next;43 public Node(Integer data) {44 super();45 this.data = data;46 }47 @Override48 public String toString() {49 return "Node [data=" + data + ", next=" + next + "]";50 }51 }