java-单链表

来源:互联网 发布:机器人技术基础知乎 编辑:程序博客网 时间:2024/05/22 02:24

定义一个单链表,先定义一个节点,实现判断链表是否为空、在链表中插入节点(头插和尾插)、删除节点等操作

//定义节点class Node{    int value; //结点存放的值    Node next; //next域    public Node(){        this(0);  //this引用    }    Node(int value){        this.value = value;        this.next = null;    }}//定义单链表class LinkList{    Node head;  //头结点    LinkList next; //next域    public LinkList(){        head = new Node();    }    //判断链表是够否空    public boolean empty(){         return head.next == null;    }    //头插法    public void insertHead(int value){        Node n = new Node(value); //定义一个新节点        n.next = head.next; //将n插到头结点后        head.next = n;    }    //尾插法    public void insertTail(int value){        Node ptail = head; //将头结点赋予尾        while(ptail.next != null){            ptail = ptail.next;        } //找到单链表的尾部        ptail.next = new Node(value); //插入新节点    }    //删除值为value的节点    public void delete(int value){        Node pcur = head.next;         Node ppre = head;        while(pcur != null){            if(pcur.value == value){                  ppre.next = pcur.next;                break;            }            ppre = pcur;            pcur = pcur.next;        }    }    //自己实现toString的方法,利用StringBuilder//可以改变底层元素的值    public String toString(){        StringBuilder builder = new StringBuilder();        Node n = head.next;        while(n != null){            builder.append(n.value+" ");//插入值为value的节点            n = n.next;        }        return builder.toString();    }}

1.判断单链表是否有环:定义两个引用变量,慢变量slow,快变量fast,慢变量一次走1个节点,快变量一次走2个节点,当两个变量所指的值相等时退出循环

//判断当前单链表是否有环  true:有环  false:没有环public boolean haveCircle(){    Node slow = head;    Node fast = head;    while(fast != null && fast.next != null){        slow = slow.next;        fast = fast.next.next;        if(slow == fast){            return true;        }    }    return false;}

2.如果单链表有环,返回环的入口节点
先判断是否有环,若有环,将快引用fast移回到头结点,慢引用slow在它们的相交节点,同时向后移直至再次相交,相交节点就是入口节点
单链表返回环的入口
慢指针slow走到相遇点走了x+y,快指针走了x+y+(n-x-y)+y,而快指针走的距离是慢指针的两倍,即快指针走了2x+2y,所以2x+2y = x+y+(n-x-y)+y,即2x + y = n

public Node firstCircleNode(){    //碰撞点到连接点的距离 = 头指针到连接点的距离    if(this.haveCircle() == false){        return null;    }    else{        Node fast = this.head;        Node slow = this.head;        while(fast != null){            fast = fast.next.next;            slow = slow.next;            if(fast == slow){                break;            }        }        fast= head;        while(slow != fast){            slow = slow.next;            fast = fast.next;        }        return fast;    }}

3.寻找单链表的倒数第K个节点:
定义两个引用变量,第一个变量在正数第K个节点位置,第二个变量个在头部,然后两个变量一起遍历直至第一个变量走到尾部,然后返回第二个变量所指的节点
环的倒数第K个节点

public Node findReverseKNode(int k){    Node p1= head;    Node p2= head;    if(p1 == null || k < 1){        return null;    }    while(p1.next != null && k > 1){        p1 = p1.next;  //正数第k个        k--;    }    while(p1 != null){        p1 = p1.next;  // k = length - (length - k)        p2 = p2.next;    }    return p2;}

4.判断链表相交(只传入一个参数,另一个环引用此函数)
先求出两个链表的长度,然后让长链表先跑两个链表长度之差,接着两个链表一起向后遍历直至有值相等

public boolean isLinkCross(LinkList list){    if (!(this.haveCircle() || list.haveCircle())) {         int l1 = this.length();        int l2 = list.length();        int n;        Node p = this.head;        Node q = list.head;        if(l1 > l2){ //如果p是长链表,让p先走长度之差            n = l1 - l2;            for(int i=0;i<n;++i){                p = p.next;            }        }        else{ //如果q是长链表,让q先走长度之差            n = l2- l1;            for(int i=0;i<n;++i){                q = q.next;            }        }        while(p!=q && p.next != null){            p = p.next;            q = q.next;            if(p == q){                retern true;                break;            }    }    else if (this.HaveCircle()&&list.HaveCircle()) {              if (firstCircleNode() ==firstCircleNode()){                return true;                // 两个有环单链表,它们环的入口结点相同时,它们相交              }              else{                return false;              }            }      return false;}
原创粉丝点击