java数据结构及其实现

Java常用的数据类型

一、线性数据结构

1.栈

遵循“后进先出”(LIFO, Last In First Out)的原则

java.util.Stack 是 Java 标准库提供的一个类,它继承自 Vector 类,并提供了栈的基本操作,如 push, pop, peek 等。

import java.util.Stack;

public class StackExample {
    public static void main(String[] args) {
        // 创建一个 Stack 对象
        Stack<String> stack = new Stack<>();

        // 入栈操作
        stack.push("one");
        stack.push("two");
        stack.push("three");

        // 查看栈顶元素
        System.out.println("Top element: " + stack.peek());

        // 出栈操作
        String topElement = stack.pop();
        System.out.println("Popped element: " + topElement);

        // 输出栈的内容
        System.out.println("Stack contents: " + stack);
    }
}

2.队列

Queue 是 Java 集合框架中的一个接口,它继承自 Collection 接口,因此实现了 Queue 的类可以使用所有 Collection 接口的方法。Queue 接口中定义了一些特定于队列的操作方法,比如 add, offer, remove, poll, element 和 peek 等。
add(e): 添加元素到队列尾部,如果队列已满,则抛出 IllegalStateException。
offer(e): 添加元素到队列尾部,如果队列已满则返回 false。
remove(): 移除并返回队列头部的元素,如果队列为空则抛出 NoSuchElementException。
poll(): 移除并返回队列头部的元素,如果队列为空则返回 null。
element(): 返回队列头部的元素,如果队列为空则抛出 NoSuchElementException。
peek(): 返回队列头部的元素,如果队列为空则返回 null。

Java 队列实现:

在Java中,队列(Queue)是一种先进先出(FIFO, First-In-First-Out)的数据结构。Java的java.util包提供了多种队列的实现类,这些类根据它们的特性(如线程安全性、是否允许null元素、性能特性等)而有所不同。以下是一些常见的Queue实现类:

  1. LinkedList:
    • LinkedList类实现了ListDeque接口,因此它也可以用作队列。由于其基于链表的结构,它在添加和删除元素时表现出良好的性能(在链表的两端)。
    • 使用offer(E e)添加元素到队列的末尾,poll()移除并返回队列头部的元素,或者peek()查看队列头部的元素但不移除它。
  2. PriorityQueue:
    • PriorityQueue是一个基于优先级堆的无界优先级队列。元素根据其自然顺序进行排序,或者根据创建PriorityQueue时提供的Comparator进行排序。
    • 注意,PriorityQueue不是严格意义上的FIFO队列,因为它基于元素的优先级进行排序。
  3. ArrayDeque:
    • ArrayDeque是一个基于数组的双端队列,但它也可以高效地用作FIFO队列。
    • 相比LinkedListArrayDeque在大多数实现中提供了更好的性能,尤其是在执行大量的插入和删除操作时。
  4. ConcurrentLinkedQueue:
    • ConcurrentLinkedQueue是一个基于链接节点的无界线程安全队列。此队列按照FIFO(先进先出)排序元素。
    • 它适合在多线程环境中使用,因为它支持高并发级别的操作。
  5. LinkedBlockingQueue和ArrayBlockingQueue:
    • 这两个类都是BlockingQueue接口的实现,它们支持两个附加操作:支持阻塞的插入和移除方法。
    • LinkedBlockingQueue通常具有更高的吞吐量,但在大多数并发级别上,ArrayBlockingQueue提供了更好的可预测性能。
    • ArrayBlockingQueue是一个由数组结构组成的有界阻塞队列。
    • LinkedBlockingQueue如果创建时没有指定容量,则默认为Integer.MAX_VALUE
  6. SynchronousQueue:
    • SynchronousQueue是一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,反之亦然。
    • 它对于传递性场景特别有用,其中一个线程需要将对象传递给另一个线程。

在选择队列实现时,您应该根据您的具体需求(如性能要求、是否需要线程安全、队列的大小是否有限制等)来决定使用哪个实现。

代码案例:
import java.util.LinkedList;
import java.util.Queue;

public class QueueExample {
    public static void main(String[] args) {
        // 创建一个队列实例
        Queue<String> queue = new LinkedList<>();

        // 向队列中添加元素
        queue.add("one");
        queue.add("two");
        queue.add("three");

        // 输出队列头部的元素
        System.out.println("Head of the queue: " + queue.element());

        // 从队列中移除并输出头部的元素
        String removedElement = queue.remove();
        System.out.println("Removed element: " + removedElement);

        // 输出队列的内容
        System.out.println("Queue contents: " + queue);
    }
}

3.数组(Array)

  • 是一种线性表数据结构,它用一组连续的内存空间来存储一组具有相同类型的数据。
  • 特点:内存地址连续,检索效率高(可以通过下标访问成员),但增删操作效率低(需要移动数据)
int[] arr =new int[]

4.链表(Linked List)

  • 由一系列节点组成,每个节点包含数据和指向下一个节点的引用(在双向链表中还包含指向前一个节点的引用)。
  • 分为单向链表、双向链表和循环链表等。
  • 特点:内存地址不连续,插入和删除操作效率高,但随机访问效率低。
// 定义节点
class Node {  
    int data; // 节点存储的数据  
    Node next; // 指向下一个节点的指针  
  
    // 构造函数  
    public Node(int data) {  
        this.data = data;  
        this.next = null; // 新节点的下一个节点初始时为null  
    }  
}

// 定义链表
class LinkedList {  
    Node head; // 链表的头节点  
  
    // 构造函数  
    public LinkedList() {  
        this.head = null; // 初始时链表为空  
    }  
  
    // 在链表末尾添加节点  
    public void add(int data) {  
        Node newNode = new Node(data);  
        if (head == null) {  
            head = newNode; // 如果链表为空,则新节点即为头节点  
        } else {  
            Node current = head;  
            while (current.next != null) {  
                current = current.next; // 遍历到链表的最后一个节点  
            }  
            current.next = newNode; // 将新节点添加到链表末尾  
        }  
    }  
  
    // 打印链表  
    public void printList() {  
        Node current = head;  
        while (current != null) {  
            System.out.print(current.data + " -> ");  
            current = current.next;  
        }  
        System.out.println("null");  
    }  
  
    // 其他方法(如删除节点、查找节点等)可以根据需要添加  
}

// 使用
public class Main {  
    public static void main(String[] args) {  
        LinkedList list = new LinkedList();  
        list.add(1);  
        list.add(2);  
        list.add(3);  
  
        list.printList(); // 输出: 1 -> 2 -> 3 -> null  
    }  
}

二、非线性数据结构

数据元素之间存在一对多或多对多的关系,形成非线性结构。常见的非线性数据结构包括:

1.树(Tree)

  • 由n(n≥0)个节点组成的具有层次关系的集合。
  • 包括二叉树、完全二叉树、平衡二叉树(如AVL树)、B树、B+树等多种类型。
  • 特点:具有层次结构,便于进行查找、插入和删除等操作。
// 二叉树的节点
class TreeNode {  
    int val; // 节点存储的数据  
    TreeNode left; // 左子节点  
    TreeNode right; // 右子节点  
  
    // 构造函数  
    public TreeNode(int val) {  
        this.val = val;  
        this.left = null;  
        this.right = null;  
    }  
}

// 二叉树的定义
class BinaryTree {  
    TreeNode root; // 二叉树的根节点  
  
    // 构造函数  
    public BinaryTree() {  
        this.root = null;  
    }  
  
    // 简化的插入方法(总是插入为左子节点,仅用于示例)  
    public void insert(int val) {  
        if (root == null) {  
            root = new TreeNode(val);  
        } else {  
            // 注意:这里只是简单地总是插入为根节点的左子节点,实际中可能需要根据情况决定插入位置  
            TreeNode current = root;  
            while (current.left != null) {  
                // 这里实际上没有处理右子树的情况,仅作为示例  
                current = current.left;  
            }  
            current.left = new TreeNode(val);  
        }  
    }  
  
    // 遍历方法(这里以中序遍历为例)  
    public void inorderTraversal(TreeNode node) {  
        if (node != null) {  
            inorderTraversal(node.left); // 遍历左子树  
            System.out.print(node.val + " "); // 访问节点  
            inorderTraversal(node.right); // 遍历右子树  
        }  
    }  
  
    // 提供一个公共的遍历入口  
    public void inorderTraversal() {  
        inorderTraversal(root);  
    }  
  
    // 其他方法(如前序遍历、后序遍历、搜索节点、删除节点等)可以根据需要添加  
}

// 二叉树的使用
public class Main {  
    public static void main(String[] args) {  
        BinaryTree tree = new BinaryTree();  
        tree.insert(1);  
        tree.insert(2);  
        tree.insert(3);  
        // 注意:由于插入方法总是将新节点插入为左子节点,所以这里的树结构是倾斜的  
  
        tree.inorderTraversal(); // 输出将取决于树的结构,但在这个例子中,由于插入逻辑,输出可能不是直观的排序  
        // 假设树的结构是:  
        //       1  
        //      /  
        //     2  
        //    /  
        //   3  
        // 那么输出将是:3 2 1(因为我们是中序遍历,但树是倾斜的)  
    }  
}

2.图(Graph)

  • 由一系列顶点(Vertex)和边(Edge)组成的集合,用于描述对象之间的关系。
  • 分为有向图和无向图两种。
  • 特点:节点之间的关系是任意的,图中任意两个数据元素之间都有可能相关。
// 图的定义
public class GraphMatrix {  
    private int vertices; // 图的顶点数  
    private int[][] adjMatrix; // 邻接矩阵  
  
    // 构造函数  
    public GraphMatrix(int vertices) {  
        this.vertices = vertices;  
        adjMatrix = new int[vertices][vertices];  
  
        // 初始化邻接矩阵为0(表示无边)  
        for (int i = 0; i < vertices; i++) {  
            for (int j = 0; j < vertices; j++) {  
                adjMatrix[i][j] = 0;  
            }  
        }  
    }  
  
    // 添加边  
    public void addEdge(int v1, int v2, int weight) {  
        adjMatrix[v1][v2] = weight; // 无向图时,还需要设置adjMatrix[v2][v1] = weight  
        // 对于有向图,上面的代码就足够了  
    }  
  
    // 打印邻接矩阵  
    public void printGraph() {  
        for (int i = 0; i < vertices; i++) {  
            for (int j = 0; j < vertices; j++) {  
                System.out.print(adjMatrix[i][j] + " ");  
            }  
            System.out.println();  
        }  
    }  
}

// 图的实现
import java.util.LinkedList;  
import java.util.List;  
  
public class GraphList {  
    private int vertices; // 图的顶点数  
    private List<List<Integer>> adjLists; // 邻接表  
  
    // 图的节点类,用于存储边(如果图是有权重的,则可以存储权重信息)  
    class AdjListNode {  
        int dest; // 相邻的顶点  
        // 如果需要,可以在这里添加权重等其他信息  
        AdjListNode next; // 指向下一个邻接节点的指针  
  
        // 构造函数  
        public AdjListNode(int dest) {  
            this.dest = dest;  
            this.next = null;  
        }  
    }  
  
    // 构造函数  
    public GraphList(int vertices) {  
        this.vertices = vertices;  
        adjLists = new LinkedList<>();  
  
        // 初始化邻接表  
        for (int i = 0; i < vertices; i++) {  
            adjLists.add(new LinkedList<>());  
        }  
    }  
  
    // 添加边  
    public void addEdge(int v1, int v2) {  
        // 注意:对于无向图,还需要调用addEdge(v2, v1)  
        adjLists.get(v1).add(new AdjListNode(v2));  
    }  
  
    // 打印邻接表(简化版,不打印权重)  
    public void printGraph() {  
        for (int i = 0; i < vertices; i++) {  
            System.out.print("顶点 " + i + " 的邻接表: ");  
            List<Integer> list = adjLists.get(i);  
            for (int node : list) {  
                System.out.print(node + " ");  
            }  
            System.out.println();  
        }  
    }  
}

3.哈希表(Hash Table)

  • 也叫散列表,是一种可以通过关键码值(Key-Value)直接访问的数据结构。
  • 实现了快速查询、插入和删除操作。
  • 在Java中,HashMap是哈希表的典型实现,它通过哈希函数将数据元素映射到数组的某个位置,并通过链表或红黑树解决哈希冲突问题。
Map map = new HashMap<Object,Object>();
  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值