数据结构学习笔记——单链表

链表介绍

  • 链表(linked list)是一种在物理上非连续,非顺序的数据结构,由若干节点(node)组成
  • 单链表每一个节点又包含两部分,1是存放数据的变量data,2是存放指向下一个结点的指针next
  • 双向链表每一个节点包含三部分,在单链表的基础上多了一个指向前置节点的prev指针
  • 链表的第一个节点被称为头节点,最后一个节点被称为尾节点,尾结点的next指针指向null
  • 链表在内存中的存储方式为随机存储

时间复杂度

  • 不考虑插入,删除操作之前的查找元素的过程,只考虑插入和删除,时间复杂度为O(1)
  • 链表的查找从头结点开始,链表的长度越大,查找的时间越长,时间复杂度为O(n)

对比数组和链表

数组优势在于快速定位元素,对于读操作多,写操作少的场景,数组更合适
链表优势在于快速的插入和删除操作,如果频繁的在尾部删除和插入元素,用链表更好

单链表demo

package com.cc.node;

public class NodeDemo1 {
    //内部类,只能在内部访问使用
    private static class Node {
        int data;
        Node next;

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

    private Node head;
    private Node last;
    //链表的实际长度
    private int size;

    /**
     * 链表插入元素
     *
     * @param index
     * @param data
     * @throws Exception
     */
    public void insert(int index, int data) throws Exception {
        if (index < 0 || index > size) {
            throw new IndexOutOfBoundsException("超出链表的节点范围");
        }
        Node insertNode = new Node(data);
        //空链表
        if (size == 0) {
            head = insertNode;
            last = insertNode;
        } else if (index == 0) {
            //插入头部
            //分为两步:1.把新节点的next指针指向原head节点,2.把新节点变为链表的头节点
            insertNode.next = head;
            head = insertNode;
        } else if (index > 0 && index < size - 1) {
            //中间插入
            //分两步:1.把新节点的next指针指向插入位置的节点,2.插入位置的前置节点的next指针指向新节点
            Node prevNode = getNode(index - 1);//前置节点
            insertNode.next = prevNode.next;//新节点指向插入位置的节点
            prevNode.next = insertNode;//前置节点指向新节点

        } else {
            //插入尾部
            //分两步,1.最后一个节点的next指针指向新节点,2.把新节点指向尾部节点
            last.next = insertNode;
            last = insertNode;
        }
        //链表的长度加1
        size++;
    }

    /**
     * 删除链表中指定位置的节点
     *
     * @param index
     * @throws Exception
     */
    public void deleteNode(int index) throws Exception {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("超出链表的节点范围");
        }
        Node deleteNode = null;
        if (index == 0) {
            //头部删除节点
            //链表的头节点设为原先头节点的next指向的节点
            head = head.next;
        } else if (index > 0 && index < size - 1) {
            //删除中间的节点
            //插入位置的前一个节点,指向插入插入位置的下一个节点
            Node prevNode = getNode(index - 1);
            prevNode.next = prevNode.next.next;
        } else {
            //删除尾部节点
            //获取尾部的前一个节点,1.倒数第二个节点next指向空,2.尾节点指向倒数第二个节点
            Node prevNode = getNode(index - 1);
            prevNode.next = null;
            last = prevNode;
        }
        size--;
    }

    /**
     * 链表中查找指定位置的节点
     *
     * @param index
     * @return
     * @throws Exception
     */
    public Node getNode(int index) throws Exception {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("超出链表的节点范围");
        }
        //链表的查找从头节点开始
        Node temp = head;
        for (int i = 0; i < index; i++) {
            temp = temp.next;
        }
        return temp;
    }

    /**
     * 输出链表中的所有数据
     */
    public void outList() {
        Node temp = head;
        for (int i = 0; i < size; i++) {
            System.out.println(temp.data);
            temp = temp.next;
        }
    }

    public static void main(String[] args) throws Exception {
        NodeDemo1 linkedlist = new NodeDemo1();
        linkedlist.insert(0, 1);
        linkedlist.insert(1, 2);
        linkedlist.insert(2, 3);
        linkedlist.insert(3, 4);
        linkedlist.insert(4, 5);
        linkedlist.insert(5, 6);
        linkedlist.outList();
        linkedlist.deleteNode(5);
        linkedlist.outList();


    }
}

发布了35 篇原创文章 · 获赞 55 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/cchulu/article/details/105307673