java 不带头结点的单链表实现(基本功能+reverse逆序+removeRange删除区间+lastIndex该元素最后出现的位置+add直接添加保证顺序)

2 篇文章 0 订阅
2 篇文章 0 订阅

目录

完整代码:

reverse逆序:

removerange删除区间:

lastindex该元素最后出现的位置:

add直接添加,保证顺序正确


完整代码:

package list;

import java.util.Iterator;

//不带头结点的单链表
@SuppressWarnings("all")
public class CLinkedList<T> implements Ilist<T>, Iterable<T>, Cloneable {
    /**
     * Node 内部类
     *
     * @param <T>
     */
    private static class Node<T> {
        // 注意和Itr类的比较,通过这个例子,应该能明白静态嵌套类和内部类的使用场合
        T data;
        Node<T> next;

        Node(T data, Node<T> next) {
            this.data = data;
            this.next = next;
        }

        public String toString() {//测试后面的tail有没有弄对
            return String.valueOf(data);
        }//测试用
    }

    private Node<T> head;
    private int size;

    public CLinkedList() {
        // head = null;
        // size = 0;
    }

    /**
     * isEmpty
     *
     * @return size == 0
     */
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * size
     *
     * @return size
     */
    public int size() {
        return size;
    }

    /**
     * indexOf x不能为null
     *
     * @param x
     * @return
     */
    public int indexOf(T x) {
        int index = 0;
        for (Node<T> p = head; p != null; p = p.next) {
            if (x.equals(p.data))
                return index;
            ++index;
        }
        return -1;
    }

    /**
     * indexOf1 数据就可以是null,x也可以是null
     *
     * @param x
     * @return
     */
    public int indexOf1(T x) {
        if (x == null) {
            int index = 0;
            for (Node<T> p = head; p != null; p = p.next) {
                if (p.data == null)
                    return index;
                ++index;
            }
        } else {
            int index = 0;
            for (Node<T> p = head; p != null; p = p.next) {
                if (x.equals(p.data))
                    return index;
                ++index;
            }
        }
        return -1;
    }

    // 可以这样写,但是,java类库用的前面的indexOf的写法,使用引用变量控制循环,不要用下面的写法
    public int indexOf2(T x) {
        Node<T> p = head;
        for (int index = 0; index < size; ++index) {
            if (x.equals(p.data))
                return index;
            p = p.next;
        }
        return -1;
    }

    // 可以用while,但是,看起来没有for容易理解,不要使用
    public int indexOf3(T x) {
        Node<T> p = head;
        int index = 0;
        while (p != null) {
            if (x.equals(p.data))
                return index;
            p = p.next;
            ++index;
        }
        return -1;
    }

    /**
     * 将索引号的合法性检查抽出作为方法
     *
     * @param index
     */
    private void rangCheckForAdd(int index) {// add用
        if (index < 0 || index > size)
            throw new IndexOutOfBoundsException(String.valueOf(index));
    }

    private void rangeCheck(int index) {// 其它方法用
        if (index < 0 || index > size - 1)
            throw new IndexOutOfBoundsException(String.valueOf(index));
    }

    /**
     * get
     *
     * @param index
     * @return
     */
    public T get(int index) {
        rangeCheck(index);
        Node<T> p = head;
        for (int i = 0; i < index; i++) // 找到结点index
            p = p.next;
        return p.data;
    }

    /**
     * add
     *
     * @param index
     * @param x
     */
    public void add(int index, T x) {
        rangCheckForAdd(index);
        if (index == 0) {// 空表,及插入位置0
            head = new Node<>(x, head);
        } else {
            Node<T> p = head;
            for (int i = 0; i < index - 1; i++) // 找到index的前驱
                p = p.next;
            p.next = new Node<>(x, p.next);
        }
        ++size;
    }

    /**
     * remove
     *
     * @param index
     * @return
     */
    public T remove(int index) {
        rangeCheck(index);
        Node<T> p = head;
        if (index == 0) {// 肯定不为空
            head = head.next;
        } else {// 至少有2个结点
            // 找到index的前驱
            for (int i = 0; i < index - 1; i++)
                p = p.next;
            Node<T> q = p;
            p = p.next;
            q.next = p.next;
        }
        // p引用待删除结点
        T value = p.data;
        p.data = null;// 帮助GC
        p.next = null;
        --size;
        return value;
    }

    /**
     * reverse
     */
    public void reverse() {//逆序
        if (head == null || head.next == null) return;
        Node<T> p = head.next;//先指到第2个节点
        head.next = null;//把第一个节点断开
        while (p != null) {
            Node<T> q = p.next;//后移
            //将p插入头结点之后
            p.next = head;
            head = p;
            p = q;//继续访问下一个元素
        }
    }

    /**
     * removeRange
     *
     * @param from
     * @param to
     */
    public void removeRange(int from, int to) {
        rangeCheck(from);
        rangeCheck(to);//检查index
        Node<T> from_h = head;
        Node<T> to_b = head;
        Node<T> p = head;//帮助GC的指针
        if (from == 0) {//from在开头的情况
            for (int i = 0; i < to + 1; i++) {
                p = to_b.next;
                to_b = null;
                to_b = p;
            }
            head = to_b;
        } else {//一般情况
            for (int i = 0; i < to + 1; i++) {
                if (i < from - 1) {
                    from_h = from_h.next;
                }
                p = to_b.next;
                to_b = null;
                to_b = p;
            }
            from_h.next = to_b;
        }
        size = size - (to - from + 1);//更改size
    }

    /**
     * lastIndex
     *
     * @param x
     * @return
     */
    public int lastIndex(T x) {
        Node<T> p = head;
        int index = -1;
        int i = 0;
        while (p != null) {
            if (p.data.equals(x)) {
                index = i;
            }
            i++;
            p = p.next;
        }
        return index;
    }

    /**
     * add
     *
     * @param x
     */
    public void add(T x) {
        Comparable<? super T> tmp = (Comparable<? super T>) x;
        if (size == 0) {//空表情况,及插入位置0
            head = new Node<>(x, head);
        } else {//非空表情况
            Node<T> p = head;
            Node<T> temp = head;
            int i;
            for (i = 0; i < size; i++) {
                if (tmp.compareTo((T) p.data) < 0)
                    break;
                p = p.next;
            }
            if (i==0){//第一个位置的情况
                head=new Node<>(x,head);
            }else {//普通情况
                p=head;
                for (int j = 0; j < i-1; j++) {
                    p=p.next;
                }
                p.next=new Node<>(x, p.next);
            }
        }

        ++size;//调整size
    }

    /**
     * clear
     */
    public void clear() {
        while (head != null) {// 从第1个结点开始,逐个删除
            Node<T> q = head;// q待删除结点
            head = head.next;// 下一个结点

            q.data = null;// 帮助GC
            q.next = null;
        }
        size = 0;
    }

    public String toString() {
        StringBuilder str = new StringBuilder();
        for (T elem : this)// 利用了实现了的迭代器
            str.append(elem + "  ");
        return str.toString();
    }

    public boolean equals(Object obj) {
        if (this == obj)
            return true;

        if (obj instanceof CLinkedList<?>) {
            CLinkedList<?> rhd = (CLinkedList<?>) obj;
            if (this.size != rhd.size)
                return false;
            for (Node<?> p = head, q = rhd.head; p != null; p = p.next, q = q.next) {
                if (!p.data.equals(q.data))
                    return false;
            }
            return true;
        }
        return false;
    }

    public int hashCode() {
        int result = 1;
        for (Node<T> p = head; p != null; p = p.next)
            result = result * 31 + p.data.hashCode();
        return result;
    }

    @SuppressWarnings("unchecked")
    private CLinkedList<T> superClone() {
        try {
            return (CLinkedList<T>) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e);
        }
    }

    public Object clone() {
        CLinkedList<T> v = superClone();// v的head和size与this的head和size相同
        if (v.head == null)// 空链表
            return v;
        // 为v分配新的结点,不能与this共用
        v.head = new Node<>(head.data, null);
        for (Node<T> p = head.next, q = v.head; p != null; p = p.next, q = q.next)
            q.next = new Node<>(p.data, null);
        return v;
    }

    public Iterator<T> iterator() {
        return new Itr();
    }

    private class Itr implements Iterator<T> {// 注意Itr是内部类,而 Node是静态的嵌套类
        private Node<T> currentNode;

        public Itr() {
            currentNode = head;
        }

        public boolean hasNext() {
            return currentNode != null;
        }

        public T next() {
            T data = currentNode.data;
            currentNode = currentNode.next;
            return data;
        }

    }

    
}

reverse逆序:

/**
     * reverse
     */
    public void reverse() {//逆序
        if (head == null || head.next == null) return;
        Node<T> p = head.next;//先指到第2个节点
        head.next = null;//把第一个节点断开
        while (p != null) {
            Node<T> q = p.next;//后移
            //将p插入头结点之后
            p.next = head;
            head = p;
            p = q;//继续访问下一个元素
        }
    }

removerange删除区间:

/**
     * removeRange
     *
     * @param from
     * @param to
     */
    public void removeRange(int from, int to) {
        rangeCheck(from);
        rangeCheck(to);//检查index
        Node<T> from_h = head;
        Node<T> to_b = head;
        Node<T> p = head;//帮助GC的指针
        if (from == 0) {//from在开头的情况
            for (int i = 0; i < to + 1; i++) {
                p = to_b.next;
                to_b = null;
                to_b = p;
            }
            head = to_b;
        } else {//一般情况
            for (int i = 0; i < to + 1; i++) {
                if (i < from - 1) {
                    from_h = from_h.next;
                }
                p = to_b.next;
                to_b = null;
                to_b = p;
            }
            from_h.next = to_b;
        }
        size = size - (to - from + 1);//更改size
    }

1. 检查from,to

2. 注意帮助GC,清空内存

3. 找到from的前驱节点指向to的后继节点即可

4. 删除注意更改size

lastindex该元素最后出现的位置:

/**
     * lastIndex
     *
     * @param x
     * @return
     */
    public int lastIndex(T x) {
        Node<T> p = head;
        int index = -1;
        int i = 0;
        while (p != null) {
            if (p.data.equals(x)) {
                index = i;
            }
            i++;
            p = p.next;
        }
        return index;
    }

额.........找到返回即可

add直接添加,保证顺序正确

/**
     * add
     *
     * @param x
     */
    public void add(T x) {
        Comparable<? super T> tmp = (Comparable<? super T>) x;
        if (size == 0) {//空表情况,及插入位置0
            head = new Node<>(x, head);
        } else {//非空表情况
            Node<T> p = head;
            Node<T> temp = head;
            int i;
            for (i = 0; i < size; i++) {
                if (tmp.compareTo((T) p.data) < 0)
                    break;
                p = p.next;
            }
            if (i==0){//第一个位置的情况
                head=new Node<>(x,head);
            }else {//普通情况
                p=head;
                for (int j = 0; j < i-1; j++) {
                    p=p.next;
                }
                p.next=new Node<>(x, p.next);
            }
        }

        ++size;//调整size
    }

1. 空表直接加入

2. compare找到位置

3. 找到前驱节点,使前驱节点指向该新建节点,该新建节点指向原前驱节点的next

4. 注意插入的位置

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值