数据结构-链表

学习目标:

链表的只是

学习内容:

1、 创建结点 2、 添加结点 3、 删除结点 4、 其他操作 5、 使用链表实现队列

学习时间:

2021年7月10日

学习产出:

1、 技术笔记 1 遍 2、CSDN 技术博客 1 篇 3、 练习题若干

前面学习的线性数据结构:1.动态数组 2.栈 3.队列

底层都是依托静态数组:靠resize解决固定容量的问题

今天学习的链表是真正的动态数据结构

链表

数据存储在结点(Node)中

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f5UukT16-1629082253479)(E:\Users\asus\AppData\Roaming\Typora\typora-user-images\1629079867322.png)]

优点:不需要处理固定容量的问题,真正的动态

缺点:丧失了随机访问的能力

创建Node

	// 结点的数据结构
    private class Node {
        private T val; // 数据内容
        private Node next; // 指向下个结点的引用

        Node(T val) {
            this.val = val;
            this.next = null;
        }

        @Override
        public String toString() {
            return val.toString();
        }
    }
	// 构建链表
    private Node head; // 头结点
    private int size; // 链表中结点的个数

    public MyLink() {
        head = null;
    }

添加结点

关键点:找到要添加结点的前一个结点

	// 在任意位置插入,增加虚拟头结点
    public void add(T val, int index) {
        if (index > this.size || index < 0) {
            throw new IllegalArgumentException("index是错误的!");
        }
        //使用虚拟头结点
        Node dummyHead = new Node(null);
        //要插入的结点
        Node node = new Node(val);
        dummyHead.next = head;
        //找到要添加结点的前一个结点
        Node preNode = dummyHead;
        for (int i = 0; i < index; i++) {
            preNode = preNode.next;
        }
        node.next = preNode.next;
        preNode.next = node;
        // 更新size
        this.size++;
        // 更新head
        head = dummyHead.next;
    }

	// 在尾部添加结点
    public void addLast(T val) {
        add(val, this.size);
    }

    // 在头添加结点
    public void addFirst(T val) {
        add(val, 0);
    }

删除结点

	//根据索引删除
    public T remove(int index) {
        if (index >= this.size || index < 0) {
            throw new IllegalArgumentException("index是错误的!");
        }
        Node dummyHead = new Node(null);
        dummyHead.next = head;
        Node preNode = dummyHead;
        for (int i = 0; i < index; i++) {
            preNode = preNode.next;
        }
        Node delNode = preNode.next;
        T result = delNode.val;
        preNode.next = delNode.next;
        delNode.next = null;
        this.size--;
        head = dummyHead.next;
        return result;
    }

    // 删除头结点
    public T removeFirst() {
        return remove(0);
    }

    // 删除尾结点
    public T removeLast() {
        return remove(this.size - 1);
    }

    // 根据内容删除
    public Node remove(T val) {
        Node dummyHead = new Node(null);
        dummyHead.next = head;
        Node preNode = dummyHead;
        while (preNode.next != null) {
            T result = preNode.next.val;
            if (result.equals(val)) {
                //删除
                Node delNode = preNode.next;
                preNode.next = delNode.next;
                delNode.next = null;
                this.size--;
            } else {
                preNode = preNode.next;
            }
        }
        return dummyHead.next;
    }

其他操作

    public MyLink() {
        head = null;
    }

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

    // 获取链表中结点的个数
    public int getSize() {
        return this.size;
    }

    // 获取指定索引的结点信息
    public T get(int index) {
        if (index > this.size || index < 0) {
            throw new IllegalArgumentException("index是错误的!");
        }
        Node curNode = head;
        for (int i = 0; i < index; i++) {
            curNode = curNode.next;
        }
        return curNode.val;
    }

    // 获取头结点
    public T getFirst() {
        return get(0);
    }

    // 获取尾结点
    public T getLast() {
        return get(this.size - 1);
    }

@Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        Node cur = head;
        while (cur != null) {
            sb.append(cur + "-->");
            cur = cur.next;
        }
        return sb.toString();
    }

    // 判断链表中是否包含指定的元素
    public boolean contains(T val) {
        Node curNode = head;
        while (curNode != null && !curNode.val.equals(val)) {
            curNode = curNode.next;
        }
        return curNode != null;
    }

    // 根据索引更新链表中的结点内容
    public void set(int index, T val) {
        if (index >= this.size || index < 0) {
            throw new IllegalArgumentException("index是错误的!");
        }
        Node curNode = head;
        for (int i = 0; i < index; i++) {
            curNode = curNode.next;
        }
        curNode.val = val;
    }

测试

public static void main(String[] args) {
        int count = 10;
        Random random = new Random();
        MyLink<Integer> myLink = new MyLink<>();
        for (int i = 0; i < count; i++) {
            myLink.addFirst(random.nextInt(100));
        }
        System.out.println(myLink);
        System.out.println("在尾部的位置插入");
        myLink.addLast(random.nextInt(100));
        System.out.println(myLink);
        System.out.println("在头部的位置插入");
        myLink.addFirst(random.nextInt(100));
        System.out.println(myLink);
        System.out.println("获取头部结点" + myLink.getFirst());
        System.out.println("获取尾部结点" + myLink.getLast());
        System.out.println("获取索引为3的结点" + myLink.get(3));
        System.out.println("总共有多少个结点" + myLink.getSize());
        System.out.println("判断15是否存在?" + myLink.contains(15));
        System.out.println("更新索引为10的元素为99");
        myLink.set(10, 99);
        System.out.println(myLink);
        System.out.println("删除head");
        myLink.removeFirst();
        System.out.println(myLink);
        System.out.println("删除tail");
        myLink.removeLast();
        System.out.println(myLink);
        System.out.println("删除索引为2");
        myLink.remove(2);
        System.out.println(myLink);

    }

使用链表实现队列

public class LinkedQueue<T> implements Queue<T> {
    private MyLink<T> data;

    public LinkedQueue() {
        data = new MyLink<>();
    }

    @Override
    public int getSize() {
        return data.getSize();
    }

    @Override
    public boolean isEmpty() {
        return data.isEmpty();
    }

    @Override
    public void enqueue(T ele) {
        data.addLast(ele);
    }

    @Override
    public T dequeue() {
        return data.removeFirst();
    }

    @Override
    public T getFront() {
        return data.getFirst();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值