zoukankan      html  css  js  c++  java
  • 学习记录 java 链表知识

    01.import java.util.HashMap;  
    02.import java.util.Scanner;  
    03.import java.util.Stack;  
    04.  
    05./** 
    06. *  
    07. * @author kerryfish 
    08. * 关于java中链表的操作 
    09. * 1. 求单链表中结点的个数: getListLength  
    10. * 2. 将单链表反转: reverseList(遍历),reverseListRec(递归)  
    11. * 3. 查找单链表中的倒数第K个结点(k > 0): reGetKthNode  
    12. * 4. 查找单链表的中间结点: getMiddleNode  
    13. * 5. 从尾到头打印单链表: reversePrintListStack,reversePrintListRec(递归)  
    14. * 6. 已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序: mergeSortedList, mergeSortedListRec  
    15. * 7. 对单链表进行排序,listSort(归并),insertionSortList(插入) 
    16. * 8. 判断一个单链表中是否有环: hasCycle  
    17. * 9. 判断两个单链表是否相交: isIntersect  
    18. * 10. 已知一个单链表中存在环,求进入环中的第一个节点: getFirstNodeInCycle, getFirstNodeInCycleHashMap  
    19. * 11. 给出一单链表头指针head和一节点指针delete,O(1)时间复杂度删除节点delete: deleteNode 
    20. */  
    21.public class LinkedListSummary {  
    22.    /** 
    23.     * @param args 
    24.     *  
    25.     */  
    26.    public static class Node{  
    27.        int value;  
    28.        Node next;  
    29.        public Node(int n){  
    30.            this.value=n;  
    31.            this.next=null;  
    32.        }  
    33.    }  
    34.    public static void main(String[] args) {  
    35.        // TODO Auto-generated method stub   
    36.        Scanner in=new Scanner(System.in);  
    37.        Node head=null;  
    38.        if(in.hasNextInt()){  
    39.            head=new Node(in.nextInt());  
    40.        }  
    41.        Node temp=head;  
    42.        while(in.hasNextInt()){  
    43.            temp.next=new Node(in.nextInt());  
    44.            temp=temp.next;  
    45.        }  
    46.        in.close();  
    47.        //int len=getListLength(head);   
    48.        //Node reHead=reverseList(head);   
    49.        //reHead=reverseListRec(reHead);   
    50.        //Node node_k=reGetKthNode(head,3);   
    51.        //Node mid=getMiddleNode(head);   
    52.        //reversePrintListRec(head);   
    53.        //reversePrintListStack(head);   
    54.        //Node mergeHead=mergeSortedList(head,null);   
    55.        //Node sortHead=listSort(head);   
    56.          
    57.    }  
    58.    //求单链表中结点的个数: getListLength    
    59.    public static int getListLength(Node head){  
    60.        int len=0;  
    61.        while(head!=null){  
    62.            len++;  
    63.            head=head.next;  
    64.        }  
    65.        return len;  
    66.    }  
    67.    //将单链表反转,循环   
    68.    public static Node reverseList(Node head){  
    69.        if(head==null||head.next==null)return head;  
    70.        Node pre=null;  
    71.        Node nex=null;  
    72.        while(head!=null){  
    73.            nex=head.next;  
    74.            head.next=pre;  
    75.            pre=head;  
    76.            head=nex;  
    77.        }  
    78.        return pre;  
    79.    }  
    80.    //将单链表反转,递归   
    81.    public static Node reverseListRec(Node head){  
    82.        if(head==null||head.next==null)return head;  
    83.        Node reHead=reverseListRec(head.next);  
    84.        head.next.next=head;  
    85.        head.next=null;  
    86.        return reHead;  
    87.    }  
    88.    //查找单链表中的倒数第K个结点(k > 0)   
    89.    public static Node reGetKthNode(Node head,int k){  
    90.        if(head==null)return head;  
    91.        int len=getListLength(head);  
    92.        if(k>len)return null;  
    93.        Node target=head;  
    94.        Node nexk=head;  
    95.        for(int i=0;i<k;i++){  
    96.            nexk=nexk.next;  
    97.        }  
    98.        while(nexk!=null){  
    99.            target=target.next;  
    100.            nexk=nexk.next;  
    101.        }  
    102.        return target;  
    103.    }  
    104.    //查找单链表的中间结点    
    105.    public static Node getMiddleNode(Node head){  
    106.        if(head==null||head.next==null)return head;  
    107.        Node target=head;  
    108.        Node temp=head;  
    109.        while(temp!=null&&temp.next!=null){  
    110.            target=target.next;  
    111.            temp=temp.next.next;  
    112.        }  
    113.        return target;  
    114.    }  
    115.    //从尾到头打印单链表,递归   
    116.    public static void reversePrintListRec(Node head){  
    117.        if(head==null)return;  
    118.        else{  
    119.            reversePrintListRec(head.next);  
    120.            System.out.println(head.value);  
    121.        }  
    122.    }  
    123.    //从尾到头打印单链表,栈   
    124.    public static void reversePrintListStack(Node head){  
    125.        Stack<Node> s=new Stack<Node>();  
    126.        while(head!=null){  
    127.            s.push(head);  
    128.            head=head.next;  
    129.        }  
    130.        while(!s.isEmpty()){  
    131.            System.out.println(s.pop().value);  
    132.        }  
    133.    }  
    134.    //合并两个有序的单链表head1和head2,循环   
    135.    public static Node mergeSortedList(Node head1,Node head2){  
    136.        if(head1==null)return head2;  
    137.        if(head2==null)return head1;  
    138.        Node target=null;  
    139.        if(head1.value>head2.value){  
    140.            target=head2;  
    141.            head2=head2.next;  
    142.        }  
    143.        else{  
    144.            target=head1;  
    145.            head1=head1.next;  
    146.        }  
    147.        target.next=null;  
    148.        Node mergeHead=target;  
    149.        while(head1!=null && head2!=null){  
    150.            if(head1.value>head2.value){  
    151.                target.next=head2;  
    152.                head2=head2.next;  
    153.            }  
    154.            else{  
    155.                target.next=head1;  
    156.                head1=head1.next;  
    157.            }  
    158.            target=target.next;  
    159.            target.next=null;  
    160.        }  
    161.        if(head1==null)target.next=head2;  
    162.        else target.next=head1;  
    163.        return mergeHead;  
    164.    }  
    165.    //合并两个有序的单链表head1和head2,递归   
    166.    public static Node mergeSortedListRec(Node head1,Node head2){  
    167.        if(head1==null)return head2;  
    168.        if(head2==null)return head1;  
    169.        if(head1.value>head2.value){  
    170.            head2.next=mergeSortedListRec(head2.next,head1);  
    171.            return head2;  
    172.        }  
    173.        else{  
    174.            head1.next=mergeSortedListRec(head1.next,head2);  
    175.            return head1;  
    176.        }  
    177.    }  
    178.    //对单链表进行排序,归并排序,在排序里面不建议选用递归的合并有序链表算法,如果链表长度较长,很容易出现栈溢出   
    179.    public static Node listSort(Node head){  
    180.        Node nex=null;  
    181.        if(head==null||head.next==null)return head;  
    182.        else if(head.next.next==null){  
    183.            nex=head.next;  
    184.            head.next=null;  
    185.        }  
    186.        else{  
    187.            Node mid=getMiddleNode(head);  
    188.            nex=mid.next;  
    189.            mid.next=null;  
    190.        }  
    191.        return mergeSortedList(listSort(head),listSort(nex));//合并两个有序链表,不建议递归   
    192.    }  
    193.    //对单链表进行排序,插入排序   
    194.    public Node insertionSortList(Node head) {  
    195.        if(head==null||head.next==null)return head;  
    196.        Node pnex=head.next;  
    197.        Node pnex_nex=null;  
    198.        head.next=null;  
    199.        while(pnex!=null){  
    200.            pnex_nex=pnex.next;  
    201.            Node temp=head;  
    202.            Node temp_pre=null;  
    203.            while(temp!=null){  
    204.                if(temp.value>pnex.value)break;  
    205.                temp_pre=temp;  
    206.                temp=temp.next;  
    207.            }  
    208.            if(temp_pre==null){  
    209.                head=pnex;  
    210.                pnex.next=temp;  
    211.            }  
    212.            else{  
    213.                temp_pre.next=pnex;  
    214.                pnex.next=temp;  
    215.            }  
    216.            pnex=pnex_nex;  
    217.        }  
    218.        return head;  
    219.    }  
    220.    //判断一个单链表中是否有环,快慢指针   
    221.    public static boolean hasCycle(Node head){  
    222.        boolean flag=false;  
    223.        Node p1=head;  
    224.        Node p2=head;  
    225.        while(p1!=null&&p2!=null){  
    226.            p1=p1.next;  
    227.            p2=p2.next.next;  
    228.            if(p2==p1){  
    229.                flag=true;  
    230.                break;  
    231.            }  
    232.        }  
    233.        return flag;  
    234.    }  
    235.    //判断两个单链表是否相交,如果相交返回第一个节点,否则返回null   
    236.    //如果单纯的判断是否相交,只需要看最后一个指针是否相等   
    237.    public static Node isIntersect(Node head1,Node head2){  
    238.        Node target=null;  
    239.        if(head1==null||head2==null)return target;  
    240.        int len1=getListLength(head1);  
    241.        int len2=getListLength(head2);  
    242.        if(len1>=len2){  
    243.            for(int i=0;i<len1-len2;i++){  
    244.                head1=head1.next;  
    245.            }  
    246.        }else{  
    247.            for(int i=0;i<len2-len1;i++){  
    248.                head2=head2.next;  
    249.            }  
    250.        }  
    251.        while(head1!=null&&head2!=null){  
    252.            if(head1==head2){  
    253.                target=head1;  
    254.                break;  
    255.            }  
    256.            else{  
    257.                head1=head1.next;  
    258.                head2=head2.next;  
    259.            }  
    260.        }  
    261.        return target;  
    262.    }  
    263.    //已知一个单链表中存在环,求进入环中的第一个节点,利用hashmap,不要用ArrayList,因为判断ArrayList是否包含某个元素的效率不高   
    264.    public static Node getFirstNodeInCycleHashMap(Node head){  
    265.        Node target=null;  
    266.        HashMap<Node,Boolean> map=new HashMap<Node,Boolean>();  
    267.        while(head!=null){  
    268.            if(map.containsKey(head))target=head;  
    269.            else{  
    270.                map.put(head, true);  
    271.            }  
    272.            head=head.next;  
    273.        }  
    274.        return target;  
    275.    }  
    276.    //已知一个单链表中存在环,求进入环中的第一个节点,不用hashmap   
    277.    //用快慢指针,与判断一个单链表中是否有环一样,找到快慢指针第一次相交的节点,此时这个节点距离环开始节点的长度和链表投距离环开始的节点的长度相等   
    278.    public static Node getFirstNodeInCycle(Node head){  
    279.        Node fast=head;  
    280.        Node slow=head;  
    281.        while(fast!=null&&fast.next!=null){  
    282.            slow=slow.next;  
    283.            fast=fast.next.next;  
    284.            if(slow==fast)break;  
    285.        }  
    286.        if(fast==null||fast.next==null)return null;//判断是否包含环   
    287.        //相遇节点距离环开始节点的长度和链表投距离环开始的节点的长度相等   
    288.        slow=head;  
    289.        while(slow!=fast){  
    290.            slow=slow.next;  
    291.            fast=fast.next;  
    292.        }//同步走   
    293.        return slow;  
    294.          
    295.    }  
    296.    //给出一单链表头指针head和一节点指针delete,O(1)时间复杂度删除节点delete   
    297.    //可惜采用将delete节点value值与它下个节点的值互换的方法,但是如果delete是最后一个节点,则不行,但是总得复杂度还是O(1)   
    298.    public static void deleteNode(Node head,Node delete){  
    299.        //首先处理delete节点为最后一个节点的情况   
    300.        if(delete==null)return;  
    301.        if(delete.next==null){  
    302.            if(head==delete)head=null;  
    303.            else{  
    304.                Node temp=head;  
    305.                while(temp.next!=delete){  
    306.                    temp=temp.next;  
    307.                }  
    308.                temp.next=null;  
    309.            }  
    310.        }  
    311.        else{  
    312.            delete.value=delete.next.value;  
    313.            delete.next=delete.next.next;  
    314.        }  
    315.        return;  
    316.    }  
    317.}  
    import java.util.HashMap;
    import java.util.Scanner;
    import java.util.Stack;
    
    /**
     * 
     * @author kerryfish
     * 关于java中链表的操作
     * 1. 求单链表中结点的个数: getListLength 
     * 2. 将单链表反转: reverseList(遍历),reverseListRec(递归) 
     * 3. 查找单链表中的倒数第K个结点(k > 0): reGetKthNode 
     * 4. 查找单链表的中间结点: getMiddleNode 
     * 5. 从尾到头打印单链表: reversePrintListStack,reversePrintListRec(递归) 
     * 6. 已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序: mergeSortedList, mergeSortedListRec 
     * 7. 对单链表进行排序,listSort(归并),insertionSortList(插入)
     * 8. 判断一个单链表中是否有环: hasCycle 
     * 9. 判断两个单链表是否相交: isIntersect 
     * 10. 已知一个单链表中存在环,求进入环中的第一个节点: getFirstNodeInCycle, getFirstNodeInCycleHashMap 
     * 11. 给出一单链表头指针head和一节点指针delete,O(1)时间复杂度删除节点delete: deleteNode
     */
    public class LinkedListSummary {
        /**
         * @param args
         * 
         */
        public static class Node{
            int value;
            Node next;
            public Node(int n){
                this.value=n;
                this.next=null;
            }
        }
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            Scanner in=new Scanner(System.in);
            Node head=null;
            if(in.hasNextInt()){
                head=new Node(in.nextInt());
            }
            Node temp=head;
            while(in.hasNextInt()){
                temp.next=new Node(in.nextInt());
                temp=temp.next;
            }
            in.close();
            //int len=getListLength(head);
            //Node reHead=reverseList(head);
            //reHead=reverseListRec(reHead);
            //Node node_k=reGetKthNode(head,3);
            //Node mid=getMiddleNode(head);
            //reversePrintListRec(head);
            //reversePrintListStack(head);
            //Node mergeHead=mergeSortedList(head,null);
            //Node sortHead=listSort(head);
            
        }
        //求单链表中结点的个数: getListLength 
        public static int getListLength(Node head){
            int len=0;
            while(head!=null){
                len++;
                head=head.next;
            }
            return len;
        }
        //将单链表反转,循环
        public static Node reverseList(Node head){
            if(head==null||head.next==null)return head;
            Node pre=null;
            Node nex=null;
            while(head!=null){
                nex=head.next;
                head.next=pre;
                pre=head;
                head=nex;
            }
            return pre;
        }
        //将单链表反转,递归
        public static Node reverseListRec(Node head){
            if(head==null||head.next==null)return head;
            Node reHead=reverseListRec(head.next);
            head.next.next=head;
            head.next=null;
            return reHead;
        }
        //查找单链表中的倒数第K个结点(k > 0)
        public static Node reGetKthNode(Node head,int k){
            if(head==null)return head;
            int len=getListLength(head);
            if(k>len)return null;
            Node target=head;
            Node nexk=head;
            for(int i=0;i<k;i++){
                nexk=nexk.next;
            }
            while(nexk!=null){
                target=target.next;
                nexk=nexk.next;
            }
            return target;
        }
        //查找单链表的中间结点 
        public static Node getMiddleNode(Node head){
            if(head==null||head.next==null)return head;
            Node target=head;
            Node temp=head;
            while(temp!=null&&temp.next!=null){
                target=target.next;
                temp=temp.next.next;
            }
            return target;
        }
        //从尾到头打印单链表,递归
        public static void reversePrintListRec(Node head){
            if(head==null)return;
            else{
                reversePrintListRec(head.next);
                System.out.println(head.value);
            }
        }
        //从尾到头打印单链表,栈
        public static void reversePrintListStack(Node head){
            Stack<Node> s=new Stack<Node>();
            while(head!=null){
                s.push(head);
                head=head.next;
            }
            while(!s.isEmpty()){
                System.out.println(s.pop().value);
            }
        }
        //合并两个有序的单链表head1和head2,循环
        public static Node mergeSortedList(Node head1,Node head2){
            if(head1==null)return head2;
            if(head2==null)return head1;
            Node target=null;
            if(head1.value>head2.value){
                target=head2;
                head2=head2.next;
            }
            else{
                target=head1;
                head1=head1.next;
            }
            target.next=null;
            Node mergeHead=target;
            while(head1!=null && head2!=null){
                if(head1.value>head2.value){
                    target.next=head2;
                    head2=head2.next;
                }
                else{
                    target.next=head1;
                    head1=head1.next;
                }
                target=target.next;
                target.next=null;
            }
            if(head1==null)target.next=head2;
            else target.next=head1;
            return mergeHead;
        }
        //合并两个有序的单链表head1和head2,递归
        public static Node mergeSortedListRec(Node head1,Node head2){
            if(head1==null)return head2;
            if(head2==null)return head1;
            if(head1.value>head2.value){
                head2.next=mergeSortedListRec(head2.next,head1);
                return head2;
            }
            else{
                head1.next=mergeSortedListRec(head1.next,head2);
                return head1;
            }
        }
        //对单链表进行排序,归并排序,在排序里面不建议选用递归的合并有序链表算法,如果链表长度较长,很容易出现栈溢出
        public static Node listSort(Node head){
            Node nex=null;
            if(head==null||head.next==null)return head;
            else if(head.next.next==null){
                nex=head.next;
                head.next=null;
            }
            else{
                Node mid=getMiddleNode(head);
                nex=mid.next;
                mid.next=null;
            }
            return mergeSortedList(listSort(head),listSort(nex));//合并两个有序链表,不建议递归
        }
        //对单链表进行排序,插入排序
        public Node insertionSortList(Node head) {
            if(head==null||head.next==null)return head;
            Node pnex=head.next;
            Node pnex_nex=null;
            head.next=null;
            while(pnex!=null){
                pnex_nex=pnex.next;
                Node temp=head;
                Node temp_pre=null;
                while(temp!=null){
                    if(temp.value>pnex.value)break;
                    temp_pre=temp;
                    temp=temp.next;
                }
                if(temp_pre==null){
                    head=pnex;
                    pnex.next=temp;
                }
                else{
                    temp_pre.next=pnex;
                    pnex.next=temp;
                }
                pnex=pnex_nex;
            }
            return head;
        }
        //判断一个单链表中是否有环,快慢指针
        public static boolean hasCycle(Node head){
            boolean flag=false;
            Node p1=head;
            Node p2=head;
            while(p1!=null&&p2!=null){
                p1=p1.next;
                p2=p2.next.next;
                if(p2==p1){
                    flag=true;
                    break;
                }
            }
            return flag;
        }
        //判断两个单链表是否相交,如果相交返回第一个节点,否则返回null
        //如果单纯的判断是否相交,只需要看最后一个指针是否相等
        public static Node isIntersect(Node head1,Node head2){
            Node target=null;
            if(head1==null||head2==null)return target;
            int len1=getListLength(head1);
            int len2=getListLength(head2);
            if(len1>=len2){
                for(int i=0;i<len1-len2;i++){
                    head1=head1.next;
                }
            }else{
                for(int i=0;i<len2-len1;i++){
                    head2=head2.next;
                }
            }
            while(head1!=null&&head2!=null){
                if(head1==head2){
                    target=head1;
                    break;
                }
                else{
                    head1=head1.next;
                    head2=head2.next;
                }
            }
            return target;
        }
        //已知一个单链表中存在环,求进入环中的第一个节点,利用hashmap,不要用ArrayList,因为判断ArrayList是否包含某个元素的效率不高
        public static Node getFirstNodeInCycleHashMap(Node head){
            Node target=null;
            HashMap<Node,Boolean> map=new HashMap<Node,Boolean>();
            while(head!=null){
                if(map.containsKey(head))target=head;
                else{
                    map.put(head, true);
                }
                head=head.next;
            }
            return target;
        }
        //已知一个单链表中存在环,求进入环中的第一个节点,不用hashmap
        //用快慢指针,与判断一个单链表中是否有环一样,找到快慢指针第一次相交的节点,此时这个节点距离环开始节点的长度和链表投距离环开始的节点的长度相等
        public static Node getFirstNodeInCycle(Node head){
            Node fast=head;
            Node slow=head;
            while(fast!=null&&fast.next!=null){
                slow=slow.next;
                fast=fast.next.next;
                if(slow==fast)break;
            }
            if(fast==null||fast.next==null)return null;//判断是否包含环
            //相遇节点距离环开始节点的长度和链表投距离环开始的节点的长度相等
            slow=head;
            while(slow!=fast){
                slow=slow.next;
                fast=fast.next;
            }//同步走
            return slow;
            
        }
        //给出一单链表头指针head和一节点指针delete,O(1)时间复杂度删除节点delete
        //可惜采用将delete节点value值与它下个节点的值互换的方法,但是如果delete是最后一个节点,则不行,但是总得复杂度还是O(1)
        public static void deleteNode(Node head,Node delete){
            //首先处理delete节点为最后一个节点的情况
            if(delete==null)return;
            if(delete.next==null){
                if(head==delete)head=null;
                else{
                    Node temp=head;
                    while(temp.next!=delete){
                        temp=temp.next;
                    }
                    temp.next=null;
                }
            }
            else{
                delete.value=delete.next.value;
                delete.next=delete.next.next;
            }
            return;
        }
    }
  • 相关阅读:
    设计模式
    Junit单元测试
    数组存储和链表存储
    java新特型
    List&&Set
    Map
    File文件
    1588. 所有奇数长度子数组的和
    2秒后跳转到某页面
    图片轮播/倒计时--windows对象(setInterval)
  • 原文地址:https://www.cnblogs.com/zhoudi/p/5539506.html
Copyright © 2011-2022 走看看