Java_链表(方法大全)

package javaTest;
import java.util.*;
public class LinkList{
    public Node head;
    public Node current;
    //方法:向链表中添加数据
    public void add(int data){
        //判断链表为空
        if(head == null){ //若头结点为空,说明该链表未创建,把新的结点赋给头结点
            head = new Node(data);
            current = head;
        }else{
            //创建新的结点,放在当前结点的后面(把新的结点和链表进行关联)
            current.next = new Node(data);
            //把链表的当前索引向后移一位
            current = current.next; //此步结束后,current结点指向新添加的结点
        }
    }
    //方法重载:向链表中添加结点
    public void add(Node node){
        if(node == null){
            return;
        }
        if (head == null){
            head = node;
            current = head;
        }else{
            current.next = node;
            current = current.next;
        }
    }
    //方法:遍历链表
    public void print(Node node){
        if (node == null){
            return;
        }
        current = node;
        while(current != null){
            System.out.println(current.data);
            current = current.next;
        }
    }
    //方法:获取单链表的长度
    public int getLength(Node head){
        if(head == null){
            return 0;
        }
        int length = 0;
        Node current = head;
        while(current != null){
            length++;
            current = current.next;
        }
        return length;
    }
    //方法:查找单链表中的倒数第k个结点(时间复杂度为O(n))
    public Node findLastNode(Node head, int index){
        //第一次遍历,得到链表的长度size
        if(head == null){
            return null;
        }
        int size = 0;
        current = head;
        while (current != null){
            size++;
            current = current.next;
        }
        //第二次遍历,输出倒数第index个结点的数据
        current = head;
        for(int i = 0; i < size - index; i++){
            current = current.next;
        }
        return current;
    }
    public Node findLastNode2(Node head, int index){
        if(index == 0 || head == null){  //注意index为0的情况
            return null;
        }
        Node first = head;
        Node second = head;
        //让second结点往后挪k-1个位置
        for(int i = 0; i < index; i++){
            System.out.println("i的值是" + i);
            second = second.next;
            if (second == null){  //说明index的值大于链表的长度
                //我们自己抛出异常,以提醒用户
                // throw new NullPointerException("链表长度小于" + index);
                return null;
            }
        }
        //让first和second结点整体向后移动,直到second走到最后一个结点
        while(second != null){
            first = first.next;
            second = second.next;
        }
        //当second走到最后一个结点时,first结点就是我们要找的倒数第index个结点
        return first;
    }
    //方法:查找单链表中的中间节点
    public Node findMidNode(Node head){
        if (head == null){
            return null;
        }
        Node first = head;
        Node second = head;
        while (second != null && second.next != null){
            first = first.next;
            second = second.next.next;
        }
        //直到second结点移动到null时,此时first指针指向的位置就是中间结点的位置
        return first; 
        //当list的长度为偶数时,得到的中间结点是第(n/2+1)个
    }
    //方法:合并两个有序的单链表,合并之后的链表仍然有序
    public Node mergeLinkedList(Node head1, Node head2){
        if (head1 == null && head2 == null){
            return null;
        }
        if (head1 == null){
            return head2;
        }
        if (head2 == null){
            return head1;
        }
        Node head;  //新链表的头结点
        Node current;  //current结点指向新链表
        //一开始,我们让current结点指向head1和head2中较小的数据,得到head结点
        if (head1.data < head2.data){
            head = head1;
            current = head1;
            head1 = head1.next;
        }
        else{
            head = head2;
            current =head2;
            head2 = head2.next;
        }
        while(head1 != null && head2 != null){
            if (head1.data < head2.data){
                current.next = head1; //新链表中,current指针的下一个结点对应较小的那个数据
                current = current.next; //current指针下移
                head1 = head1.next;
            }
            else{
                current.next = head2;
                current = current.next;
                head2 = head2.next;
            }
        }
        if (head1 != null){ //说明链表2遍历完了,是空的
            current.next = head1;
        }
        if (head2 != null){ //说明链表1遍历完了,是空的
            current.next =head2;
        }
        return head;
    }
    //方法:单链表的反转
    public Node reverseList(Node head){
        //如果链表为空或者只有一个结点,无需反转,直接返回链表的头结点
        if (head == null || head.next == null){
            return head;
        }
        Node former = null;
        Node current = head;
        Node latter = null; //定义当前结点的的下一个结点
        while(current != null){
            latter = current.next;  //保存当前结点的下一个结点
            current.next = former;  //当前结点的下一个结点变为former结点
            former = current;  //former结点更新为当前结点
            current = latter; //current结点更新为之前保存的(原先的下一个结点)
        }
        return former;
    }
    //方法:从尾到头打印单链表
    public void reversePrint(Node head){
        //颠倒顺序,联想到栈,先进后出(时间复杂度O(n))
        if (head == null){
            return;
        }
        Stack<Node> stack = new Stack<Node>();  //新建一个栈
        Node current = head;
        while (current != null){
            stack.push(current);  //将当前结点压栈
            current = current.next;
        }
        while (stack.size() > 0){
            System.out.println(stack.pop().data);  //出栈操作
        }
    }
    public void reversePrint2(Node head){
        //使用系统的栈,递归
        if (head == null){
            return;
        }
        reversePrint2(head.next);
        System.out.println(head.data);
        //当链表很长的时候,会导致方法的调用层级很深,可能会造成栈溢出
    }
    //方法:判断单链表是否有环
    public boolean hasCycle(Node head){
        if (head == null){
            return false;
        }
        Node first = head;
        Node second = head;
        while (first != null && second != null && second.next != null){
            first = first.next;  //first指针走一步
            second = second.next.next;  //second指针走两步
            if (first == second){
                return true;
            }
        }
        return false;
    }
    //方法:判断单链表是否有环;返回的结点是相遇的那个结点
    public Node hasCycle2(Node head){
        if (head == null){
            return null;
        }
        Node first = head;
        Node second = head;
        while (first != null && second != null && second.next != null){
            first = first.next;  //first指针走一步
            second = second.next.next;  //second指针走两步
            if (first == second){
                return first;  //将相遇的节点返回
            }
        }
        return null;
    }
    //方法:有环链表中,获取环的长度,参数node代表的是相遇的那个结点
    public int getCycleLength(Node node){
        if (head == null){
            return 0;
        }
        Node current = node;
        // 该结点在环里,让该结点对应的指针一直往下走,直到回到原点
        int length = 0;
        // while (current.next != node){
        //     current = current.next;
        //     length++;
        // }
        // return (length+1);
        while (current != null){
            current = current.next;
            length++;
            if (current == node){
                return length;
            }
        }
        return length;
    }
    //方法:单链表中取出环的起始点
    //方法:判断两个单链表相交的一个交点
    public Node getFirstCommonNode(Node head1, Node head2){
        if (head1 == null || head2 == null){
            return null;
        }
        int length1 = getLength(head1);
        int length2 = getLength(head2);
        int lengthDif = 0; //两个链表长度的差值
        Node longHead;
        Node shortHead;
        //找出较长的链表
        if (length1 > length2){
            longHead = head1;
            shortHead = head2;
            lengthDif = length1 - length2;
        } else {
            longHead = head2;
            shortHead = head1;
            lengthDif = length2 - length1;
        }
        //将较长的那个链表的指针向前走lengthDif个距离
        for (int i = 0; i < lengthDif; i++){
            longHead = longHead.next;
        }
        //将两个链表的指针同时向前移动
        while (longHead != null && shortHead != null){
            if (longHead == shortHead){ //第一个相同的结点就是相交的第一个结点
                return longHead;
            }
            longHead = longHead.next;
            shortHead = shortHead.next;
        }
        return null;
    }
    //结点内部类
    class Node{  //内部类
        int data;  //数据域
        Node next;  //指针域
        public Node(int data){
            this.data = data;
        }
    }
    public static void main(String[] args){
        LinkList list = new LinkList();
        //向链表中添加数据
        for (int i = 0 ; i < 10; i++){
            list.add(i);
        }
        list.print(list.head); //从head结点开始遍历输出
        System.out.println("length of this list is " + list.getLength(list.head));
        System.out.println(list.hasCycle(list.head));
        System.out.println(list.findLastNode(list.head, 4).data);
        System.out.println(list.findLastNode2(list.head, 4).data);
        System.out.println(list.findMidNode(list.head).data);
        LinkList list2 = new LinkList();
        for(int j = 3; j < 8; j++){
            list2.add(j);
        }
        LinkList list3 = new LinkList();
        list3.head = list3.mergeLinkedList(list.head, list2.head);
        list3.print(list3.head);
        System.out.println("\n");
        LinkList list4 = new LinkList();
        list4.head = list3.reverseList(list3.head);
        list4.print(list4.head);
        System.out.println("\n");
        list4.reversePrint(list4.head);
        LinkList list5 = new LinkList();
        for (int k = 0; k < 4; k++){
            list5.add(k);
        }
        list5.add(list5.head); //将头结点添加到链表中,于是单链表就有环了
        System.out.println(list5.hasCycle(list5.head));
        Node thisNode = list5.hasCycle2(list5.head);
        System.out.println(thisNode.data);
        System.out.println(list5.getCycleLength(thisNode));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值