天天看点

JAVA手写代码链表反转_数据结构List示例(一):链表反转

链式存储结构就是两个相邻的元素在内存中可能不是相邻的,每一个元素都有一个指针域,指针域一般是存储着到下一个元素的指针。这种存储方式的优点是插入和删除的时间复杂度为O(1),不会浪费太多内存,添加元素的时候才会申请内存,删除元素会释放内存,。缺点是访问的时间复杂度最坏为O(n),关于查找的算法很少,一般只能遍历,这样时间复杂度也是线性(O(n))的了,频繁的申请和释放内存也会消耗时间。

顺序表的特性是随机读取,也就是访问一个元素的时间复杂度是O(1),链式表的特性是插入和删除的时间复杂度为O(1)。要根据实际情况去选取适合自己的存储结构。

链表就是链式存储的线性表。根据指针域的不同,链表分为单向链表、双向链表、循环链表等等。

链表反转也是比较常见的问题,一般解决方式是:分别设置三个指针。第一个指针保持结果,第二个指针指向当前的节点,第三个指针保存下一个节点。实现代码如下:

    package List;    public class ListReverse {    public static class Node { public int data; public Node next;   public Node(int data) { this.data = data; this.next = null; } }    public static class LinkList { // 根结点 private Node root;    public void push(int data) { Node cur = root; if (root == null) { // 分配内存空间 root = new Node(data); return; } while (cur.next != null) { cur = cur.next; } // 分配内存空间 cur.next = new Node(data); }    public Node linkListReversre() { // 当前结点 Node cur = null; // 下一个结点 Node next = null; // 前一个结点 Node pre = null;   // 判断边界条件,空链表 if (root == null) { return null; } // 赋值 cur = root; // 当链表非空时,执行反转 while (cur != null) { // 保存后一个结点 next = cur.next; // 注意此处反转的顺序不能乱 cur.next = pre; pre = cur; cur = next; } // 反转结束后修改头结点 root = pre; // 返回 return root; }  public Node linkListRecReverse(Node cur){ // Node cur = root; if(cur == null || cur.next == null){ return cur; } //递归 Node reverseRest = linkListRecReverse(cur.next); //反转 cur.next.next = cur; //源节点为空 cur.next = null; return reverseRest; }   public void printList() { Node cur = root; // 空表 if (root == null) { return; } // 非空 while (cur != null) { System.out.print(cur.data + " "); cur = cur.next; } } }      public static void main(String[] args) { // TODO Auto-generated method stub LinkList list = new LinkList(); //添加数据 list.push(10); list.push(2); list.push(3); list.push(4); list.push(5); list.push(6); //输出原始链表 list.printList(); System.out.println(); //非递归反转 list.linkListReversre(); //输出原始链表 list.printList();  }   }