用java实现单链表的各种操作:

单链表的结构如下:

//定义一个单链表,内部类
    private class Node {
        private int data;
        private Node next;
        public Node() {}
        public Node(int data) {
            this.data = data;
        }
    }

具体代码如下:

package lianbiao;


//java中的LinkedList由双链表组成,这里使用单链表
public class MyLinkedList {
    private Node head = null;
    //定义一个单链表,内部类
    private class Node {
        private int data;
        private Node next;
        public Node() {}
        public Node(int data) {
            this.data = data;
        }
    }

1.增加到链表尾部

public void add(int data) {
        Node node = new Node(data);
        if(head == null) {
            head = node;
            return;
        }
        Node tmp = head;
        while (tmp.next != null) {
            tmp = tmp.next;
        }
        tmp.next = node;
    }

2.删除第i个元素

public boolean delete(int index) {
        if(index < 1 || index > length()) {
            System.out.println("您输入的索引有误,不再范围内");
            return false;
        }
        if(index == 1) {
            head = head.next;
            return true;
        }
        int i = 2;
        Node cur = head;
        while (cur != null) {
            if(i == index) {
                cur.next = cur.next.next;
                break;
            }
            i++;
            cur = cur.next;

        }
        return true;
    }

3.计算该链表的长度

//计算该链表的长度
    public int length() {
        int count = 0;
        Node cur = head;
        while (cur != null) {
            count++;
            cur = cur.next;
        }
        return count;
    }

4.对该链表进行排序

//对该链表进行排序
    public void oderList() {
        if(length() <= 1) {
            return;
        }
        Node cur = head;
        Node nextNode = null;
        int temp = 0;
        while (cur.next != null) {
            nextNode = cur.next;
            while (nextNode != null) {
                if(cur.data > nextNode.data) {
                    temp = cur.data;
                    cur.data = nextNode.data;
                    nextNode.data = temp;
                }
                nextNode = nextNode.next;
            }
            cur = cur.next;
        }
    }

5.删除单链表中的重复元素

//删除单链表中的重复元素
    public void deleteDuplecate() {
        Node p = head;
        while (p != null) {
            Node q = p;
            while (q.next != null) {
                if (q.data == p.next.data) {
                    q.next = q.next.next;
                }else {
                    q = q.next;
                }
            }
            p = p.next;
        }
    }

6.打印该链表

//打印该链表
    public void printList() {
        Node cur = head;
        while (cur != null) {
            System.out.print(cur.data+",");
            cur = cur.next;
        }
        System.out.println();
    }

7.找出单链表的倒数第k个元素

//找出单链表的倒数第k个元素:
    //思路:设置两个指针,让两个指针相差k-1个位置,当一个指针到达最后一个位置的时候,我们就能找到倒数第K个位置
    public Node findElem(int k) {
        if(k < 1) {
            return null;
        }
        Node p1 = head;
        Node p2 = head;
        for(int i=0; i< k-1 && p1 != null; i++) {
            p1 = p1.next;
        }
        if(p1 == null) {
            System.out.println("k不合法");
            return null;
        }
        while (p1.next != null) {
            p1 = p1.next;
            p2 = p2.next;
        }
        return p2;
    }

8.实现链表的反转,并返回反转链表以后的头结点

//实现链表的反转,并返回反转链表以后的头结点:
    public void reverse() {
        Node ReverseHead = head;
        Node pNode = head;
        Node pPrev = null;

        //核心四步骤:
        //Node pNext = pNode.next;
        //pNode.next = pPrev;
        //pPrev = pNode;
        //pNode = pNext;
        //循环指针为pNode,直到它为空
        while (pNode != null) {
            Node pNext = pNode.next;
            //保证链表中所有的节点都进行了反转,并讲最后一个节点保存下来并赋值给ReverseHead
            if(pNext == null) {
                ReverseHead = pNode;
            }
            pNode.next = pPrev;
            pPrev = pNode;
            pNode = pNext;

        }
        //最后将该链表的头结点进行反转
        this.head = ReverseHead;
    }

9.如何从尾到头输出链表中的元素

//如何从尾到头输出链表中的元素
    public void printListReverse(Node head) {
        if(head != null) {
            printListReverse(head.next);
            System.out.println(head.data);
        }
    }

10.寻找单链表的中间节点

//寻找单链表的中间节点:设置快慢节点,当快节点到达末尾是慢节点所指向的就是中间节点
    public Node searchMid() {
          Node fast = this.head;
          Node slow = this.head;
          while (fast != null && fast.next != null && fast.next.next != null) {
              fast = fast.next.next;
              slow = slow.next;
          }
          return slow;
    }

11.如何检测一个链表是否有环

//如何检测一个链表是否有环
    public boolean isLoop() {
        Node fast = this.head;
        Node slow = this.head;
        if(fast == null) {
            return false;
        }
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow) {
                return true;
            }
        }
        return false;
    }

12.查找有环链表的环的入口

//查找有环链表的环的入口
    public Node finLoopPort() {
        Node slow = head;
        Node fast = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.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;
    }

13.如何在不知道头指针的情况下删除指定指针

//如何在不知道头指针的情况下删除指定指针
    public boolean deleteNode(Node node) {
        //这种方式无法删除链表的尾节点和空接点
        if(node == null || node.next == null) {
            return false;
        }
        int tmp = node.data;
        node.data = node.next.data;
        node.next = node.next.next;
        return true;
    }

14.判断两个链表是否相交:只考虑无环链表

//判断两个链表是否相交:只考虑无环链表
    public  boolean isIntersect(Node head1, Node head2) {
        if(head1 == null || head2 == null) {
            return false;
        }
        //找到链表head1的尾节点
        Node tail1 = head1;
        while (tail1.next != null) {
            tail1 = tail1.next;
        }
        //找到head2的尾节点
        Node tail2 = head2;
        while (tail2.next != null) {
            tail2 = tail2.next;
        }
        return tail1 == tail2;
    }

15.如果两个链表相交,则如何找到相交的节点

//如果两个链表相交,则如何找到相交的节点
    public Node getFirstMeetNode(Node head1, Node head2) {
        if(head1 == null || head2 ==null) {
            return null;
        }
        Node tail1 = head1;
        int len1 = 1;
        while (tail1.next != null) {
            tail1 = tail1.next;
            len1++;
        }
        Node tail2 = head2;
        int len2 = 1;
        while (tail2.next != null) {
            tail2 = tail2.next;
            len2++;
        }
        //如果两链表不相交,则直接返回null
        if(tail1 != tail2) {
            return null;
        }
        //设置两个指针,使其句交点相同的位置开始往后遍历,直到二者相遇,即就是交点的位置
        Node t1 = head1;
        Node t2 = head2;
        //找出较长的链表
        if(len1 > len2) {
            int d = len1-len2;
            while (d != 0) {
                t1 = t1.next;
                d--;
            }
        }else {
            int d = len2-len1;
            while (d != 0) {
                t2 = t2.next;
                d--;
            }
        }
        while (t1 != t2) {
            t1 = t1.next;
            t2 = t2.next;
        }
        return t1;
    }

以下对上述的方法进行测试代码

//以下对上述的方法进行测试
    public static void main(String[] args) {
        MyLinkedList list = new MyLinkedList();
        list.add(5);
        list.add(1);
        list.add(3);
        list.add(6);
        list.add(20);
        list.add(9);
        list.printList();
        list.delete(3);
        list.delete(3);
        list.delete(3);
        System.out.println("删除三个元素之后:");
        list.printList();
        list.oderList();
        System.out.println("排序后:");
        list.printList();
        //验证findElemm(int k)的方法是否正确
        list.add(10);
        list.add(7);
        list.add(6);
        list.printList();
        Node p3 = list.findElem(1);
        Node p4 = list.findElem(3);
        Node p5 = list.findElem(2);
        System.out.println("倒数第一个数为:"+p3.data);
        System.out.println("倒数第三个数为:"+p4.data);
        System.out.println("倒数第二个数为:"+p5.data);
        System.out.println("输出当前链表中的所有元素");
        list.printList();
        list.reverse();
        System.out.println("输出链表进行翻转以后的元素");
        list.printList();
        System.out.println("从尾到头输出元素");
        list.printListReverse(list.head);
    }

}