测试开发常见面试题-- 数据结构篇

1. 数组和链表

数组

概念:数组是一种线性数据结构,其中元素按顺序存储并可以通过索引随机访问。

优点:

  • 快速随机访问:O(1)时间复杂度
  • 内存连续,缓存友好。

缺点:

  • 插入和删除操作效率低:O(n)时间复杂度
  • 大小固定,需要预定义。

使用场景:需要频繁访问元素且数组大小已知或可预估时。

public class ArrayExample {

    public static void main(String[] args) {
        // 声明和初始化数组
        int[] array = new int[5];
        
        // 给数组赋值
        array[0] = 1;
        array[1] = 2;
        array[2] = 3;
        array[3] = 4;
        array[4] = 5;

        // 访问数组元素
        for (int i = 0; i < array.length; i++) {
            System.out.println("Element at index " + i + ": " + array[i]);
        }

		// 动态数组(ArrayList)
		ArrayList<Integer> dynamicArray = new ArrayList<>();
		dynamicArray.add(1);
		dynamicArray.add(2);
		dynamicArray.add(3);
		
		System.out.println("Dynamic Array Elements: " + dynamicArray);
    }
}

链表

概念:链表是一种线性数据结构,其中每个元素(节点)包含一个数据值和一个指向下一个节点的引用

优点:

  • 插入和删除操作效率高:O(1)时间复杂度(在已知节点位置时)。
  • 动态大小。

缺点:

  • 随机访问效率低:O(n)时间复杂度
  • 需要额外的存储空间来存储指针。

使用场景:需要频繁插入和删除元素,且元素访问相对较少时。

class Node {
    int data;
    Node next;

    Node(int data) {
        this.data = data;
        this.next = null;
    }
}

class LinkedList {
    Node head;

    // 向链表添加元素
    public void add(int data) {
        Node newNode = new Node(data);
        if (head == null) {
            head = newNode;
        } else {
            Node temp = head;
            while (temp.next != null) {
                temp = temp.next;
            }
            temp.next = newNode;
        }
    }

    // 打印链表
    public void printList() {
        Node temp = head;
        while (temp != null) {
            System.out.print(temp.data + " -> ");
            temp = temp.next;
        }
        System.out.println("null");
    }

    // 删除链表中的元素
    public void delete(int key) {
        Node temp = head, prev = null;

        // 如果头节点就是要删除的节点
        if (temp != null && temp.data == key) {
            head = temp.next;
            return;
        }

        // 搜索要删除的节点,记录前一个节点
        while (temp != null && temp.data != key) {
            prev = temp;
            temp = temp.next;
        }

        // 如果没找到节点
        if (temp == null) return;

        // 断开节点
        prev.next = temp.next;
    }

    public static void main(String[] args) {
        LinkedList list = new LinkedList();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);

        System.out.println("Initial Linked List:");
        list.printList();

        list.delete(3);

        System.out.println("Linked List after deletion:");
        list.printList();
    }
}

2. 栈和队列


先进后出(LIFO)结构。
主要操作:push(入栈),pop(出栈),top(获取栈顶元素), 时间复杂度都是O(1)
应用场景:函数调用管理(调用栈),表达式求值,括号匹配等。

import java.util.Stack;

public class StackExample {

    public static void main(String[] args) {
    
        Stack<Integer> stack = new Stack<>();

        // 压入元素
        stack.push(1);
        stack.push(2);
        stack.push(3);

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

        // 弹出元素
        System.out.println("Popped element: " + stack.pop());
        System.out.println("Popped element: " + stack.pop());

        // 检查栈是否为空
        System.out.println("Is stack empty? " + stack.isEmpty());

        // 打印剩余元素
        System.out.println("Remaining elements in stack: " + stack);
    }
}

队列
先进先出(FIFO)结构。
主要操作:enqueue(入队),dequeue(出队),front(获取队头元素), 时间复杂度都是O(1)
应用场景:任务调度,广度优先搜索(BFS),打印任务管理等。

import java.util.LinkedList;
import java.util.Queue;

public class QueueExample {

    public static void main(String[] args) {
    
        Queue<Integer> queue = new LinkedList<>();

        // 添加元素
        queue.add(1);
        queue.add(2);
        queue.add(3);

        // 查看队头元素
        System.out.println("Front element: " + queue.peek());

        // 移除元素
        System.out.println("Removed element: " + queue.poll());
        System.out.println("Removed element: " + queue.poll());

        // 检查队列是否为空
        System.out.println("Is queue empty? " + queue.isEmpty());

        // 打印剩余元素
        System.out.println("Remaining elements in queue: " + queue);
    }
}

3. 哈希表

概念
哈希表:通过哈希函数将键转换为数组的索引,并将值存储在相应的位置。哈希表的关键优势在于其常数时间复杂度O(1)的查找、插入和删除操作。

哈希函数:一种将输入(键)转换为固定大小整数的函数。好的哈希函数应尽量均匀地分布输入值,减少哈希冲突。

哈希冲突:当多个键被映射到相同索引时发生冲突。解决冲突的方法包括链地址法和开放地址法。

哈希表的优缺点
优点:

  • 快速查找、插入和删除操作,平均时间复杂度为O(1)。

缺点:

  • 需要处理哈希冲突。
  • 性能依赖于哈希函数的质量。
  • 需要足够大的内存来存储元素,以减少冲突。
import java.util.HashMap;

public class HashTableExample {

    public static void main(String[] args) {
        // 创建一个 HashMap
        HashMap<String, Integer> map = new HashMap<>();

        // 插入键值对
        map.put("Alice", 30);
        map.put("Bob", 25);
        map.put("Charlie", 35);

        // 查找元素
        System.out.println("Alice's age: " + map.get("Alice"));

        // 删除元素
        map.remove("Bob");

        // 检查是否包含某个键
        if (map.containsKey("Charlie")) {
            System.out.println("Charlie is in the map.");
        }

        // 遍历元素
        for (String key : map.keySet()) {
            System.out.println(key + ": " + map.get(key));
        }
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值