数据结构|链表及Java实现

线性表-链表

1. 原理

在这里插入图片描述
把结点看成对象,对象中有两个属性:

  1. 这个结点中装的元素;
  2. 下个结点的位置(指向下个结点对象的引用)。
class Node {
	int val;		// 保存元素
	Node next;		// 保存指向下一个结点的引用;其中尾结点的 next == null
}

我们通过链表的头结点,来代表一整条链表。

2. 链表的常见操作

2.1 链表的结点定义

public class Node {
    public String val;
    public Node prev;
    public Node next;

    public Node(String val){
        this.val = val;
    }

    @Override
    public String toString() {
        return "Node{" + "val=" + val  + "}";
    }
}

2.2 链表的手工创建

Node n1 = new Node("1");
Node n3 = new Node("2");
Node n2 = new Node("4");
Node n6 = new Node("6");

n1.next = n3;
n3.next = n2;
n2.next = n6;
n6.next = null;

Node head = n1;

创建一个空链表

Node head = null;

2.3 链表的遍历

Node cur = head;
while (cur != null) {
    System.out.println(cur.val);
    cur = cur.next;
}

2.4 链表的元素插入和删除

给定前驱结点后的插入

Node prev = ...;	// 给定结点的前驱结点
Node node = new Node("v");

node.next = prev.next;
prev.next = node;

给定前驱节点后的删除

Node prev = ...;	// 待删除的结点的前驱节点
prev.next = prev.next.next;

头插

private static Node pushFront(Node head, String v){
    Node node = new Node(v);
    node.next = head;
    head = node;
    return head;
}

头删

private static Node popFront(Node head){
    if (head == null){
        throw new RuntimeException("链表为空");
    }
    
    head = head.next;
    return head;
}

尾插

private static Node pushBack(Node head, String v){
    if (head == null){
        Node node = new Node(v);
        return node;
    }
    
    Node last = head;
    while (last.next != null){
        last = last.next;
    }
    
    Node node = new Node(v);
    last.next = node;
    return head;
}

尾删

private static Node popBack(Node head){
    if (head == null){
        throw new RuntimeException("链表为空");
    }
    
    if (head.next == null){
        return null;
    }
    
    Node last2 = head;
    while (last2.next.next != null){
        last2 = last2.next;
    }
    last2.next = null;
    return head;
}

3. Java中的链表 - LinkedList

  1. LinkedList 实现了 List 接口,LinkedList 具备的方法,等同于 LIst 具备的方法;
  2. Java 中的链表,不再使用头结点来代替边表,而是定义了一个链表类来表示链表;
  3. Java 中的链表采用的是一种双向链表;
  4. Java 中的链表既保存了链表的头结点,也保存了尾结点。

4. 实现自己的LinkedList - MyLinkedList

public class Node {
    public String val;
    public Node prev;
    public Node next;

    public Node(String val){
        this.val = val;
    }

    @Override
    public String toString() {
        return "Node{" + "val=" + val  + "}";
    }

}

public class MyLinkedList {
    private Node head;
    private Node last;
    private int size;

    public MyLinkedList(){
        head = null;
        last = null;
        size = 0;
    }

    public boolean add(String e){
        Node node = new Node(e);
        if (head == null){
            head = last= node;
        }else {
            node.prev = last;
            last.next = node;
            last = node;
        }
        size++;
        return true;

    }

    public void add(int index, String e){
        if (index < 0 || index > size){
            throw new ArrayIndexOutOfBoundsException();
        }

        if (head == null){
            Node node = new Node(e);
            head = last = node;
        }else if (index == 0){
            Node node = new Node(e);
            node.next = head;
            head.prev = node;
            head = node;
        }else if (index == size){
            Node node = new Node(e);
            last.next = node;
            node.prev = last;
            last = node;
        }else {
            Node node = new Node(e);
            Node pre = head;
            for (int i = 0; i < index - 1; i++){
                pre = pre.next;
            }
            Node next = pre.next;
            pre.next = node;
            next.prev = pre;
            node.next = next;
            next.prev = node;
        }
        size++;
    }

    public String remove(int index){
        if (index < 0 || index >= size){
            throw new ArrayIndexOutOfBoundsException();
        }
        String e;
        if (size == 1){
            e = head.val;
            head = last = null;
        }else if (index == 0){
            e = head.val;
            head = head.next;
            head.prev = null;
        }else if (index == size - 1){
            e = last.val;
            last = last.prev;
            last.next = null;
        }else {
            Node toDelete = head;
            for (int i = 0; i < index; i++){
                toDelete = toDelete.next;
            }
            e = toDelete.val;
            Node pre = toDelete.prev;
            Node next = toDelete.next;

            pre.next = next;
            next.prev = pre;
        }
        size--;
        return e;
    }

    boolean remove(String e){
        int i = indexOf(e);
        if (i < 0){
            return false;
        }
        remove(i);
        return true;
    }

    public String get(int index){
        if (index < 0 || index >= size){
            throw new ArrayIndexOutOfBoundsException();
        }
        Node findNode = head;
        for (int i = 0; i < index; i++){
            findNode = findNode.next;
        }
        return findNode.val;
    }

    public String set(int index, String e){
        if (index < 0 || index >= size){
            throw new ArrayIndexOutOfBoundsException();
        }
        Node setNode = head;
        for (int i = 0; i < index; i++){
            setNode = setNode.next;
        }
        setNode.val = e;
        return e;
    }

    public boolean contains(String e){
        return indexOf(e) > 0;
    }

    public int indexOf(String e){
        int i = 0;
        for (Node cur = head; cur != null; cur = cur.next){
            if (cur.val.equals(e)){
                return i;
            }
            i++;
        }
        return -1;
    }

    public int lastIndexOf(String e){
        int i = size - 1;
        for (Node cur = last; cur != null; cur = cur.prev){
            if (cur.val.equals(e)){
                return i;
            }
            i--;
        }
        return -1;
    }

    public void clear(){
        head = last = null;
        size = 0;
    }

    public int size(){
        return size;
    }

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

    @Override
    public String toString() {
        StringBuilder stringBuilder = new StringBuilder("[");
        Node cur = head;
        while (cur != null){
            stringBuilder.append(cur.val);
            if (cur.next  != null){
                stringBuilder.append(",");
            }
            cur = cur.next;
        }
        stringBuilder.append("]");
        return stringBuilder.toString();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值