学习记录 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;
    }
}
时间: 2024-08-15 19:42:18

学习记录 java 链表知识的相关文章

学习记录 java 值类型和引用类型的知识

1. Java中值类型和引用类型的不同? [定义] 引用类型表示你操作的数据是同一个,也就是说当你传一个参数给另一个方法时,你在另一个方法中改变这个变量的值, 那么调用这个方法是传入的变量的值也将改变.值类型表示复制一个当前变量传给方法, 当你在这个方法中改变这个变量的值时,最初生命的变量的值不会变.通俗说法: 值类型就是现金,要用直接用:引用类型是存折,要用还得先去银行取现.----(摘自网上) [值类型] 也就是基本数据类型 基本数据类型常被称为四类八种 四类: 1,整型 2,浮点型 3,字

JVM学习记录-Java内存模型(二)

对于volatile型变量的特殊规则 关键字volatile可以说是Java虚拟机提供的最轻量级的同步机制. 在处理多线程数据竞争问题时,不仅仅是可以使用synchronized关键字来实现,使用volatile也可以实现. Java内存模型对volatitle专门定义了一些特殊的访问规则,当一个变量被定义为volatile时,它将具备以下两个特性: 第一个是保证此变量对所有线程的可见性,这里的“可见性”是指当一条线程修改了这个变量的值,新值对于其他线程来说是可以立即得知的.而普通变量不能做到这

学习记录 java session保存用户登录

1 <%@ page language="java" contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%> 3 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"&g

学习记录 java 哈希

哈希表(Hash Table,又叫散列表),是存储键值对(Key-value)的表,之所以不叫它Map(键值对一起存储一般叫做Map),是因为它下面的特性:它能把关键码(key)映射到表中的一个位置来直接访问,这样访问速度就非常快.其中的映射函数称为散列函数(Hash function). 1) 对于关键字key, f(key)是其存储位置,f则是散列函数 2) 如果key1 != key2 但是 f(key1) == f(key2),这种现象称为冲突(collison).冲突不可避免,这是因为

STL学习记录:链表

直接百度链表的话,其实和真正用起来的STL链表差的挺远的(毕竟有些情况能用就行~),还是自己写一下记录一下STL里链表具体用法吧 #include <bits/stdc++.h> using namespace std; int main () { //1. 定义 //list<数据类型> 链表名称 list<int> test; list<int>::iterator iter=test.begin(); //2. 增删改查 //增加 test.push_

学习记录 java随机数的产生机制

java 随机数 一.在j2se里我们可以使用Math.random()方法来产生一个随机数,这个产生的随机数是0-1之间的一个double,我们可以把他乘以一定的数,比如说乘以100,他就是个100以内的随机,这个在j2me中没有. 二.在java.util这个包里面提供了一个Random的类,我们可以新建一个Random的对象来产生随机数,他可以产生随机整数.随机float.随机double,随机long,这个也是我们在j2me的程序里经常用的一个取随机数的方法. 三.在我们的System类

我的学习记录-JAVA SE 04

(三)流程语句 3.控制循环结构 1)break * 在switch语句中,用来终止一个语句序列. * 用于退出一个循环,使用break语句直接抢修退出循环,忽略循环体中任何其他语句和循环条件测试. * 在循环中遇到break语句时,循环被终止,程序控制在循环后面的语句重新开始. 实例: package day4; import java.util.Scanner; public class Exam_1 { public static void main(String[] args) { //

我的学习记录-JAVA SE 01

一.大纲 一.IT和计算机 1.IT的前世今生 第五代       DT时代 2.操作系统和平台的相关性 1)OS所处位置: 2)unix家族 3)windows家族 3.windows常用快捷键/命令 二.计算机很二 1.太极和八怪 1)太极 2)八卦 3)六十四卦 2.进制概述 进制也就是进位制,是人们规定的一种进位方法. 对于任何一种进制---X进制,就表示某一位置上的数运算时是逢X进一位. 十进制是逢十进一,十六进制是逢十六进一,二进制就是逢二进一,以此类推,x进制就是逢x进位. 1)二

学习记录 java泛型资料

java泛型资料: 1. 概述在引入范型之前,Java类型分为原始类型.复杂类型,其中复杂类型分为数组和类.引入范型后,一个复杂类型就可以在细分成更多的类型.例如原先的类型List,现在在细分成List<Object>, List<String>等更多的类型.注意,现在List<Object>, List<String>是两种不同的类型,他们之间没有继承关系,即使String继承了Object.下面的代码是非法的    List<String>