数据结构java(四)线性表 ②链式结构实现(单链表SingleLinkedList)

本文详细介绍了如何使用Java创建单链表的数据结构,包括结点Node类的定义、单链表结构的实现类SingleLinkedList以及测试类SingleLinkedListTest。内容涵盖了单链表的基本操作和实现原理。

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

1.创建单链表的结点Node类

/**
 * 单链表的结点
 * @author Administrator
 */
public class Node {
    /**
     * 要存储的数据
     */
    private Object data;

    /**
     * 后继
     */
    private Node next;


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


    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public Node getNext() {
        return next;
    }

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

    @Override
    public String toString() {
        return "Node{" +
                "data=" + data +
                ", next=" + next +
                '}';
    }
}

2.单链表结构的实现类(SingleLinkedList) 

/**
 * 单链表
 * @author Administrator
 */
public class SingleLinkedList implements List {
    /**
     * 头结点,不存储数据,为了编程方便
     */
    private Node head = new Node(null);

    /**
     * 一共几个结点
     */
    private int size;

    /**
     * 定义size方法,应返回size大小,最大值为Integer.MAX_VALUE
     *
     * @return
     */
    @Override
    public int size() {
        return size;
    }

    /**
     * List要求,定义get方法,获取指定index的值
     *
     * @param index
     * @return
     */
    @Override
    public Object get(int index) {
        //如果index位置错误,抛异常
        if (index<0 || index>=size){
            throw new MyArrayIndexOutOfBoundsException("数组越界异常:"+index);
        }

        //和顺序表不一样,不能通过索引直接计算定位,需要从头结点开始查找
        Node p = getNode(index);
        return p.getData();
    }

    /**
     * 定义isEmpty方法,用于返回是否为空
     * 如果不包含元素,则返回true
     *
     * @return
     */
    @Override
    public boolean isEmpty() {
        return size==0;
    }

    /**
     * 定义contains方法,判断一个e是否属于此集合
     * 如不是集合,则返回true
     *
     * @param e
     * @return
     */
    @Override
    public boolean contains(Object e) {
        return indexOf(e)>=0;
    }

    /**
     * 获取查询元素的index,若备查元素为null,则寻找空元素,返回index
     * 若备查元素不为null,则使用equal判断该元素是否存在,并返回index
     * 不存在则返回-1
     * 被contains调用
     *
     * @param e
     * @return
     */
    @Override
    public int indexOf(Object e) {
        if (e == null) {
            for (int i = 0; i < size; i++) {
                if (getNode(i).getData() == null) {
                    return i;
                }
            }
        } else {
            for (int i = 0; i < size; i++) {
                if (e.equals(getNode(i).getData())) {
                    return i;
                }
            }
        }
        return -1;
    }

    /**
     * 定义add方法,添加一个元素e,并返回添加成功标志
     *
     * @param e
     * @return
     */
    @Override
    public boolean add(Object e) {
        this.add(size,e);
        return true;
    }

    /**
     * 在指定位置插入指定元素在这个列表(可选操作)。变化的元素目前位置(如果有的话)和任何后续元素向右(添加一个索引)。
     *
     * @param index 指数要插入指定的元素
     * @param e     元素被插入
     */
    @Override
    public void add(int index, Object e) {
        //如果index位置错误,抛异常
        if (index<0 || index>size){
            throw new MyArrayIndexOutOfBoundsException("数组越界异常:"+index);
        }

        //查找前一个结点,从head结点开始
        Node p = getNode(index-1);
        //新创建一个结点
        Node newNode  = new Node(e);
        //指明新结点的直接后记
        newNode.setNext(p.getNext());
        //指明新结点的直接前驱结点
        p.setNext(newNode);
        //数量+1
        size++;
    }

    /**
     * 将元素e插入到元素object之前
     *
     * @param object 目标元素
     * @param e      元素被插入
     * @return
     */
    @Override
    public boolean addBefore(Object object, Object e) {
        int i = indexOf(object);
        if (i==-1){
            return false;
        }
        //添加操作
        add(i,e);
        return true;
    }

    /**
     * 将元素e插入到元素object之后
     *
     * @param object 目标元素
     * @param e      元素被插入
     * @return
     */
    @Override
    public boolean addAfter(Object object, Object e) {
        //目标元素的索引序号 -1说明无此元素
        int i = indexOf(object);
        if (i==-1){
            return false;
        }
        //添加操作
        add(i+1,e);
        return true;
    }

    /**
     * 这个列表中删除指定位置的元素(可选操作)。任何后续元素转移到左(减去一个来自他们的指标)。返回的元素从列表中删除。
     *
     * @param index 删除元素的索引
     * @return
     */
    @Override
    public Object remove(int index) {
        //如果index位置错误,抛异常
        if (index<0 || index>=size){
            throw new MyArrayIndexOutOfBoundsException("数组越界异常:"+index);
        }
        Node deleteNode = fastRemove(index);
        return deleteNode.getData();
    }

    /**
     * 线性表删除具体结点操作
     * @param index
     * @return
     */
    private Node fastRemove(int index) {
        //查找前一个结点,从head结点开始
        Node p = getNode(index - 1);
//        System.out.println("删除的结点前一个:"+p);
        //删除的结点
        Node deleteNode  = p.getNext();
//        System.out.println("删除的结点:"+deleteNode);
        //指明删除结点的后一个的直接前驱
        p.setNext(deleteNode.getNext());
        //删除结点置空
        deleteNode.setNext(null);
        //数量-1
        size--;
        return deleteNode;
    }

    /**
     * 定义remove方法,移除一个元素e,并返回移除元素成功标志
     *
     * @param e
     * @return
     */
    @Override
    public boolean remove(Object e) {
        //当前元素的索引序号 -1说明无此元素
        int i = indexOf(e);
        if (i==-1){
            return false;
        }
        //删除操作
        fastRemove(i);
        return true;
    }

    /**
     * 替换序号为index的元素为e 返回原元素
     *
     * @param index 序号
     * @param e     替换元素
     * @return 原元素
     */
    @Override
    public Object replace(int index, Object e) {
        //如果index位置错误,抛异常
        if (index<0 || index>=size){
            throw new MyArrayIndexOutOfBoundsException("数组越界异常:"+index);
        }
        //查找当前结点,从head结点开始
        Node p = getNode(index);
        //原结点数据
        Object data = p.getData();
        //修改
        p.setData(e);
        return data;
    }

    /**
     * 查找当前结点,从head结点开始
     * @param index
     * @return
     */
    private Node getNode(int index) {
        Node p = head;
        for (int j = 0;j<index+1;j++){
            p = p.getNext();
        }
        return p;
    }

    //[0,1,2,3,4,5]
    @Override
    public String toString() {
        if (size == 0){
            return "[]";
        }

        StringBuilder builder = new StringBuilder("[");
        Node p = head.getNext();

        for (int i = 0;i<size;i++){
            if (i!=size-1){
                builder.append(p.getData()+",");
            }else {
                builder.append(p.getData());
            }
            //移动到下一个结点
            p=p.getNext();
        }
        builder.append("]");

        return builder.toString() ;
    }
}

3.测试类(SingleLinkedListTest) 

/**
 * 单链表测试类
 * @author Administrator
 */
public class SingleLinkedListTest {
    private SingleLinkedList list;
    @Before
    public void setUp() throws Exception {
        list = new SingleLinkedList();
        list.add(1);
        list.add(2);
        list.add(null);
        list.add(4);
        list.add(5);
    }

    @Test
    public void add(){
        list.add(0,10);
        System.out.println(list.size());
        System.out.println(list.isEmpty());
        System.out.println(list);
    }

    @Test
    public void get(){
        Object o = list.get(0);
        System.out.println(o);
        String s = list.toString();
        System.out.println(s);
    }

    @Test
    public void remove() {
        System.out.println("删除前线性表:"+list);
        Object remove = list.remove(2);
        System.out.println(remove);
        System.out.println("删除后线性表:"+list);
    }
    @Test
    public void remove1() {
        System.out.println("删除前线性表:"+list);
        Object remove = list.remove(Integer.valueOf(6));
        System.out.println(remove);
        System.out.println("删除后线性表:"+list);
    }

    @Test
    public void replace(){
        Object replace = list.replace(3, 10);
        System.out.println(replace);
        System.out.println(list);
    }

    @Test
    public void indexOf(){
        int i = list.indexOf(1);
        System.out.println(i);
        System.out.println(list);
    }
    @Test
    public void contains(){
        boolean contains = list.contains(null);
        System.out.println(contains);
        System.out.println(list);
    }

    @Test
    public void addAfter() {
        System.out.println("操作前线性表:"+list);
        boolean b = list.addAfter(1, 99999);
        System.out.println(b);
        int size = list.size();
        System.out.println("元素个数="+size);
        System.out.println("操作后线性表:"+list);
    }

    @Test
    public void addBefore() {
        System.out.println("操作前线性表:"+list);
        boolean b = list.addBefore(1, 99999);
        System.out.println(b);
        int size = list.size();
        System.out.println("元素个数="+size);
        System.out.println("操作后线性表:"+list);
    }
}

下一篇:数据结构java(五)线性表 ②链式结构实现(双向链表LinkedList)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值