数组列表 (Array List) 进行详细解析,包括中文解释、适用场景、示例代码、测试用例,并特别针对半导体产线或测试机场景提供定制化的代码示例。

数组列表是项目(https://github.com/aalhour/C-Sharp-Algorithms)中列出的线性数据结构之一,因其简单性和灵活性在多种场景下非常实用。以下内容将基于 C# 类库项目的结构,结合半导体产线应用进行扩展,并确保内容清晰、简洁且全面。


一、数组列表 (Array List) 详解中文解释数组列表是一种动态数组数据结构,基于固定大小的数组实现,但支持动态扩展和收缩。它的核心特点是:

  • 随机访问:通过索引直接访问元素,时间复杂度为 O(1)。
  • 动态调整:当元素数量超过当前数组容量时,自动扩展数组(通常翻倍)。
  • 有序存储:元素按插入顺序存储,支持顺序遍历。

数组列表的常见操作及其时间复杂度:

  • 插入(尾部):O(1)(均摊,考虑扩容情况)。
  • 插入(任意位置):O(n),需移动后续元素。
  • 删除:O(n),需移动后续元素。
  • 访问/更新:O(1)。
  • 查找(无序):O(n)。

相比固定大小的数组,数组列表提供了动态性;相比链表,它提供了高效的随机访问。适用场景

  • 通用场景:
    • 存储动态增长的列表数据(如日志记录、任务队列)。
    • 需要频繁随机访问的场景(如索引访问元素)。
    • 简单的数据集合管理(如临时存储查询结果)。
  • 半导体产线场景:
    • 测试机:存储晶圆测试结果的序列(如按测试顺序记录缺陷率)。
    • 贴片机 (SMT):记录元件贴片位置的列表,支持动态添加和快速访问。
  • 优点:
    • 高效的随机访问(O(1))。
    • 实现简单,内存利用率高。
    • 适合尾部插入频繁的场景。
  • 缺点:
    • 插入/删除非尾部元素效率低(O(n))。
    • 扩容可能导致性能抖动。
    • 不适合键值对或复杂查询场景。

二、示例代码以下是数组列表的 C# 实现,基于项目的 Data Structures 子项目,简化以突出核心逻辑(类似于 C# 的 List<T>,但自定义实现以展示原理):csharp

 

using System;

public class ArrayList<T>
{
    private T[] items;
    private int size;
    private int capacity;
    private const int DefaultCapacity = 4;

    public ArrayList(int initialCapacity = DefaultCapacity)
    {
        capacity = initialCapacity;
        items = new T[capacity];
        size = 0;
    }

    public int Count => size;

    public void Add(T item)
    {
        if (size == capacity)
            Resize(capacity * 2); // 容量翻倍
        items[size++] = item;
    }

    public void Insert(int index, T item)
    {
        if (index < 0 || index > size)
            throw new ArgumentOutOfRangeException(nameof(index));
        if (size == capacity)
            Resize(capacity * 2);
        for (int i = size; i > index; i--)
            items[i] = items[i - 1];
        items[index] = item;
        size++;
    }

    public bool Remove(T item)
    {
        int index = IndexOf(item);
        if (index >= 0)
        {
            RemoveAt(index);
            return true;
        }
        return false;
    }

    public void RemoveAt(int index)
    {
        if (index < 0 || index >= size)
            throw new ArgumentOutOfRangeException(nameof(index));
        for (int i = index; i < size - 1; i++)
            items[i] = items[i + 1];
        items[size - 1] = default;
        size--;
        if (size > 0 && size <= capacity / 4)
            Resize(capacity / 2); // 缩容
    }

    public T this[int index]
    {
        get
        {
            if (index < 0 || index >= size)
                throw new ArgumentOutOfRangeException(nameof(index));
            return items[index];
        }
        set
        {
            if (index < 0 || index >= size)
                throw new ArgumentOutOfRangeException(nameof(index));
            items[index] = value;
        }
    }

    public int IndexOf(T item)
    {
        for (int i = 0; i < size; i++)
            if (Equals(items[i], item))
                return i;
        return -1;
    }

    private void Resize(int newCapacity)
    {
        T[] newItems = new T[newCapacity];
        for (int i = 0; i < size; i++)
            newItems[i] = items[i];
        items = newItems;
        capacity = newCapacity;
    }
}

代码说明

  • 构造:初始化数组,设置默认容量(DefaultCapacity)。
  • Add:尾部添加元素,必要时扩容。
  • Insert:在指定索引插入元素,需移动后续元素。
  • Remove/RemoveAt:删除元素,需移动后续元素并可能缩容。
  • this[int index]:提供索引器,支持随机访问。
  • Resize:动态调整数组大小,扩容或缩容。

三、测试用例以下是使用 MSTest 框架的单元测试代码:csharp

 

using Microsoft.VisualStudio.TestTools.UnitTesting;

[TestClass]
public class ArrayListTests
{
    [TestMethod]
    public void Add_ValidItem_IncreasesCountAndStoresItem()
    {
        // Arrange
        var list = new ArrayList<int>();
        list.Add(1);
        list.Add(2);

        // Act
        int count = list.Count;
        int firstItem = list[0];
        int secondItem = list[1];

        // Assert
        Assert.AreEqual(2, count);
        Assert.AreEqual(1, firstItem);
        Assert.AreEqual(2, secondItem);
    }

    [TestMethod]
    public void Insert_ValidIndex_InsertsCorrectly()
    {
        // Arrange
        var list = new ArrayList<int>();
        list.Add(1);
        list.Add(3);

        // Act
        list.Insert(1, 2);

        // Assert
        Assert.AreEqual(3, list.Count);
        Assert.AreEqual(1, list[0]);
        Assert.AreEqual(2, list[1]);
        Assert.AreEqual(3, list[2]);
    }

    [TestMethod]
    public void Remove_ValidItem_RemovesCorrectly()
    {
        // Arrange
        var list = new ArrayList<int>();
        list.Add(1);
        list.Add(2);

        // Act
        bool removed = list.Remove(1);

        // Assert
        Assert.IsTrue(removed);
        Assert.AreEqual(1, list.Count);
        Assert.AreEqual(2, list[0]);
    }

    [TestMethod]
    [ExpectedException(typeof(ArgumentOutOfRangeException))]
    public void Access_InvalidIndex_ThrowsException()
    {
        // Arrange
        var list = new ArrayList<int>();

        // Act
        int item = list[0]; // 应抛出异常
    }
}

测试说明

  • 测试添加功能,确保元素正确存储且计数增加。
  • 测试插入功能,验证元素插入正确位置且后续元素移动。
  • 测试删除功能,确认元素移除和列表调整。
  • 测试边界情况,确保无效索引抛出异常。

四、半导体产线示例在半导体测试机中,数组列表可用于存储晶圆测试结果的序列(如按测试顺序记录缺陷率),支持动态添加和快速访问。以下是一个具体场景:测试机按顺序记录晶圆的测试数据,需要快速访问特定测试结果或追加新数据。示例代码csharp

 

public class WaferTestRecord
{
    public int WaferId { get; set; }
    public double DefectRate { get; set; }
    public DateTime TestTime { get; set; }

    public WaferTestRecord(int waferId, double defectRate, DateTime testTime)
    {
        WaferId = waferId;
        DefectRate = defectRate;
        TestTime = testTime;
    }
}

public class WaferTestManager
{
    private ArrayList<WaferTestRecord> testRecords;

    public WaferTestManager()
    {
        testRecords = new ArrayList<WaferTestRecord>();
    }

    public void AddTestRecord(int waferId, double defectRate, DateTime testTime)
    {
        testRecords.Add(new WaferTestRecord(waferId, defectRate, testTime));
    }

    public WaferTestRecord GetTestRecord(int index)
    {
        return testRecords[index];
    }

    public bool RemoveTestRecord(int waferId)
    {
        for (int i = 0; i < testRecords.Count; i++)
        {
            if (testRecords[i].WaferId == waferId)
            {
                testRecords.RemoveAt(i);
                return true;
            }
        }
        return false;
    }

    public int Count => testRecords.Count;
}

测试用例csharp

 

[TestMethod]
public void WaferTestManager_AddAndGetTestRecord_ReturnsCorrectRecord()
{
    // Arrange
    var manager = new WaferTestManager();
    var testTime1 = new DateTime(2025, 8, 6, 13, 0, 0);
    var testTime2 = new DateTime(2025, 8, 6, 13, 1, 0);
    manager.AddTestRecord(1001, 0.05, testTime1);
    manager.AddTestRecord(1002, 0.03, testTime2);

    // Act
    var record = manager.GetTestRecord(0);

    // Assert
    Assert.IsNotNull(record);
    Assert.AreEqual(1001, record.WaferId);
    Assert.AreEqual(0.05, record.DefectRate);
}

[TestMethod]
public void WaferTestManager_RemoveTestRecord_RemovesCorrectly()
{
    // Arrange
    var manager = new WaferTestManager();
    var testTime = new DateTime(2025, 8, 6, 13, 0, 0);
    manager.AddTestRecord(1001, 0.05, testTime);

    // Act
    bool removed = manager.RemoveTestRecord(1001);
    int count = manager.Count;

    // Assert
    Assert.IsTrue(removed);
    Assert.AreEqual(0, count);
}

半导体场景说明

  • 场景:测试机按顺序记录晶圆测试结果(如缺陷率),需要快速访问特定测试记录(通过索引)或追加新记录。
  • 优势:数组列表的 O(1) 随机访问适合按索引查询测试结果,尾部添加操作高效(O(1) 均摊)。
  • 局限性:如果需要频繁插入或删除非尾部记录,性能较差(O(n)),可考虑链表或跳表。
  • 优化建议:对于大规模数据,可预分配较大初始容量以减少扩容开销。

五、贴片机场景示例在贴片机 (SMT) 中,数组列表可用于存储元件的贴片位置序列,按贴片顺序记录,支持动态添加和快速访问。示例代码csharp

 

public class ComponentPlacementRecord
{
    public int ComponentId { get; set; }
    public double X { get; set; }
    public double Y { get; set; }
    public DateTime PlacementTime { get; set; }

    public ComponentPlacementRecord(int componentId, double x, double y, DateTime placementTime)
    {
        ComponentId = componentId;
        X = x;
        Y = y;
        PlacementTime = placementTime;
    }
}

public class SmtPlacementManager
{
    private ArrayList<ComponentPlacementRecord> placements;

    public SmtPlacementManager()
    {
        placements = new ArrayList<ComponentPlacementRecord>();
    }

    public void AddPlacement(int componentId, double x, double y, DateTime placementTime)
    {
        placements.Add(new ComponentPlacementRecord(componentId, x, y, placementTime));
    }

    public ComponentPlacementRecord GetPlacement(int index)
    {
        return placements[index];
    }

    public int Count => placements.Count;
}

// 测试用例
[TestMethod]
public void SmtPlacementManager_AddAndGetPlacement_ReturnsCorrectRecord()
{
    // Arrange
    var manager = new SmtPlacementManager();
    var placementTime = new DateTime(2025, 8, 6, 13, 0, 0);
    manager.AddPlacement(2001, 10.5, 20.5, placementTime);

    // Act
    var record = manager.GetPlacement(0);

    // Assert
    Assert.IsNotNull(record);
    Assert.AreEqual(2001, record.ComponentId);
    Assert.AreEqual(10.5, record.X);
    Assert.AreEqual(20.5, record.Y);
}

贴片机场景说明

  • 场景:贴片机按顺序记录元件的贴片位置和时间,支持快速访问特定贴片记录(如检查第 n 个元件的坐标)。
  • 优势:数组列表的 O(1) 随机访问适合按索引查询贴片记录,尾部添加高效。
  • 局限性:如果需要按元件 ID 查找,需线性搜索(O(n)),可结合哈希表优化。
  • 优化建议:可结合快速排序(Quick Sort)对贴片记录按时间或坐标排序,支持后续分析。

六、总结与注意事项

  1. 数组列表特点:
    • 高效的随机访问(O(1))和尾部添加(O(1) 均摊)。
    • 适合顺序存储和动态增长的场景。
    • 插入/删除非尾部元素效率较低(O(n))。
  2. 半导体产线应用:
    • 测试机:存储晶圆测试结果序列,支持快速访问。
    • 贴片机:记录元件贴片位置序列,支持动态添加。
  3. 优化建议:
    • 预分配容量以减少扩容开销。
    • 对于频繁插入/删除的场景,可考虑链表或跳表。
    • 结合哈希表或跳表支持键值查询或范围查询。
  4. 与其他数据结构的对比:
    • 相比链表,数组列表提供高效随机访问,但插入/删除效率较低。
    • 相比跳表,数组列表不支持高效的键值查询,但实现更简单,适合顺序存储。

如果您需要更详细的数组列表实现(如并发支持)、其他算法或数据结构的解析,或针对特定半导体设备(如晶圆切割机)的定制代码,请进一步说明,我将提供更深入的示例!

 

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐