单链表的Java实现(全方法)

本文详细介绍了一种单链表的Java实现方式,包括构造方法、数据存取、插入删除等核心操作,并提供了完整的源代码示例。通过实践加深了对数据结构原理的理解。

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

只有当自己去写一遍数据结构时,才能真正体会到其中的妙处,多思考数据结构的写法为什么不用其他的方式,有助于对代码的理解。
本文的注释较为详细,细节之处请看代码对应的注释。
/**
 * @title 单链表的Java实现
 * @author 未名
 * @date 2017-4-28
 * 
 * @implement 
 *      通过闭卷书写一遍,再与课本的写法对比、修改,加深了对数据结构的理解,提升了编码能力
 *      1、其中Node节点的有参构造方法可以为Node(data),或者为Node(data,next),在这里只用了第一种
 *      2、再链表类参数申明中,length和p是一个可选项。
 *          (1)若声明了length,需要在相应的方法中用到它,当方法较多时容易出错。
 *              若不声明,只用在size()方法中返回一个数值即可。本文采用了length
 *          (2)若声明了Node next= p,则在单链表的方法中不用新建变量,直接用统一的p,就不用每次写方法都新建节点变量
 *              若不声明,在每个方法中p的名字可以是front、rear等等,使用起来比较直观。本文采用此种方法
 *      3、在不同实现方法中,head 可以是节点,也可以只作为指针,本文采用后者   
 *      4、还有诸多细节之处需要自己写一遍才能体会,这里不做一一说明,有疑问欢迎留言交流
 */

package datastructure;

public class LinkedList<A> {
    public Node<A> head ;//该处为头指针,指向头结点(自己并非是头结点)
    //Node<A> p = head;//增加节点P来记录当前的节点位置
    private int length = 0;

//1、构造方法    
    public LinkedList(){    //构造空单链表
            this.head = new Node<A>();
    }

    public LinkedList(A[] val){
        this();   //调用无参构造方法,构造空链表
        Node<A> rear = this.head;
        for(int i=0;i<val.length;i++){
            rear.next = new Node<A>(val[i]);
            rear = rear.next;
            length++;
        }
    }

    public boolean isEmpty(){
        return this.head.next == null; //头结点为空时链表为空
    }

//2、数据存取    
    public A get(int index){   //下标越界返回null而不是返回异常
        Node<A> p = this.head.next;
        p = head ;
        if(index<0||p==null)
            return null;
        for(int i=0;i<=index&&p!=null;i++)
            p=p.next;   
        return p.data;
    }

    public void set(int i,A x){
        Node<A> p = this.head.next;
        for(int j=0;j<i;j++){
            p = p.next;
        }
        p.data = x;
    }

    public int size(){
        return length;
    }

    public String toString(){
        String s = this.getClass().getName()+"(";
        for(Node<A> p=this.head.next;p!=null;p=p.next){
            s+=p.data.toString();
            if(p.next!=null)
                s+=","; //不是最后一点时加分隔符
        }
        return s+")";
    }

//3、插入
    public Node<A> insert(int index,A data){
        if(data==null)
            throw new NullPointerException("data=null");
        Node<A> front = this.head;  //指向头指针,所以插入节点时就包括了插入到空表插入、头结点和中间节点及尾部节点的情况
//删除以下条件设置是因为index必须要容错,为防止超过上限,for循环中加条件front.next!=null
//      if(index>length||index<0)
//          return null;  //
        for(int i=0;i<index&&front.next!=null;i++){
            front = front.next; //最多只会指向最后一个节点
            }
        front.next = new Node<A>(data);
        length++;
        return front.next;
    }

    public Node<A> insert(A data){
        length++;
        return insert(length,data); //实际应为length-1,但是insert(,)具有容错性
    }

//4、删除          
    public A remove(int index){
        if(index>=length||index<0){
            return null;
        }else{
            Node<A> front = this.head;
            for(int i=0;i<index;i++){
                front = front.next;
            }
            A oldData = front.next.data;
            front = front.next.next;
            length--;
            return oldData;
        }
    }

    public A remove(){
        return remove(--length);  //删除尾部节点
    }

    public void clear(){
        this.head.next = null;  //Java自动回收
    }

//5、查找相关
    public Node<A> search(A key){   //查找第一个与key相等的元素
        Node<A> p = this.head.next;
        while(p!=null){
            if(p.data==key)
                break;
            p = p.next;
        }
        return p;
    }

    public boolean contains(A key){
        Node<A> p = search(key);
        if(p==null)
            return false;
        return true;    
    }

    public Node<A> insertDifferent(A x){
        if(contains(x))
            return null;
        return insert(x);
    }

    public A remove(A x){   //删除与x相等的元素
        Node<A> p=this.head.next;
        for(int i=0;p!=null;p=p.next,i++){
            if(p.data==x)
                return remove(i);   
        }
        return null;
    }
    //遍历所有元素,在这里其实与toString重复
    public void travelAll(){
        Node<A> p = head.next;
        System.out.println("All elements is:");
        while(p!=null){     //用while循环而不同for,减少中间变量的使用
            System.out.print(p.toString()+" ");
            p=p.next;
        }
    }
}

class Node<A> {
    protected A data;
    protected Node<A> next;

    public Node(){
        this.data = null;
    }

    public Node(A data){
        this.data = data;
        //this.next = next;
    }
    //输出存储数据信息
    public String toString(){
        return data.toString();
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值