《数据结构:从0到1》-05-数组

数组:编程世界的万能收纳架,你真的会用吗?

想象一下,你有一个药盒,里面有7个小格子,分别放着周一到周日的药。每天早上,你只需要打开对应日期的格子取药------这,就是数组在现实生活中的完美体现!

数组就像是我们生活中的各种收纳工具:

  • 🗃️ 药盒 → 一维数组
  • 🎒 多层饭盒 → 二维数组
  • 📚 书架 → 三维数组
  • 🏢 公寓楼 → 多维数组

今天,就让我带你彻底搞懂这个看似简单、实则暗藏玄机的数据结构!

第一章:数组到底是什么?

1.1 用大白话解释数组

数组就是一群"数据类型相同、住址相邻"的数据元素的集合。

把内存想象成一条大街,数组就是街上的一排连号公寓:

css 复制代码
内存地址: 1001  1002  1003  1004  1005
住户数据:[  A ][  B ][  C ][  D ][  E ]
房间号:    0     1     2     3     4

三个关键特征:

  1. 📍 住址固定:每个元素有固定的"门牌号"(索引)
  2. 👯 同类聚居:所有元素必须是同一数据类型
  3. 🏘️ 紧密相邻:元素在内存中紧密排列,没有空隙

1.2 为什么需要数组?

假设我们要记录5个学生的成绩:

笨方法

java 复制代码
int score1 = 90;
int score2 = 85;
int score3 = 92;
int score4 = 78;
int score5 = 88;
// 要计算平均分得写:double avg = (score1 + score2 + ... + score5) / 5.0;

聪明方法(用数组)

java 复制代码
int[] scores = {90, 85, 92, 78, 88};
// 计算平均分:
int sum = 0;
for(int i = 0; i < scores.length; i++) {
    sum += scores[i];
}
double avg = sum / 5.0;

看到差别了吗?数组让我们的代码更简洁、更易扩展!

第二章:静态数组 vs 动态数组

2.1 静态数组

举个例子:就像健身房租的储物柜,大小固定,多了放不下,少了空间浪费。

java 复制代码
// 创建一个能放5本书的书架(静态数组)
String[] bookshelf = new String[5];

// 往书架上放书
bookshelf[0] = "Java编程思想";
bookshelf[1] = "数据结构与算法"; 
bookshelf[2] = "设计模式";
bookshelf[3] = "计算机网络";
bookshelf[4] = "操作系统";

// 悲剧:想放第6本书?放不下了!
// bookshelf[5] = "编译原理"; // 这会报错!

静态数组原理图

arduino 复制代码
静态数组就像固定格子的储物柜:
┌─────────┬─────────┬─────────┬─────────┬─────────┐
│  格子0  │  格子1  │  格子2  │  格子3  │  格子4  │
│  "Java" │"数据结构"│"设计模式"│"计算机网络"│"操作系统"│
└─────────┴─────────┴─────────┴─────────┴─────────┘
大小固定:5个格子,无法增加或减少

2.2 动态数组"

举个例子:就像哈利波特的魔法背包,东西多了自动变大,永远装得下!

java 复制代码
// Java中的ArrayList就是动态数组
import java.util.ArrayList;

public class MagicBackpack {
    public static void main(String[] args) {
        // 创建一个空的魔法背包
        ArrayList<String> backpack = new ArrayList<>();
        
        System.out.println("初始背包容量: " + backpack.size());
        
        // 往背包里放东西,不用担心容量
        backpack.add("魔法杖");
        backpack.add("隐身衣");
        backpack.add("飞行扫帚");
        backpack.add("时间转换器");
        backpack.add("复活石");
        
        System.out.println("放了5件物品后容量: " + backpack.size());
        
        // 再放一件,背包会自动扩容!
        backpack.add("厄里斯魔镜");
        System.out.println("放了6件物品后容量: " + backpack.size());
    }
}

动态数组扩容流程图

scss 复制代码
┌─────────────────────────────────────────────┐
│            动态数组扩容过程                  │
├─────────────────────────────────────────────┤
│ 1. 背包已满,还想放新物品                    │
│    ↓                                        │
│ 2. 召唤一个更大的新背包(通常是1.5-2倍大)      │
│    ↓                                        │
│ 3. 把旧背包所有物品搬到新背包                │
│    ↓                                        │
│ 4. 扔掉旧背包,使用新背包                    │
│    ↓                                        │
│ 5. 把新物品放进新背包                        │
└─────────────────────────────────────────────┘

实际扩容代码模拟

java 复制代码
public class DynamicArrayDemo {
    private int[] data;      // 存储数据的数组
    private int size;        // 当前元素个数
    private int capacity;    // 总容量
    
    public DynamicArrayDemo() {
        capacity = 3;        // 初始容量3
        data = new int[capacity];
        size = 0;
    }
    
    // 添加元素,自动扩容
    public void add(int value) {
        // 如果背包满了,就扩容
        if (size == capacity) {
            System.out.println("⚠️ 背包已满,开始扩容...");
            resize(capacity * 2);  // 容量翻倍
        }
        
        data[size] = value;
        size++;
        System.out.println("✅ 添加元素: " + value + ", 当前大小: " + size);
    }
    
    // 扩容方法
    private void resize(int newCapacity) {
        System.out.println("🔄 从容量 " + capacity + " 扩容到 " + newCapacity);
        
        int[] newData = new int[newCapacity];  // 创建新背包
        
        // 把旧背包的东西搬到新背包
        for (int i = 0; i < size; i++) {
            newData[i] = data[i];
        }
        
        data = newData;      // 换上新背包
        capacity = newCapacity;
        System.out.println("🎉 扩容完成!");
    }
}

第三章:揭秘数组操作效率

3.1 读取元素:为什么这么快?

举个例子:我们生活中常见的场景,就像你知道朋友住在3号楼201房间,直接去敲门就行,不用从1号楼开始找。

java 复制代码
int[] apartmentBuilding = {101, 102, 103, 104, 105};

// 直接访问3号房间(索引为2)
int room3 = apartmentBuilding[2]; // 瞬间拿到103!

// 计算机怎么做到的?
// 内存地址 = 起始地址 + 索引 × 元素大小
// 假设起始地址是1000,每个int占4字节:
// 房间3的地址 = 1000 + 2 × 4 = 1008
// 直接去1008地址取数据,一步到位!

随机访问原理图

ini 复制代码
内存街道:
地址:  1000  1004  1008  1012  1016
数据: [ 101 ][ 102 ][ 103 ][ 104 ][ 105 ]
索引:    0      1      2      3      4

要找103号(索引2):
1. 知道整条街起点:1000
2. 知道每个房子大小:4字节  
3. 计算:1000 + 2 × 4 = 1008
4. 直接去1008敲门 → 拿到103!

时间复杂度:O(1) - 恒定时间,与数组大小无关

3.2 插入元素:为什么这么麻烦?

生活比喻:就像在排队买奶茶时,有人要插队到中间位置,后面所有人都得往后挪一步。

java 复制代码
public class ArrayInsertExample {
    public static void main(String[] args) {
        // 原数组:5个人的队伍
        String[] queue = {"小明", "小红", "小刚", "小丽", null};
        System.out.println("原队伍: " + Arrays.toString(queue));
        
        // 小华要插队到第2个位置(索引1)
        int insertPosition = 1;
        String newPerson = "小华";
        
        // 插入过程:后面的人都要往后挪
        System.out.println("🚶 开始挪动位置...");
        for (int i = queue.length - 1; i > insertPosition; i--) {
            queue[i] = queue[i - 1];  // 每个人往后挪一位
            System.out.println("第" + (i-1) + "位挪到第" + i + "位");
        }
        
        // 空出位置后,新的人插入
        queue[insertPosition] = newPerson;
        System.out.println("✅ " + newPerson + "插入到位置" + insertPosition);
        System.out.println("新队伍: " + Arrays.toString(queue));
    }
}

插入操作流程图

css 复制代码
┌─────────────────────────────────────────────┐
│             数组插入元素过程                 │
├─────────────────────────────────────────────┤
│ 原数组:[A, B, C, D, E, 空]                 │
│ 要在索引1位置插入X                           │
│                                             │
│ 步骤1:从后往前,逐个后移                    │
│   E → 空位, D → E的位置, C → D的位置...      │
│                                             │
│ 步骤2:空出目标位置                          │
│   [A, 空, B, C, D, E]                       │
│                                             │
│ 步骤3:插入新元素                            │
│   [A, X, B, C, D, E]                        │
└─────────────────────────────────────────────┘

插入时间复杂度分析

  • 🏆 最佳情况 :在末尾插入 → O(1)
    • 不用移动任何元素,直接放最后就行
  • 😊 平均情况 :在中间插入 → O(n)
    • 平均需要移动 n/2 个元素
  • 😭 最坏情况 :在开头插入 → O(n)
    • 需要移动所有 n 个元素

3.3 删除元素:同样麻烦的搬家过程

java 复制代码
public class ArrayDeleteExample {
    public static void main(String[] args) {
        // 原数组:5个人的队伍  
        String[] queue = {"小明", "小红", "小刚", "小丽", "小华"};
        System.out.println("原队伍: " + Arrays.toString(queue));
        
        // 第2个人(索引1)要离开队伍
        int deletePosition = 1;
        
        System.out.println("❌ 位置" + deletePosition + "的" + 
                         queue[deletePosition] + "要离开");
        
        // 删除过程:后面的人往前补位
        System.out.println("🚶 开始补位...");
        for (int i = deletePosition; i < queue.length - 1; i++) {
            queue[i] = queue[i + 1];  // 后面的人往前补
            System.out.println("第" + (i+1) + "位补到第" + i + "位");
        }
        
        // 最后一个位置置空
        queue[queue.length - 1] = null;
        System.out.println("✅ 删除完成");
        System.out.println("新队伍: " + Arrays.toString(queue));
    }
}

3.4 数组操作效率总结表

操作 时间复杂度 形象比喻 效率评价
读取 O(1) 按门牌号直接找人 ⭐⭐⭐⭐⭐ 极快
搜索 O(n) 挨家挨户敲门找 ⭐⭐☆☆☆ 较慢
插入 O(n) 排队中间插队 ⭐⭐☆☆☆ 较慢
删除 O(n) 排队中间离开 ⭐⭐☆☆☆ 较慢

第四章:多维数组 - 从线到面

4.1 二维数组:数据的"Excel表格"

举个生活中的场景来形容二维数组

  • 一维数组 → 一条街道的门牌号
  • 二维数组 → 一个小区的楼号+单元号
  • 三维数组 → 一个城市的区+街道+门牌号
java 复制代码
// 用二维数组表示棋盘游戏
public class ChessBoard {
    public static void main(String[] args) {
        // 创建8×8的国际象棋棋盘
        String[][] chessBoard = new String[8][8];
        
        // 初始化棋盘 - 空棋盘用"·"表示
        for (int row = 0; row < 8; row++) {
            for (int col = 0; col < 8; col++) {
                chessBoard[row][col] = "·";
            }
        }
        
        // 摆放棋子
        // 白方棋子
        chessBoard[0] = new String[]{"♜", "♞", "♝", "♛", "♚", "♝", "♞", "♜"};
        chessBoard[1] = new String[]{"♟", "♟", "♟", "♟", "♟", "♟", "♟", "♟"};
        
        // 黑方棋子  
        chessBoard[6] = new String[]{"♙", "♙", "♙", "♙", "♙", "♙", "♙", "♙"};
        chessBoard[7] = new String[]{"♖", "♘", "♗", "♕", "♔", "♗", "♘", "♖"};
        
        // 打印棋盘
        System.out.println("   a b c d e f g h");
        System.out.println("  ┌─┬─┬─┬─┬─┬─┬─┬─┐");
        for (int row = 0; row < 8; row++) {
            System.out.print((8 - row) + " │");
            for (int col = 0; col < 8; col++) {
                System.out.print(chessBoard[row][col] + "│");
            }
            System.out.println(" " + (8 - row));
            if (row < 7) {
                System.out.println("  ├─┼─┼─┼─┼─┼─┼─┼─┤");
            }
        }
        System.out.println("  └─┴─┴─┴─┴─┴─┴─┴─┘");
        System.out.println("   a b c d e f g h");
    }
}

4.2 多维数组的内存存储

重要:虽然我们觉得二维数组是表格,但在内存中,它仍然是一维连续存储的!

java 复制代码
// 二维数组:3行4列的表格
int[][] classroom = {
    {1, 2, 3, 4},     // 第一排
    {5, 6, 7, 8},     // 第二排  
    {9, 10, 11, 12}   // 第三排
};

// 在内存中的实际存储:
// 地址: 1000 1004 1008 1012 1016 1020 1024 1028 1032 1036 1040 1044
// 数据: [ 1 ][ 2 ][ 3 ][ 4 ][ 5 ][ 6 ][ 7 ][ 8 ][ 9 ][10][11][12]

内存寻址公式

java 复制代码
// 访问classroom[i][j]的地址计算:
// 地址 = 基地址 + (i × 列数 + j) × 元素大小

// 例子:访问classroom[1][2](值为7)
// 假设基地址=1000,列数=4,元素大小=4字节
// 地址 = 1000 + (1×4 + 2)×4 
//      = 1000 + 6×4 
//      = 1000 + 24 = 1024
// 去1024地址取数据 → 得到7!

多维数组存储原理图

css 复制代码
我们眼中的二维数组:
┌─────┬─────┬─────┬─────┐
│ [0][0] │ [0][1] │ [0][2] │ [0][3] │ ← 第0行
├─────┼─────┼─────┼─────┤
│ [1][0] │ [1][1] │ [1][2] │ [1][3] │ ← 第1行  
├─────┼─────┼─────┼─────┤
│ [2][0] │ [2][1] │ [2][2] │ [2][3] │ ← 第2行
└─────┴─────┴─────┴─────┘

内存中的真实存储(行优先):
┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
│00│01│02│03│10│11│12│13│20│21│22│23│
└──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┘

第五章:数组的实战应用

5.1 应用一:学生成绩管理系统

java 复制代码
import java.util.Arrays;

public class StudentGradeSystem {
    public static void main(String[] args) {
        // 用二维数组存储3个学生的4门课成绩
        // 行:学生,列:课程
        int[][] grades = {
            {85, 92, 78, 90},   // 学生1:数学,语文,英语,物理
            {76, 88, 95, 82},   // 学生2
            {92, 79, 85, 88}    // 学生3
        };
        
        String[] students = {"张三", "李四", "王五"};
        String[] subjects = {"数学", "语文", "英语", "物理"};
        
        System.out.println("🎓 学生成绩统计系统");
        System.out.println("==================");
        
        // 1. 计算每个学生的平均分
        System.out.println("\n📊 学生平均分:");
        for (int i = 0; i < grades.length; i++) {
            int sum = 0;
            for (int j = 0; j < grades[i].length; j++) {
                sum += grades[i][j];
            }
            double average = (double) sum / grades[i].length;
            System.out.printf("%s: %.2f分\n", students[i], average);
        }
        
        // 2. 计算每门课的平均分
        System.out.println("\n📈 科目平均分:");
        for (int j = 0; j < grades[0].length; j++) {
            int sum = 0;
            for (int i = 0; i < grades.length; i++) {
                sum += grades[i][j];
            }
            double average = (double) sum / grades.length;
            System.out.printf("%s: %.2f分\n", subjects[j], average);
        }
        
        // 3. 找出每门课的最高分
        System.out.println("\n🏆 单科最高分:");
        for (int j = 0; j < grades[0].length; j++) {
            int maxScore = 0;
            String topStudent = "";
            for (int i = 0; i < grades.length; i++) {
                if (grades[i][j] > maxScore) {
                    maxScore = grades[i][j];
                    topStudent = students[i];
                }
            }
            System.out.printf("%s: %s (%d分)\n", 
                subjects[j], topStudent, maxScore);
        }
    }
}

5.2 应用二:图像处理 - 像素矩阵

java 复制代码
public class ImageProcessor {
    // 用二维数组表示黑白图片
    // 0=纯黑, 255=纯白
    public static void main(String[] args) {
        // 5×5像素的简单图像(一个笑脸)
        int[][] image = createSmileyFace();
        
        System.out.println("😊 原图像(笑脸):");
        printImage(image);
        
        // 图像处理1:反色效果
        int[][] inverted = invertImage(image);
        System.out.println("\n🔄 反色效果:");
        printImage(inverted);
        
        // 图像处理2:模糊效果
        int[][] blurred = blurImage(image);
        System.out.println("\n💨 模糊效果:");
        printImage(blurred);
    }
    
    // 创建笑脸图像
    public static int[][] createSmileyFace() {
        int[][] img = new int[5][5];
        
        // 初始化全白
        for (int i = 0; i < 5; i++) {
            Arrays.fill(img[i], 255);
        }
        
        // 画笑脸
        img[1][1] = 0; // 左眼
        img[1][3] = 0; // 右眼
        img[3][1] = 0; // 嘴左
        img[3][2] = 0; // 嘴中
        img[3][3] = 0; // 嘴右
        
        return img;
    }
    
    // 图像反色:黑变白,白变黑
    public static int[][] invertImage(int[][] original) {
        int height = original.length;
        int width = original[0].length;
        int[][] result = new int[height][width];
        
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                result[i][j] = 255 - original[i][j];
            }
        }
        return result;
    }
    
    // 简单模糊:每个像素取周围像素的平均值
    public static int[][] blurImage(int[][] original) {
        int height = original.length;
        int width = original[0].length;
        int[][] result = new int[height][width];
        
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                int sum = 0, count = 0;
                
                // 检查周围的3×3区域
                for (int di = -1; di <= 1; di++) {
                    for (int dj = -1; dj <= 1; dj++) {
                        int ni = i + di, nj = j + dj;
                        if (ni >= 0 && ni < height && nj >= 0 && nj < width) {
                            sum += original[ni][nj];
                            count++;
                        }
                    }
                }
                result[i][j] = sum / count; // 取平均值
            }
        }
        return result;
    }
    
    // 打印图像
    public static void printImage(int[][] image) {
        for (int[] row : image) {
            for (int pixel : row) {
                // 用不同字符表示灰度
                if (pixel == 0) System.out.print("■ ");      // 纯黑
                else if (pixel < 100) System.out.print("▒ "); // 深灰
                else if (pixel < 200) System.out.print("░ "); // 浅灰
                else System.out.print("□ ");                  // 纯白
            }
            System.out.println();
        }
    }
}

5.3 应用三:游戏地图

java 复制代码
public class GameMapSystem {
    // 定义地图元素类型
    static final int EMPTY = 0;      // 空地
    static final int WALL = 1;       // 墙
    static final int TREASURE = 2;   // 宝藏
    static final int PLAYER = 3;     // 玩家
    static final int ENEMY = 4;      // 敌人
    static final int DOOR = 5;       // 门
    
    public static void main(String[] args) {
        // 创建10×10的游戏地图
        int[][] gameMap = createGameMap();
        
        System.out.println("🎮 游戏地图生成完毕!");
        printGameMap(gameMap);
        
        // 移动玩家
        System.out.println("\n🎯 玩家移动中...");
        movePlayer(gameMap, 2, 1);  // 向右移动
        printGameMap(gameMap);
    }
    
    // 创建游戏地图
    public static int[][] createGameMap() {
        int[][] map = new int[10][10];
        
        // 初始化:四周是墙,中间是空地
        for (int i = 0; i < 10; i++) {
            for (int j = 0; j < 10; j++) {
                if (i == 0 || i == 9 || j == 0 || j == 9) {
                    map[i][j] = WALL;  // 边界墙
                } else {
                    map[i][j] = EMPTY; // 内部空地
                }
            }
        }
        
        // 放置障碍物
        map[2][2] = WALL; map[2][3] = WALL;
        map[5][5] = WALL; map[5][6] = WALL;
        map[7][3] = WALL; map[7][4] = WALL;
        
        // 放置宝藏
        map[1][7] = TREASURE;
        map[8][2] = TREASURE;
        map[6][8] = TREASURE;
        
        // 放置敌人
        map[3][7] = ENEMY;
        map[8][6] = ENEMY;
        
        // 放置门
        map[9][5] = DOOR;
        
        // 放置玩家(起始位置)
        map[1][1] = PLAYER;
        
        return map;
    }
    
    // 移动玩家
    public static void movePlayer(int[][] map, int dx, int dy) {
        // 找到玩家当前位置
        int playerX = -1, playerY = -1;
        for (int i = 0; i < map.length; i++) {
            for (int j = 0; j < map[i].length; j++) {
                if (map[i][j] == PLAYER) {
                    playerX = i;
                    playerY = j;
                    break;
                }
            }
        }
        
        // 计算新位置
        int newX = playerX + dx;
        int newY = playerY + dy;
        
        // 检查是否可以移动
        if (newX >= 0 && newX < map.length && 
            newY >= 0 && newY < map[0].length) {
            
            if (map[newX][newY] == EMPTY) {
                // 移动玩家
                map[playerX][playerY] = EMPTY;  // 原位置清空
                map[newX][newY] = PLAYER;       // 新位置放置玩家
                System.out.println("✅ 移动成功!");
            } else if (map[newX][newY] == TREASURE) {
                System.out.println("💰 找到宝藏!游戏胜利!");
                map[playerX][playerY] = EMPTY;
                map[newX][newY] = PLAYER;
            } else if (map[newX][newY] == WALL) {
                System.out.println("🚫 撞墙了!无法移动");
            } else if (map[newX][newY] == ENEMY) {
                System.out.println("💀 遇到敌人!游戏结束");
            } else if (map[newX][newY] == DOOR) {
                System.out.println("🚪 找到出口!游戏通关!");
            }
        } else {
            System.out.println("🚫 超出地图边界!");
        }
    }
    
    // 打印游戏地图
    public static void printGameMap(int[][] map) {
        char[] symbols = {' ', '█', '★', 'P', 'E', 'D'};
        String[] names = {"空地", "墙", "宝藏", "玩家", "敌人", "门"};
        
        System.out.println("\n地图图例:");
        for (int i = 0; i < symbols.length; i++) {
            System.out.println("  " + symbols[i] + " = " + names[i]);
        }
        
        System.out.println("\n当前地图:");
        System.out.println("┌───────────────────┐");
        for (int i = 0; i < map.length; i++) {
            System.out.print("│ ");
            for (int j = 0; j < map[i].length; j++) {
                System.out.print(symbols[map[i][j]] + " ");
            }
            System.out.println("│");
        }
        System.out.println("└───────────────────┘");
    }
}

第六章:数组使用技巧与最佳实践

6.1 数组遍历的四种姿势

java 复制代码
import java.util.Arrays;

public class ArrayTraversalStyles {
    public static void main(String[] args) {
        String[] fruits = {"苹果", "香蕉", "橙子", "葡萄", "芒果"};
        
        System.out.println("🍎 水果数组: " + Arrays.toString(fruits));
        
        // 姿势1:传统for循环 - 最灵活
        System.out.println("\n1. 传统for循环(可控制索引):");
        for (int i = 0; i < fruits.length; i++) {
            System.out.println("  索引 " + i + ": " + fruits[i]);
        }
        
        // 姿势2:增强for循环 - 最简洁
        System.out.println("\n2. 增强for循环(只读遍历):");
        for (String fruit : fruits) {
            System.out.println("  水果: " + fruit);
        }
        
        // 姿势3:while循环 - 灵活控制
        System.out.println("\n3. while循环(手动控制):");
        int index = 0;
        while (index < fruits.length) {
            System.out.println("  第" + (index+1) + "个: " + fruits[index]);
            index++;
        }
        
        // 姿势4:Stream API - 函数式风格
        System.out.println("\n4. Stream API(现代风格):");
        Arrays.stream(fruits)
              .forEach(fruit -> System.out.println("  🍓 " + fruit));
    }
}

6.2 数组常用方法

java 复制代码
import java.util.Arrays;
import java.util.Collections;

public class ArrayUtilsDemo {
    public static void main(String[] args) {
        Integer[] numbers = {3, 1, 4, 1, 5, 9, 2, 6};
        
        System.out.println("原数组: " + Arrays.toString(numbers));
        
        // 1. 排序
        Arrays.sort(numbers);
        System.out.println("排序后: " + Arrays.toString(numbers));
        
        // 2. 反转排序
        Arrays.sort(numbers, Collections.reverseOrder());
        System.out.println("降序后: " + Arrays.toString(numbers));
        
        // 3. 二分查找(必须先排序)
        Arrays.sort(numbers);
        int index = Arrays.binarySearch(numbers, 5);
        System.out.println("数字5的位置: " + index);
        
        // 4. 数组复制
        Integer[] copy = Arrays.copyOf(numbers, numbers.length);
        System.out.println("复制数组: " + Arrays.toString(copy));
        
        // 5. 数组填充
        Integer[] filled = new Integer[5];
        Arrays.fill(filled, 42);
        System.out.println("填充数组: " + Arrays.toString(filled));
        
        // 6. 数组比较
        System.out.println("数组相等: " + Arrays.equals(numbers, copy));
    }
}

第七章:数组的优缺点总结

🎯 数组的优点:

  1. ⚡ 访问速度极快 - 随机访问时间复杂度O(1)
  2. 💾 内存效率高 - 只存储数据,几乎没有额外开销
  3. 🔄 缓存友好 - 连续内存,预加载效果好
  4. 🔧 实现简单 - 所有编程语言原生支持

⚠️ 数组的缺点:

  1. 📏 大小固定 - 创建后难以调整容量(静态数组)
  2. 🚶 插入删除慢 - 平均需要移动O(n)个元素
  3. 🏠 内存要求高 - 需要连续的较大内存空间
  4. 🎯 类型单一 - 只能存储相同类型数据

📊 选择数组的场景:

✅ 适合用数组的情况:

  • 数据量已知或变化不大
  • 需要频繁随机访问
  • 对性能要求较高
  • 实现简单的多维数据结构

❌ 不适合用数组的情况:

  • 数据量变化很大
  • 需要频繁插入删除
  • 内存碎片严重
  • 需要存储不同类型数据

结语:数组是数据结构的基础,更是一门艺术

到这里相信你已经对数组有了全新的认识。数组就像编程世界里的乐高积木,看似简单,却能搭建出各种复杂的数据结构:

  • 链表 = 数组 + 指针
  • 栈 = 数组 + 后进先出规则
  • 队列 = 数组 + 先进先出规则
  • 哈希表 = 数组 + 哈希函数

记住:真正的高手不是会用复杂的数据结构,而是懂得在合适的地方使用最简单的数据结构。


觉得有收获吗?来个一键三连吧!欢迎在评论区分享交流,我们一起进步!

相关推荐
太理摆烂哥20 小时前
数据结构之红黑树
数据结构
hnjzsyjyj20 小时前
洛谷 B4241:[海淀区小学组 2025] 统计数对 ← STL map
数据结构·stl map
泡沫冰@21 小时前
数据结构(18)
数据结构
苏纪云1 天前
数据结构期中复习
数据结构·算法
初听于你1 天前
Java五大排序算法详解与实现
数据结构·算法·排序算法
多多*1 天前
牛客周赛 Round 117 ABCDE 题解
java·开发语言·数据结构·算法·log4j·maven
熬夜敲代码的小N1 天前
仓颉ArrayList动态数组源码分析:从底层实现到性能优化
数据结构·python·算法·ai·性能优化
大白的编程日记.1 天前
【高阶数据结构学习笔记】高阶数据结构之B树B+树B*树
数据结构·笔记·学习
ゞ 正在缓冲99%…1 天前
leetcode1547.切棍子的最小成本
数据结构·算法·leetcode·动态规划
2401_841495641 天前
【LeetCode刷题】移动零
数据结构·python·算法·leetcode·数组·双指针法·移动零