zoukankan      html  css  js  c++  java
  • 转: 单链表反转

      Java实现单链表翻转

    (一)单链表的结点结构: 
          data域:存储数据元素信息的域称为数据域; 
        next域:存储直接后继位置的域称为指针域,它是存放结点的直接后继的地址(位置)的指针域(链域)。
        data域+ next域:组成数据ai的存储映射,称为结点

        注意:①链表通过每个结点的链域将线性表的n个结点按其逻辑顺序链接在一起的。   
              ②每个结点只有一个链域的链表称为单链表(Single Linked List)。
         所谓的链表就好像火车车厢一样,从火车头开始,每一节车厢之后都连着后一节车厢。
         要实现单链表存储,首先是创建一结点类,其Java代码如下:
    [java] view plain copy
    1. class Node {  
    2.     private int Data;// 数据域  
    3.     private Node Next;// 指针域  
    4.     public Node(int Data) {  
    5.         // super();  
    6.         this.Data = Data;  
    7.     }  
    8.     public int getData() {  
    9.         return Data;  
    10.     }  
    11.     public void setData(int Data) {  
    12.         this.Data = Data;  
    13.     }  
    14.   
    15.     public Node getNext() {  
    16.         return Next;  
    17.     }  
    18.     public void setNext(Node Next) {  
    19.         this.Next = Next;  
    20.     }  
    21. }  
    (二)实现反转的方法:
      (1)递归反转法
    :在反转当前节点之前先反转后续节点。这样从头结点开始,层层深入直到尾结点才开始反转指针域的指向。简单的说就是从尾结点开始,逆向反转各个结点的指针域指向,其过程图如下所示:
       head:是前一结点的指针域(PS:前一结点的指针域指向当前结点)
       head.getNext():是当前结点的指针域(PS:当前结点的指针域指向下一结点)
       reHead:是反转后新链表的头结点(即原来单链表的尾结点)

    Java代码实现:
    [java] view plain copy
    1. package javatest1;  
    2. public class javatest1 {  
    3.     public static void main(String[] args) {  
    4.         Node head = new Node(0);  
    5.         Node node1 = new Node(1);  
    6.         Node node2 = new Node(2);  
    7.         Node node3 = new Node(3);  
    8.         head.setNext(node1);  
    9.         node1.setNext(node2);  
    10.         node2.setNext(node3);  
    11.   
    12.         // 打印反转前的链表  
    13.         Node h = head;  
    14.         while (null != h) {  
    15.             System.out.print(h.getData() + " ");  
    16.             h = h.getNext();  
    17.         }  
    18.         // 调用反转方法  
    19.         head = Reverse1(head);  
    20.   
    21.         System.out.println(" **************************");  
    22.         // 打印反转后的结果  
    23.         while (null != head) {  
    24.             System.out.print(head.getData() + " ");  
    25.             head = head.getNext();  
    26.         }  
    27.     }  
    28.   
    29.     /** 
    30.      * 递归,在反转当前节点之前先反转后续节点 
    31.      */  
    32.     public static Node Reverse1(Node head) {  
    33.         // head看作是前一结点,head.getNext()是当前结点,reHead是反转后新链表的头结点  
    34.         if (head == null || head.getNext() == null) {  
    35.             return head;// 若为空链或者当前结点在尾结点,则直接还回  
    36.         }  
    37.         Node reHead = Reverse1(head.getNext());// 先反转后续节点head.getNext()  
    38.         head.getNext().setNext(head);// 将当前结点的指针域指向前一结点  
    39.         head.setNext(null);// 前一结点的指针域令为null;  
    40.         return reHead;// 反转后新链表的头结点  
    41.     }  
    42. }  
    43.   
    44.     class Node {  
    45.         private int Data;// 数据域  
    46.         private Node Next;// 指针域  
    47.   
    48.         public Node(int Data) {  
    49.             // super();  
    50.             this.Data = Data;  
    51.         }  
    52.   
    53.         public int getData() {  
    54.             return Data;  
    55.         }  
    56.   
    57.         public void setData(int Data) {  
    58.             this.Data = Data;  
    59.         }  
    60.   
    61.         public Node getNext() {  
    62.             return Next;  
    63.         }  
    64.   
    65.         public void setNext(Node Next) {  
    66.             this.Next = Next;  
    67.         }  
    68.     }  
    (2)遍历反转法:递归反转法是从后往前逆序反转指针域的指向,而遍历反转法是从前往后反转各个结点的指针域的指向。
       基本思路是:将当前节点cur的下一个节点 cur.getNext()缓存到temp后,然后更改当前节点指针指向上一结点pre。也就是说在反转当前结点指针指向前,先把当前结点的指针域用tmp临时保存,以便下一次使用,其过程可表示如下:
       pre:上一结点
       cur: 当前结点
       tmp: 临时结点,用于保存当前结点的指针域(即下一结点)



    Java代码实现:
    [java] view plain copy
    1. package javatest1;  
    2. public class JavaTest1 {  
    3.     public static void main(String[] args) {  
    4.         Node head = new Node(0);  
    5.         Node node1 = new Node(1);  
    6.         Node node2 = new Node(2);  
    7.         Node node3 = new Node(3);  
    8.   
    9.         head.setNext(node1);  
    10.         node1.setNext(node2);  
    11.         node2.setNext(node3);  
    12.   
    13.         // 打印反转前的链表  
    14.         Node h = head;  
    15.         while (null != h) {  
    16.             System.out.print(h.getData() + " ");  
    17.             h = h.getNext();  
    18.         }  
    19.         // 调用反转方法  
    20.         // head = reverse1(head);  
    21.         head = reverse2(head);  
    22.   
    23.         System.out.println(" **************************");  
    24.         // 打印反转后的结果  
    25.         while (null != head) {  
    26.             System.out.print(head.getData() + " ");  
    27.             head = head.getNext();  
    28.         }  
    29.     }  
    30.   
    31.     /** 
    32.      * 遍历,将当前节点的下一个节点缓存后更改当前节点指针 
    33.      */  
    34.     public static Node reverse2(Node head) {  
    35.         if (head == null)  
    36.             return head;  
    37.         Node pre = head;// 上一结点  
    38.         Node cur = head.getNext();// 当前结点  
    39.         Node tmp;// 临时结点,用于保存当前结点的指针域(即下一结点)  
    40.         while (cur != null) {// 当前结点为null,说明位于尾结点  
    41.             tmp = cur.getNext();  
    42.             cur.setNext(pre);// 反转指针域的指向  
    43.   
    44.             // 指针往下移动  
    45.             pre = cur;  
    46.             cur = tmp;  
    47.         }  
    48.         // 最后将原链表的头节点的指针域置为null,还回新链表的头结点,即原链表的尾结点  
    49.         head.setNext(null);  
    50.           
    51.         return pre;  
    52.     }  
    53. }  
    54.   
    55. class Node {  
    56.     private int Data;// 数据域  
    57.     private Node Next;// 指针域  
    58.   
    59.     public Node(int Data) {  
    60.         // super();  
    61.         this.Data = Data;  
    62.     }  
    63.   
    64.     public int getData() {  
    65.         return Data;  
    66.     }  
    67.   
    68.     public void setData(int Data) {  
    69.         this.Data = Data;  
    70.     }  
    71.   
    72.     public Node getNext() {  
    73.         return Next;  
    74.     }  
    75.   
    76.     public void setNext(Node Next) {  
    77.         this.Next = Next;  
    78.     }  
    79. }  
  • 相关阅读:
    Azure PowerShell (7) 使用CSV文件批量设置Virtual Machine Endpoint
    Windows Azure Cloud Service (39) 如何将现有Web应用迁移到Azure PaaS平台
    Azure China (7) 使用WebMetrix将Web Site发布至Azure China
    Microsoft Azure News(4) Azure新D系列虚拟机上线
    Windows Azure Cloud Service (38) 微软IaaS与PaaS比较
    Windows Azure Cloud Service (37) 浅谈Cloud Service
    Azure PowerShell (6) 设置单个Virtual Machine Endpoint
    Azure PowerShell (5) 使用Azure PowerShell创建简单的Azure虚拟机和Linux虚拟机
    功能代码(1)---通过Jquery来处理复选框
    案例1.用Ajax实现用户名的校验
  • 原文地址:https://www.cnblogs.com/xmanblue/p/8057920.html
Copyright © 2011-2022 走看看