单链表及单链表的基本操作

这篇博客介绍了如何使用Java实现单链表的基本操作,包括头增、尾增、头删、尾删、删值,以及解决链表相交、寻找倒数第k个节点、链表逆置、环判断等复杂问题。通过`Entry`类和`Link`类的定义,展示了链表数据结构的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package com.tulun.src07;

/**

  • @author Richard
  • @date 2019/9/14 0014-14:50
  • 头增
  • 尾增
  • 头删
  • 尾删
  • 删值
  • 两个链表相交,输出相交节点
  • 输出单链表的倒数第k个节点
  • 单链表的逆置
  • 判断一个单链表是否有环,输出相遇节点
  • 输出环的入口节点:当前链表的入口节点

*/

class Entry<T extends Comparable>{
private T value;
private Entry next;
public Entry(T value){
this.value=value;
}

public T getValue() {
    return value;
}

public void setValue(T value) {
    this.value = value;
}

public Entry getNext() {
    return next;
}

public void setNext(Entry next) {
    this.next = next;
}

}
public class Link<T extends Comparable> {
private Entry headEntry;
private Entry tailEntry;

public Link() {
    headEntry = null;
    tailEntry = null;
}

public Entry<T> getEntry(T value) {
    for (Entry p = headEntry; p != null; p = p.getNext()) {
        if (p.getValue().compareTo(value) == 0) {
            return p;
        }
    }
    return null;
}

public void addHead(T value) {
    Entry<T> newEntry = new Entry<>(value);
    //当原链表为空链表时
    if (headEntry == null) {
        headEntry = newEntry;
        tailEntry = newEntry;
        return;
    } else {//当原链表有一个及以上节点时
        headEntry = newEntry.getNext();//newEntry.setNext(headEntry);
        headEntry=newEntry;

    }
}
public void addTail(T value){
    Entry<T> newEntry=new Entry<>(value);
    //当原链表为空链表时
    if (headEntry==null){
        headEntry=newEntry;
        tailEntry=newEntry;
        return;
    }else{//当原链表不为空链表时
        tailEntry.setNext(newEntry);
        tailEntry=newEntry;
        //Entry p=null;
        //for (p=headEntry;p.getNext()!=null;p=p.getNext());
        //p.setNext(newEntry);
    }
}
public void removeHead(){
    //当原链表为空链表
    if (headEntry==null){//该处可以使用异常,后续实现
        System.out.println("该链表为空链表,无法删除");
        return;
    }else if (headEntry.getNext()==null){//当链表只有一个节点时
        headEntry=null;
        tailEntry=null;
        return;
    }else{//当链表有大于1个节点时
        headEntry.setValue(null);//防止内存泄漏
        headEntry=headEntry.getNext();
    }
}
public void removeTail(){
    //当原链表为空链表时
    if (headEntry==null){
        System.out.println("原链表为空链表,无法删除!");
        return;
    }else if (headEntry.getNext()==null){//当原链表只有一个节点时
        headEntry=null;
        tailEntry=null;
        return;
    }else{//当原链表含有大一1个节点
        tailEntry.setValue(null);//防止内存泄漏
        Entry<T> priorTailEntry=null;
        for (priorTailEntry=headEntry;priorTailEntry.getNext().getNext()!=null;priorTailEntry=priorTailEntry.getNext());
        priorTailEntry.setNext(null);
        tailEntry=priorTailEntry;
    }
}
public void removeValue(T value){
    if (headEntry==null){//当原链表为空链表时
        System.out.println("该链表为空链表,无法删除");
        return;
    }else if (headEntry.getValue().compareTo(value)==0){//若头节点为所要删除的节点
        headEntry.setValue(null);
        //headEntry.setNext(null);此处为错误代码,需谨记
        headEntry=headEntry.getNext();
        if (tailEntry==headEntry){
            tailEntry=null;
        }
        return;
    }else{
        for(Entry<T> entry=headEntry;entry.getNext()!=null;entry=entry.getNext()){
            if (entry.getNext().getValue().compareTo(value)==0){
                entry.getNext().setValue(null);
                entry.setNext(entry.getNext().getNext());

            }
        }

    }
}
private int getLength(){
    int count=0;
    for (Entry<T> entry=headEntry;entry!=null;entry=entry.getNext()){
        count++;
    }
    return count;
}
//两个链表相交,输出相交节点的value值
public static<T extends Comparable<T>> T getMeetEntryValue(Link<T> link1,Link<T> link2){
    //1,统计出链表的长度
    int length1=link1.getLength();
    int length2=link2.getLength();
    int different=Math.abs(length1-length2);//两个链表的长度差

    //2,长链表先走差值步
    Entry<T> longLinkEntry=length1>length2?link1.headEntry:link2.headEntry;
    Entry<T> shortLinkEntry=length1<length2?link1.headEntry:link2.headEntry;
    for (;--different>=0;longLinkEntry=longLinkEntry.getNext());

    //3,长短链表同时向后走,直到long==short
    for (;longLinkEntry!=null;longLinkEntry=longLinkEntry.getNext(),shortLinkEntry=shortLinkEntry.getNext()){
        if (longLinkEntry==shortLinkEntry){
            return longLinkEntry.getValue();
        }
    }
    return null;
}
//输出倒数第K个节点
public static<T extends Comparable<T>> T showDK(Link<T> link,int k){
    if (k<0 || k>link.getLength()){
        return null;
    }
    Entry<T> p=link.headEntry;
    Entry<T> q=link.headEntry;
    for (;--k>=0;p=p.getNext());//p先走k步
    for (;p!=null;p=p.getNext(),q=q.getNext());//p和q同时走,当p==null时,q的位置就为倒数第k个节点
    return q.getValue();
}
//单链表逆置
public static<T extends Comparable<T>> void reverse(Link<T> link){
    if (link.getLength()==1){
        return;
    }
    Entry<T> p=link.headEntry;
    Entry<T> q=p.getNext();
    Entry<T> s=q.getNext();
    while (q!=null){
        q.setNext(p);
        p=q;
        q=s;
        if (s!=null){
            s.getNext();
        }

    }
    link.tailEntry=link.headEntry;
    link.headEntry=p;
    link.tailEntry.setNext(null);
}
//判断一个单链表是否有环,输出相遇节点
public Entry<T> isCircle(){
    Entry<T> fast=headEntry;
    Entry<T> slow=headEntry;
    do {
        if (fast==null || fast.getNext()==null){
            return null;
        }
        fast=fast.getNext().getNext();
        slow=slow.getNext();
    }while (fast!=slow);
    return slow;
}
//输出环的入口节点:当前链表的入口节点
public Entry<T> getCircleMeetEntry(){
    Entry<T> meet=isCircle();
    if (meet==null){
        return null;
    }
    Entry<T> p=headEntry;
    Entry<T> q=meet;
    while (p!=q){
        p=p.getNext();
        q=q.getNext();
    }
    return p;
}
//两个有序单链表合并成一个有序单链表
public Entry<T> mergeLink(Link<T> link){
    if (link==null || link.headEntry==null){
        return this.headEntry;
    }
    Entry<T> p1=this.headEntry;
    Entry<T> p2=link.headEntry;
    //新链表头&&新链表尾巴
    Entry<T> newHeadEntry=p1.getValue().compareTo(p2.getValue())>0?p2:p1;
    Entry<T> newTailEntry=newHeadEntry;
    if (newHeadEntry==p1){
        p1=p1.getNext();
    }else{
        p2=p2.getNext();
    }
    //比较p1和p2的值,值小的连接在链表尾部
    while (p1!=null && p2!=null){
        if (p1.getValue().compareTo(p2.getValue())<0){
            tailEntry.setNext(p1);
            newTailEntry=p1;//p1节点作为新链表的尾巴
            p1=p1.getNext();
        }else{
            tailEntry.setNext(p2);
            newTailEntry=p2;
            p2=p2.getNext();
        }
    }
    //p1走完,p1==null
    if (p1==null){
        tailEntry.setNext(p2);
    }
    //p2走完,p2==null
    if (p2==null){
        tailEntry.setNext(p1);
    }
    return newHeadEntry;
}
public void show(){
    for(Entry<T> entry=headEntry;entry!=null;entry=entry.getNext()){
        System.out.print(entry.getValue()+"  ");
    }
    System.out.println();
}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值