数据结构 -- 单链表

一、概述

链式存储结构实现的顺序表,增删快,查找慢。

二、节点类

2.1 API设计

类名 Node
构造方法 Node(T t,Node next):创建Node对象
成员变量 T item:存储数据
Node next:指向下一个结点

2.2 实现

public class Node<T> {
    
    
    //存储元素
    public T item;
    //指向下一个结点
    public Node next;

    public Node(T item, Node next) {
    
    
        this.item = item;
        this.next = next;
    }
}

三、单向链表

3.1 API设计

类名 LinkList
构造方法 LinkList():创建LinkList对象
成员方法 1.public void clear():空置线性表
2.publicboolean isEmpty():判断线性表是否为空,是返回true,否返回false
3.public int length():获取线性表中元素的个数
4.public T get(int i):读取并返回线性表中的第i个元素的值
5.public void insert(T t):往线性表中添加一个元素;
6.public void insert(int i,T t):在线性表的第i个元素之前插入一个值为t的数据元素。
7.public T remove(int i):删除并返回线性表中第i个数据元素。
8.public int indexOf(T t):返回线性表中首次出现的指定的数据元素的位序号,若不存在,则返回-1。
成员内部类 private class Node:结点类
成员变量 1.private Node head:记录首结点
2.private int N:记录链表的长度

3.2 实现

public class LinkList<T> implements Iterable<T> {
    
    

    // 记录头节点
    private Node head;
    // 记录链表的长度
    private int N;

    //结点类
    private class Node {
    
    
        //存储数据
        T item;
        //下一个结点
        Node next;

        public Node(T item, Node next) {
    
    
            this.item = item;
            this.next = next;
        }
    }

    public LinkList() {
    
    
        // 初始化头节点
        head = new Node(null, null);
        N = 0;
    }

    // 清空链表
    public void clear() {
    
    
        head.next = null;
        head.item = null;
        N = 0;
    }

    // 获取链表长度
    public int length() {
    
    
        return N;
    }

    // 判断链表是否为空
    public boolean isEmpty() {
    
    
        return N == 0;
    }

    // 获取指定位置i处的元素
    public T get(int i) {
    
    
        if (i < 0 || i >= N) {
    
    
            throw new RuntimeException("位置不合法!");
        }
        Node n = head.next;
        for (int index = 0; index < i; index++) {
    
    
            n = n.next;
        }
        return n.item;
    }

    // 向链表中添加元素t
    public void insert(T t) {
    
    
        // 找到最后一个节点
        Node n = head;
        while (n.next != null) {
    
    
            n = n.next;
        }
        Node newNode = new Node(t, null);
        n.next = newNode;
        // 链表长度+1
        N++;
    }

    // 向指定位置i处,添加元素t
    public void insert(int i, T t) {
    
    
        if (i < 0 || i > N) {
    
    
            throw new RuntimeException("位置不合法!");
        }

        // 寻找位置i之前的节点
        Node pre = head;
        for (int index = 0; index <= i - 1; index++) {
    
    
            pre = pre.next;
        }

        // 位置i的节点
        Node curr = pre.next;

        // 构建新的节点,让新的节点指向位置i的节点
        Node newNode = new Node(t, curr);

        // 让之前的节点指向新节点
        pre.next = newNode;

        // 长度+1
        N++;
    }

    // 删除指定位置i的元素,并返回被删除的元素
    public T remove(int i) {
    
    
        if (i < 0 || i >= N) {
    
    
            throw new RuntimeException("位置不合法!");
        }

        // 寻找i之前的元素
        Node pre = head;
        for (int index = 0; i <= i-1; index++) {
    
    
            pre = pre.next;
        }

        // 当前i位置的节点
        Node curr = pre.next;

        // i之前的节点指向下一个节点,删除当前节点
        pre.next = curr.next;

        // 长度-1
        N--;
        return curr.item;
    }

    // 查找元素t在链表中第一次出现的位置
    public int indexOf(T t){
    
    
        Node n = head;
        for(int i = 0;n.next!=null;i++){
    
    
            n = n.next;
            if (n.item.equals(t)){
    
    
                return i;
            }
        }
        return -1;
    }

    @Override
    public Iterator<T> iterator() {
    
    
        return new LIterator();
    }

    private class LIterator implements Iterator<T>{
    
    
        private Node n;

        public LIterator(){
    
    
            this.n = head;
        }

        @Override
        public boolean hasNext() {
    
    
            return n.next!=null;
        }

        @Override
        public T next() {
    
    
            n = n.next;
            return n.item;
        }
    }

}

3.3 测试

public class LinkListTest {
    
    
    public static void main(String[] args) {
    
    
        LinkList<String> list = new LinkList<>();
        list.insert(0, "张三");
        list.insert(1, "李四");
        list.insert(2, "王五");
        list.insert(3, "赵六");
        //测试length方法
        for (String s : list) {
    
    
            System.out.println(s);
        }
        System.out.println(list.length());
        System.out.println("-------------------");
        //测试get方法
        System.out.println(list.get(2));
        System.out.println("------------------------");
        //测试remove方法
        String remove = list.remove(1);
        System.out.println(remove);
        System.out.println(list.length());
        System.out.println("----------------");
        for (String s : list) {
    
    
            System.out.println(s);
        }
    }
}

三、单链表反转

    // 链表反转
    public void reverse(){
    
    
        if (N==0){
    
    
            return;
        }
        reverse(head.next);
    }

    // 反转链表中的某个节点curr,并把反转后的curr节点返回
    public Node reverse(Node curr){
    
    
        // 已经到了最后一个元素
        if (curr.next==null){
    
     // 递归出口
            // 反转后,头节点应该指向原链表中的最后一个元素
            head.next=curr;
            return curr;
        }
        // 递归反转当前节点curr的下一个节点
        Node pre = reverse(curr.next);
        // 让返回节点的下一个节点变为当前节点curr
        pre.next = curr;
        // 当前节点的下一个节点设为null
        curr.next = null;
        // 返回当前节点
        return curr;
    }

おすすめ

転載: blog.csdn.net/m0_46218511/article/details/117928231