Duyệt qua Mảng 2D
Đã giới thiệu| English | Ý nghĩa |
|---|---|
| nested loops/ˈnestɪd luːps/ | vòng lặp lồng nhau |
| row-major order/rəʊ ˈmeɪdʒə ˈɔːdə/ | thứ tự theo hàng |
| enhanced for/enˈhænst fɔː/ | vòng lặp for tăng cường |
Một lưới hình chữ nhật làm lộ ra giới hạn vòng lặp sai
- Lưới có hai hàng và ba cột. Một vòng lặp bị giới hạn bởi g.length cho cả hai chỉ mục chỉ truy cập hai cột đầu tiên.
- Sử dụng r < g.length và, với mỗi hàng, c < g[r].length. Điều này cũng xử lý các hàng có độ dài khác nhau, trong khi g[0].length giả định một lưới hình chữ nhật không rỗng.
Vòng lặp lồng nhau cho ma trận
- Để truy cập mọi ô của một mảng 2-D, hãy sử dụng vòng lặp lồng nhau (từ Unit 2). Vòng lặp ngoài duyệt hàng, vòng lặp trong duyệt cột:
for (int r = 0; r < g.length; r++) { for (int c = 0; c < g[r].length; c++) { ... g[r][c] ... } }Vòng lặp trong quét hết một hàng trước khi vòng lặp ngoài di chuyển sang hàng tiếp theo.
Thứ tự hàng trước (Row-major order)
- Sự lồng ghép này truy cập các ô theo thứ tự ưu tiên hàng: tất cả hàng 0, rồi hàng 1, …
g[0][0], g[0][1], …, g[1][0], g[1][1], … - Đây là thứ tự đọc tự nhiên — từ trái sang phải, từ trên xuống dưới. Đối với lưới hình chữ nhật không rỗng, cột có thể là vòng lặp ngoài để truy cập các ô theo từng cột. Mảng lộn xộn (ragged array) cần chính sách rõ ràng cho các cột mà một số hàng không chứa.
Phiên bản for-each
- Một vòng lặp enhanced for trên mảng 2-D cung cấp một hàng (một mảng 1-D) tại một thời điểm.
for (int[] row : g) { for (int x : row) { ... x ... } } - Biến ngoài là cả một hàng; biến trong duyệt các giá trị của hàng đó. Biến vòng lặp nguyên thủy không cập nhật các ô đã lưu khi được gán lại. Biến hàng vẫn là một tham chiếu, vì vậy vòng lặp trong dùng chỉ mục có thể sửa đổi
row[c].
Duyệt theo hàng (Row-major traversal)
Vòng lặp ngoài duyệt hàng, vòng lặp trong duyệt cột: 1,2,3,4,5,6.
Mẫu hình nào trong số các mẫu hình dưới đây sẽ truy cập mọi ô của mảng nguyên 2-D không rỗng mà tham chiếu đến dòng đều không rỗng?
Độ khó 1/5 · 100 xu + một phần thưởng nhỏ cho lần hoàn thành đầu tiên trong ngày
Ngoài duyệt hàng, trong duyệt cột.
Vòng lặp ngoài của phép duyệt 2-D theo hàng được hiển thị nên bị giới hạn bởi...
Độ khó 1/5 · 100 xu + một phần thưởng nhỏ cho lần hoàn thành đầu tiên trong ngày
Vòng lặp hàng ngoài sử dụng g.length; vòng lặp ô trong sử dụng g[r].length, điều này xử lý các độ dài hàng không bằng nhau.
Đối với lưới 2 hàng, 3 cột, vòng lặp lồng nhau truy cập bao nhiêu ô?
Độ khó 2/5 · 140 xu + một phần thưởng nhỏ cho lần hoàn thành đầu tiên trong ngày
hàng × cột = 2 × 3 = 6.
Duyệt theo hàng truy cập các ô theo thứ tự...
Độ khó 1/5 · 100 xu + một phần thưởng nhỏ cho lần hoàn thành đầu tiên trong ngày
Duyệt theo hàng = từ trái sang phải, từ trên xuống dưới.
Trong for (int[] row : g), biến row là...
Độ khó 1/5 · 100 xu + một phần thưởng nhỏ cho lần hoàn thành đầu tiên trong ngày
Biến for-each ngoài là một mảng hàng.
Việc sử dụng g.length cho cả hai giới hạn vòng lặp luôn gây ra ngoại lệ trên bất kỳ lưới chữ nhật phi vuông nào.
Độ khó 1/5 · 100 xu + một phần thưởng nhỏ cho lần hoàn thành đầu tiên trong ngày
Sai: trong lưới 2-hàng, 3-cột nó chỉ truy cập hai cột và vô tình bỏ sót các ô. Trong lưới cao hơn rộng nó có thể chạy vượt qua giới hạn dòng.
Giới hạn đúng cách
- Giới hạn ngoài:
r < g.length(số hàng). Giới hạn trong:c < g[r].length(độ dài của hàng hiện tại). Sử dụng độ dài sai cho một vòng lặp là một lỗi tinh vi trong các lưới không vuông. - Đối với lưới hình chữ nhật không rỗng,
g[0].lengthcũng cho biết số lượng cột chung, và thân vòng lặp trong chạyrows × columnslần. Đối với các hàng lộn xộn, hãy cộng tổng độ dài các hàng; tất cả các tham chiếu hàng phải khác null.
Sử dụng g.length cho số hàng và g[r].length cho số ô của hàng hiện tại. Sử dụng số hàng làm cả hai giới hạn có thể bỏ sót các cột trong lưới rộng hoặc vượt quá giới array trong lưới cao. Một mảng ngoài rỗng không cần truy cập g[0]; một hàng null cần chính sách xử lý rõ ràng trước khi đọc độ dài của nó.
Order the cells visited in row-major traversal of a 2×2 grid.
Độ khó 3/5 · 200 xu + một phần thưởng nhỏ cho lần hoàn thành đầu tiên trong ngày
The inner loop finishes one row before the outer loop advances.
Đối với int[][] g = {{1, 2, 3}, {}, {4}};, số ô nào được duyệt khi đi qua từng hàng?
Độ khó 2/5 · 140 xu + một phần thưởng nhỏ cho lần hoàn thành đầu tiên trong ngày
Cộng độ dài các hàng: 3 + 0 + 1 = 4. Hàng rỗng không đóng góp ô nào.
Tính tổng mảng 2-D:
for (int r = 0; r < g.length; r++)for (int c = 0; c < g[r].length; c++)sum += g[r][c];— truy cập tất cả các ô theo từng hàng, giả định không có hàng nào là null.
Mở rộng suy luận sang trường hợp mới
- Đối với
int[][] g = {{1, 2, 3}, {}, {4}};, độ dài các hàng là 3, 0 và 1. Các giới hạn theo từng hàng truy cập bốn ô và tổng là 10;g[0].lengthkhông phải là giới hạn hợp lệ cho mọi hàng. - Bạn có thể sửa đổi hàng [c] bằng vòng lặp trong có chỉ số; gán lại một biến nguyên x trong vòng lặp tăng cường bên trong sẽ không cập nhật một ô.
Duyệt qua mảng 2-D bằng vòng lặp lồng nhau: vòng ngoài theo các hàng (r < g.length), vòng trong theo các cột (c < g[r].length), truy cập g[r][c]. Điều này thăm các ô theo thứ tự chính hàng (tổng độ dài hàng; rows × columns cho lưới hình chữ nhật). Một enhanced for (for (int[] row : g)) trả về tham chiếu đến một hàng mỗi lần; gán cho biến vòng lặp nguyên bên trong không thay đổi một ô được lưu trữ.