线性表的四种数据结构——The Four Data Structures of Linear Tables

 

主函数(Main) 

package com.test;

import com.test.collection.ArrayList;

import com.test.collection.LinkedList;

import com.test.collection.Stack;

import com.test.collection.Queue;

public class Main {
    public static void main(String[] args) {}

}

1. 顺序表(Array List)

顺序表是一种基于数组实现的数据结构,元素在内存中连续存储。

主要功能:

  • 插入和删除:在指定位置插入或删除元素,时间复杂度为 O(n),因为需要移动其他元素。
  • 访问元素:通过索引直接访问元素,时间复杂度为 O(1)
  • 动态扩展:当数组容量不足时,可以动态扩展数组大小
适用类型:
  1. 频繁随机访问:需要频繁按索引访问元素的场景。
  2. 元素数量固定或可预测:元素数量相对固定或可以预测,不需要频繁插入/删除操作。
  3. 内存使用紧凑:内存使用较为紧凑,不需要额外的指针开销。

         


package com.test.collection;

public class ArrayList<E> {
    int size = 0;
    private int capacity = 10;
    private Object[] array = new Object[capacity];

    public void add(E element, int index) {
        if (index < 0 || index > size)
            throw new IndexOutOfBoundsException("插入位置非法,合法的插入位置为:0~" + size);

        // 如果当前容量不足,进行扩容
        if (size == capacity) {
            resize();
        }

        // 将元素插入到指定位置,并移动后续元素
        for (int i = size; i > index; i--) {
            array[i] = array[i - 1];
        }
        array[index] = element;
        size++;
    }

    private void resize() {
        capacity *= 2;// 扩容
        Object[] newArray = new Object[capacity];// 创建新的数组
        System.arraycopy(array, 0, newArray, 0, size);// 复制元素到新数组
        array = newArray;// 指向新数组
    }

    public String toString() {
        System.out.println("ArrayList size: " + size);
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < size; i++) {
            builder.append(array[i]).append(" ");
        }
        return builder.toString().trim();
    }
    @SuppressWarnings("unchecked")
    public E remove(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("删除位置非法,合法的删除位置为:0~" + (size - 1));
        }
        E e = (E) array[index];
        for (int i = index; i < size - 1; i++) {
            array[i] = array[i + 1];
        }
        array[size - 1] = null; // 清除最后一个元素
        size--; // 更新 size
        return e; // 返回被删除的元素
    }
    public  E get(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("获取位置非法,合法的获取位置为:0~" + (size - 1));
        }
        return (E) array[index];
    }
    public boolean isEmpty() {
        return size == 0;
    }
}




2. 链表(Linked List)

链表是一种基于节点和指针实现的数据结构,元素在内存中不连续存储。

主要功能:

  • 插入和删除:在指定位置插入或删除元素,时间复杂度为 O(1)(在已知节点的情况下)。
  • 访问元素:需要从头节点开始遍历,时间复杂度为 O(n)。
  • 动态扩展:无需预先分配固定大小,可以动态添加或删除节点。
适用类型
  1. 频繁插入/删除:需要频繁在中间位置插入或删除元素的场景。
  2. 元素数量不固定:元素数量不固定或难以预测,需要动态调整大小的场景。
  3. 内存使用灵活:内存使用较为灵活,不需要连续的内存空间。

 

示例代码(sample code):

public class LinkedList<E> {
    private Node<E> head;
    private int size;

    private static class Node<E> {
        E element;
        Node<E> next;

        Node(E element) {
            this.element = element;
        }
    }

    public void add(E element) {
        Node<E> newNode = new Node<>(element);
        if (head == null) {
            head = newNode;
        } else {
            Node<E> current = head;
            while (current.next != null) {
                current = current.next;
            }
            current.next = newNode;
        }
        size++;
    }

    public E get(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException();
        }
        Node<E> current = head;
        for (int i = 0; i < index; i++) {
            current = current.next;
        }
        return current.element;
    }

    public void remove(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException();
        }
        if (index == 0) {
            head = head.next;
        } else {
            Node<E> current = head;
            for (int i = 0; i < index - 1; i++) {
                current = current.next;
            }
            current.next = current.next.next;
        }
        size--;
    }
}

3. 栈(Stack)

栈是一种后进先出(LIFO)的数据结构。栈的主要操作包括压栈(push)、弹栈(pop)和查看栈顶元素(peek)。

主要功能:

  • 压栈(push):将元素添加到栈顶。
  • 弹栈(pop):移除并返回栈顶元素。
  • 查看栈顶元素(peek):返回栈顶元素但不移除。
  • 判空(isEmpty):检查栈是否为空。

适用类型:

  1. 函数调用和递归:栈在函数调用和递归中非常有用,因为函数调用和返回的过程本质上就是压栈和弹栈的过程。
  2. 表达式求值:栈可以用于中缀表达式转换为后缀表达式,以及后缀表达式的求值。
  3. 撤销操作:在文本编辑器或图形软件中,撤销操作通常使用栈来实现,每次修改操作都压入栈中,撤销时弹出栈顶操作。
  4. 浏览器历史记录:浏览器的前进和后退功能可以使用两个栈来实现,一个用于前进,一个用于后退。
  5. 括号匹配:栈可以用于检查括号是否匹配,例如检查表达式中的括号是否正确闭合。

 

示例代码(sample code):

public class Stack<E> {
    private Node<E> top;
    private int size;

    private static class Node<E> {
        E element;
        Node<E> next;

        Node(E element) {
            this.element = element;
        }
    }

    public void push(E element) {
        Node<E> newNode = new Node<>(element);
        newNode.next = top;
        top = newNode;
        size++;
    }

    public E pop() {
        if (isEmpty()) {
            throw new IllegalStateException("Stack is empty");
        }
        E element = top.element;
        top = top.next;
        size--;
        return element;
    }

    public E peek() {
        if (isEmpty()) {
            throw new IllegalStateException("Stack is empty");
        }
        return top.element;
    }

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

4. 队列(Queue)

队列是一种先进先出(FIFO)的数据结构。队列的主要操作包括入队(enqueue)、出队(dequeue)和查看队头元素

主要功能:

  • 入队(enqueue):将元素添加到队尾。
  • 出队(dequeue):移除并返回队头元素。
  • 查看队头元素(peek):返回队头元素但不移除。
  • 判空(isEmpty):检查队列是否为空。

适用类型:

  1. 任务调度:操作系统中的任务调度通常使用队列来管理待执行的任务。
  2. 消息传递:在消息队列系统中,消息的发送和接收通常使用队列来实现。
  3. 广度优先搜索(BFS):在图的遍历中,广度优先搜索算法使用队列来存储待访问的节点。
  4. 打印任务队列:打印机管理打印任务时,通常使用队列来存储待打印的文档。
  5. 缓冲区:在数据流处理中,队列可以作为缓冲区来平衡生产和消费的速度。

 

public class Queue<E> {
    private Node<E> head;
    private Node<E> tail;
    private int size;

    private static class Node<E> {
        E element;
        Node<E> next;

        Node(E element) {
            this.element = element;
        }
    }

    public void enqueue(E element) {
        Node<E> newNode = new Node<>(element);
        if (isEmpty()) {
            head = newNode;
        } else {
            tail.next = newNode;
        }
        tail = newNode;
        size++;
    }

    public E dequeue() {
        if (isEmpty()) {
            throw new IllegalStateException("Queue is empty");
        }
        E element = head.element;
        head = head.next;
        if (head == null) {
            tail = null;
        }
        size--;
        return element;
    }

    public E peek() {
        if (isEmpty()) {
            throw new IllegalStateException("Queue is empty");
        }
        return head.element;
    }

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

 

  • 17
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值