java-----单链表

Posted 小鹿可可乐

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java-----单链表相关的知识,希望对你有一定的参考价值。

单链表

1.单链表基本操作

链表是一个有序的列表
链表不同于数组,链表是以结点的形式存储,在物理空间上不一定连续
链表的每个结点的内部包含value(数据)域,next(指针)域,指针域指向下一个结点的位置

1.1代码

public class SingleLink<E extends Comparable<E>> implements List<E> 
    private Node<E> head;
    private Node<E> tail;//尾部  尾插的时间复杂度O(1)
    private int size;

    public SingleLink()
        this.head = null;//空链表
        this.tail = null;
    

    @Override
    public void addHead(E value) //O(1)
        Node<E> node = new Node<>(value);
        if(head ==null && tail == null)
            head = node;
            tail = node;
        else 

            //新节点的next = head
            node.next = head;
        
        //更新新头节点位置
        head = node;
        size++;
    

    @Override
    public void addTail(E value) //O(1)
        //申请value节点
        Node<E> node = new Node<>(value);
        if(head==null )//链表不存在有效节点
            head = node;
            tail = node;//唯一node    既是头又是尾
        else
            tail.next = node;
        
        size++;
    


    @Override
    public void removeHead() 
        if(head ==null)
            return;
        
        else if(size==1)//head.next = null 只有一个节点
            tail=null;
        
            head.value=null;
            Node<E> p = head.next;//p只保存地址
            head.next=null;
            head=p;
            size--;

    

    @Override
    public void removeTail() 
        if(head == null)//链表为空
            return;
        else if(size == 1)//一个节点
            head.value=null;
            head=null;
            tail = null;
        else//>=两个节点
            //找链表尾巴前趋
            Node<E> p =head;
            for(;p.next.next==null;p=p.next)
                ;
            
                p.next = null;
                tail.value = null;//防止内存泄漏
                tail = p;//更新尾巴指向
        
        size--;
    

    @Override
    public void removeValue(E value) 
        if(head == null)
            return;
        else if(head.value.compareTo(value) == 0)
            removeHead();
        else
            //找待删节点的前驱
            Node<E> p= head;
            for(;p.next.value.compareTo(value) != 0;p = p.next)
                ;
            
            Node<E> q = p.next.next;
            p.next.value = null;//防止内存泄漏
            //p.next=q.next;
            //q.next=null;q.value=null;
            p.next.next = null;
            p.next = q;
            size--;
        

    

    @Override
    public boolean contains(E value) 
        for(Node<E> p = head;p!=null;p = p.next)
            if(p.value.compareTo(value) == 0)
                return true;
            
        
        return false;
    

    @Override
    public void change(E srcValue, E aimValue) 
        for(Node<E> p = head;p!=null;p = p.next) 
            if (p.value.compareTo(srcValue) == 0) 
                p.value = aimValue;
            
        
    

    @Override
    public void show()
        for(Node<E> p = head;p!=null;p=p.next)
            System.out.print(p.value+" ");
        
        System.out.println();
    

    public Node<E> getHead() 
        return head;
    

    public void setHead(Node<E> head) 
        this.head = head;
    

    public void setTail(Node<E> tail) 
        this.tail = tail;
    

    public Node<E> getTail() 
        return tail;
    

    public int getSize() 
        return size;
    

    public void setSize(int size) 
        this.size = size;
    

    //Node类型
    //当前类里边this以外,不用包含外部类对象引用
     static class Node<T>
        T value;
        Node<T> next;

        public Node(T value) 
            this.value = value;
        
    



2.单链表练习题

2.1 逆置单链表

/*
    一、逆置单链表
     */
    public void reverseLink()
        if(head == null || size == 1)
            return;
        
        Node<E> p=head;
        Node<E> q=p.next;
        Node<E> s=q.next;
        head.next=null;//原来头节点->尾巴节点
        while(q != null)
            q.next=p;
            p = q;
            q = s;
            if(s!=null) 
                s = s.next;
            
        
        tail = head;//新尾巴用原来head更新
        head = p;//循环结束  p标志的使新头

    

2.2 假设两个链表相交,输出相交节点

 //二、假设两个链表相交,输出相交节点
    public Node<E> getMeetNode(SingleLinkTest<E> link)
        //1.让长链表走差值步,长短链表一起向后遍历,
        int curSize = size;
        int linkSize = link.size;
        int diff = curSize-linkSize;
        Node<E> longLinkP = diff > 0 ? head : link.head;//longLinkP遍历长链表
        Node<E> shortLinkP = diff > 0 ? link.head : head;
        //长链表遍历差值步
        diff = Math.abs(diff);//取绝对值
        while(diff>0)
            longLinkP = longLinkP.next;
            diff--;
        
        while(longLinkP != shortLinkP)
            longLinkP = longLinkP.next;
            shortLinkP = shortLinkP.next;
        
        return longLinkP;
    

2.3 给定一个链表,删除指定节点,O(1)时间复杂度删除指定节点

//三、给定一个链表,删除指定节点,O(1)时间复杂度删除指定节点
    public static <E extends Comparable<E>>boolean removeNode(SingleLink<E> link,SingleLink.Node node)
        //参数安全检测
        if(link == null || node == null)
            return false;
        
        if(node == link.getTail())
            link.removeTail();
        else
            node.value = node.next.value;//将当前节点node,下一个节点value赋值给当前节点
            node.next = node.next.next;//删除node的下一个节点
        
        link.setSize(link.getSize()-1);//size--
        return false;
    

2.4两个有序单链表合并为一个有序单链表


    //四、两个有序单链表合并为一个有序单链表
    public void mergeLink(SingleLinkTest<E> link)//this   link
        if(link == null || head == null && link.head == null)
            return;
        
        if(this.head == null)
            this.head = link.head;
            this.tail = link.tail;
        

        Node<E> p = this.head,q = link.head;
        //this.head 更新  两个链表开始的头部value,谁小谁作为起始
        this.head = this.head.value.compareTo(link.head.value)<0 ? this.head:link.head;
        if(p == head)
            p = p.next;
        else
            q = q.next;
        
        Node<E> s = head;//新链表尾部  连接动作
        while(p != null && q != null)
            if(p.value.compareTo(q.value) < 0)
                s.next = p;
                p = p.next;
            else
                s.next = q;
                s = q;//更新到链表尾巴
                q = q.next;
            
        
        if(p == null)
            q = q.next;
        else
            p = p.next;
        

        while(s.next != null)
            s = s.next;
        
        this.tail = s;

    

2.5 判断链表是否有环,并输出相交节点

 //五、判断链表是否有环,并输出相交节点
    private Node<E> isLoop0()
        Node<E> fast = head,slow = head;
        do
            if(fast == null || fast.next == null)
                return null;
            
            fast = fast.next.next;
            slow = fast.next;

        while(fast != slow);
            return fast;

    

    public boolean isLoop()
       return !(isLoop0() == null);
    

    //环的入口点
    public Node<E> loopNode()
        Node<E> fast = isLoop0();//获得相遇点
        Node<E> p = head,q = fast;
        while(p != q)
            p = p.next;
            q = q.next;
        
        return p;
    

今天也要好好学习呀~

以上是关于java-----单链表的主要内容,如果未能解决你的问题,请参考以下文章

java-----单链表

java-----单链表

java单链表的实现自己动手写一个单链表

(java实现)单链表

Java实现单链表(步骤详解+源码)

Day553.单链表 -数据结构和算法Java