Tại sao chúng ta có cả mảng răng cưa và mảng đa chiều?


87
  1. Sự khác biệt giữa mảng răng cưa và mảng đa chiều là gì. Có lợi ích của cái này trên cái khác không?

  2. Và tại sao Visual Studio không cho phép tôi thực hiện

    MyClass[][] abc = new MyClass[10][20];
    

    (Chúng tôi đã từng làm điều đó trong C ++, nhưng trong C #, nó gạch dưới [20] với dòng uốn éo màu đỏ .. Cho biết chỉ định thứ hạng không hợp lệ)

    nhưng hạnh phúc với

    MyClass[,] abc = new MyClass[10,20];
    
  3. Cuối cùng, làm cách nào để tôi có thể khởi tạo điều này trong một dòng (giống như chúng ta làm trong mảng đơn giản với {new xxx...}{new xxx....})

    MyClass[][,][,] itemscollection;
    

11
Toàn bộ điểm của mảng răng cưa là các mảng "lồng vào nhau" không cần có kích thước đồng nhất.
Ani

1
msdn.microsoft.com/en-us/library/2yd9wwz4(v=vs.71).aspx - Cú pháp mảng đa chiều là [X, Y] hợp lệ theo tài liệu
ndtreviv

Câu hỏi phụ: Có thể sử dụng foreach () với mảng nhiều chiều không?
Serge Wautier

@Serge - tất nhiên, như các Arraythiết bị IEnumerable. Bạn luôn có thể thử nó và xem cho chính mình :)
thecoop

Câu trả lời:


101
  1. Mảng răng cưa là một mảng của các mảng, do đó, an int[][]là một mảng int[], mỗi mảng có thể có độ dài khác nhau và chiếm khối riêng của chúng trong bộ nhớ. Mảng nhiều chiều ( int[,]) là một khối bộ nhớ (về cơ bản là một ma trận).

  2. Bạn không thể tạo một MyClass[10][20]vì mỗi mảng con phải được khởi tạo riêng biệt, vì chúng là các đối tượng riêng biệt:

    MyClass[][] abc = new MyClass[10][];
    
    for (int i=0; i<abc.Length; i++) {
        abc[i] = new MyClass[20];
    }
    

    A MyClass[10,20]là ok, vì nó đang khởi tạo một đối tượng duy nhất dưới dạng ma trận với 10 hàng và 20 cột.

  3. A MyClass[][,][,]có thể được khởi tạo như vậy (mặc dù không kiểm tra biên dịch):

    MyClass[][,][,] abc = new MyClass[10][,][,];
    
    for (int i=0; i<abc.Length; i++) {
        abc[i] = new MyClass[20,30][,];
    
        for (int j=0; j<abc[i].GetLength(0); j++) {
            for (int k=0; k<abc[i].GetLength(1); k++) {
                abc[i][j,k] = new MyClass[40,50];
            }
        }
    }
    

Hãy nhớ rằng CLR được tối ưu hóa rất nhiều cho quyền truy cập mảng một chiều, vì vậy việc sử dụng mảng răng cưa có thể sẽ nhanh hơn so với mảng nhiều chiều có cùng kích thước.


6
bạn có thể chỉ cho chúng tôi một số bằng chứng cho thấy truy cập mảng một chiều nhanh hơn không?
GreyCloud


Có trường hợp sử dụng (chung) nào cho mảng nhiều chiều không?
ryanwebjackson

1
Ví dụ: bảng ca rô var board = new Piece[8, 8];, ma trận biến đổi var m = new double[2, 2]; .
Olivier Jacot-Descombes

37

Mảng răng cưa là một mảng của các mảng. Mỗi mảng không được đảm bảo có cùng kích thước. Bạn có thể có

int[][] jaggedArray = new int[5][];
jaggedArray[0] = new[] {1, 2, 3}; // 3 item array
jaggedArray[1] = new int[10];     // 10 item array
// etc.

Đó là một tập hợp các mảng có liên quan.

Mặt khác, mảng nhiều chiều là một nhóm gắn kết hơn, chẳng hạn như hộp, bảng, khối lập phương, v.v., nơi không có độ dài bất thường. Điều đó có nghĩa là

int i = array[1,10];
int j = array[2,10]; // 10 will be available at 2 if available at 1

Tôi đã thử mã của bạn. Nó không biên dịch. Hãy thử thêm int [3] so Try jaggedArray[0] = int[3]{ 1, 2, 3 };
barlop

Tôi biết điều này là cũ, nhưng chỉ dành cho mục đích thông tin int [3] không cần thiết. một int [] đơn giản là tất cả những gì quan trọng. int [] [] myArray = new int [5] []; myArray [0] = new int [] {1, 2, 3, 4}; Đây là tất cả những gì cần thiết.
Velocibadgery

Bạn có thể lấy nó để biên dịch trong C # không? Tôi không thể biên dịch jaggedArray[0] = { 1, 2, 3 };trừ khi tôi thay đổi nó thành = new[] { 1, 2, 3 }(hoặc = new int[] { 1, 2, 3 }trước C # 3.0). Theo Hướng dẫn lập trình C # của Microsoft , "Bạn có thể khai báo một biến mảng mà không cần tạo nó, nhưng bạn phải sử dụng toán tử mới khi bạn gán một mảng mới cho biến này."
Joel V. Earnest-DeYoung,

11

Một mảng hình chữ nhật luôn có cùng số lượng cột cho mọi hàng.

MyClass[,] x = new MyClass[10,30]

Mỗi hàng có 30 cột, trong khi trong một mảng răng cưa, điều này không bắt buộc. Do đó, tôi nghĩ bạn sẽ phải khởi tạo mọi 'hàng' trong một mảng răng cưa riêng biệt:

MyClass[][] x = new MyClass[10][];

for(int i = 0; i < 10; i++)
{
    x[i] = new MyClass[30];
}

Trên thực tế, điều này có nghĩa là không phải mọi hàng trong mảng răng cưa đều phải chứa cùng một số phần tử. (Trong ví dụ của tôi, nó có cùng một số phần tử, nhưng điều này không bắt buộc).

Bạn hoàn toàn có thể làm điều này, ví dụ:

MyClass[][] x = new MyClass[10][];

for(int i = 0; i < 10; i++)
{
    x[i] = new MyClass[(30 + i)];
}

Đây có thể là một bài viết thú vị cho bạn.


5

Quảng cáo 3) Để khởi tạo một con quái vật như vậy [][,][,], bạn có thể làm như sau:

        int [,][,] multiArr1 = { { new int[,] { { 2, 2 }, { 1, 1 } },
                                     new int[,] { { 2, 2 }, { 1, 1 } } },
                                     { new int[,] { { 2, 2 }, { 1, 1 } },
                                         new int[,] { { 2, 2 }, { 1, 1 } } } };
        int [,][,] multiArr2 = { { new int[,] { { 2, 2 }, { 1, 1 } },
                                     new int[,] { { 2, 2 }, { 1, 1 } } },
                                     { new int[,] { { 2, 2 }, { 1, 1 } },
                                         new int[,] { { 2, 2 }, { 1, 1 } } } };

        int [][,][,] superMultiArray = { multiArr1, multiArr2 };

1

Nếu bạn đang tìm kiếm một mảng đa chiều đã đặt giới hạn, hãy luôn sử dụng [,] cú pháp kiểu. Điều này sẽ đảm bảo rằng mỗi phần có kích thước như nhau.

Khi bạn sử dụng [][]những gì thực sự diễn ra là bạn đang tạo một mảng các mảng. Điều này có nghĩa là mỗi mảng có thể có kích thước khác nhau. Ví dụ:

int[][] jaggedArray = new int[5][]
for(int index = 0; index < jaggedArray.Length ; ++index)
{
    jaggedArray[index] = new int[index + 1];
}

1

Khai báo nội tuyến sẽ trông giống như sau:

int[,] numbers = { {1, 2}, {3, 4}, {5, 6} };

1

Đối với # 1, hãy xem câu hỏi SO này

Đối với mảng nội tuyến có răng cưa hoặc nhiều chiều, hãy xem hướng dẫn lập trình này :

// Three-dimensional array.
int[, ,] array3D = new int[,,] { { { 1, 2, 3 }, { 4, 5, 6 } },
{ { 7, 8, 9 }, { 10, 11, 12 } } };

// Same array with dimensions specified at declaration.
int[, ,] array3Da = new int[2, 2, 3] { { { 1, 2, 3 }, { 4, 5, 6 } },
{ { 7, 8, 9 }, { 10, 11, 12 } } };

Bạn không cần phải chỉ định các thứ nguyên (array3D), nhưng nếu bạn biết chúng sẽ không bao giờ thay đổi, thì sẽ rất hữu ích khi biết bạn đang sử dụng thứ nguyên nào (array3Da).


0

Bạn sẽ cần hiểu hoạt động bên trong của mảng, mảng nhiều chiều hoạt động như một mảng đơn chiều ngoại trừ việc lập chỉ mục kép được chuyển đổi thành một chỉ mục duy nhất.

Mảng răng cưa của bạn trong c # là một mảng các đối tượng lần lượt là các mảng.


0

Tôi nghĩ rằng cấp phát bộ nhớ mảng răng cưa 2d trong C # giống như mảng 2d trong C ++ và C. Bởi vì mảng răng cưa 2d có con trỏ trỏ đến mảng con trỏ mà mỗi con trỏ này trỏ đến một mảng phần tử (ví dụ phần tử nguyên); như mã này trong C ++,

int** 2DArr {new int* [number1]};
for (int i = 0; i < number1; i++)
{
   2DArr[i] = new int[number2];
}

phân bổ bộ nhớ của mã dưới đây giống như mảng răng cưa 2d trong C #. Nhưng tôi nghi ngờ về điều đó, bạn có thể vui lòng giải thích thêm nếu tôi nghĩ sai.


0

Bài đăng này đã cũ nhưng đây là suy nghĩ của tôi về điều đó.

Mảng răng cưa là mảng nhiều chiều. Mảng đa chiều có hai loại: hình chữ nhật và hình răng cưa. Mảng hình chữ nhật đại diện cho một khối bộ nhớ n chiều và mảng răng cưa là mảng của mảng.

Mảng hình chữ nhật

Mảng hình chữ nhật được khai báo bằng cách sử dụng dấu phẩy để phân tách từng kích thước. Câu lệnh sau khai báo một mảng hai chiều hình chữ nhật, trong đó kích thước là 3 × 3:

int[,] matrix = new int [3, 3]; 

Mảng răng cưa

Mảng răng cưa được khai báo bằng cách sử dụng dấu ngoặc vuông liên tiếp để đại diện cho mỗi chiều. Đây là một ví dụ về khai báo một mảng hai chiều răng cưa, trong đó kích thước ngoài cùng là 3:

int[][] matrix = new int[3][];

0

Đối với một mảng nhiều chiều, hãy nghĩ đến một hình hộp hoặc hình chữ nhật. Mỗi hàng có cùng độ dài và mỗi cột có cùng độ dài.

Trong một mảng răng cưa, các hàng và cột có thể không có cùng kích thước. Ví dụ: các cột hoặc hàng có thể có kích thước khác nhau. Điều này sẽ dẫn đến một hình dạng có thể không phải là một đường thẳng xuống các cạnh như hình chữ nhật. Thay vào đó, các bên có thể bị lởm chởm .

Bây giờ tôi đã sử dụng 2 chiều / 2 mảng cho ví dụ này, nhưng điều này áp dụng cho nhiều thứ hơn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.