1. 程式人生 > >《隨筆十二》——C#中的 “ 一維陣列、矩形陣列、交錯陣列(鋸齒陣列)”

《隨筆十二》——C#中的 “ 一維陣列、矩形陣列、交錯陣列(鋸齒陣列)”

目錄

陣列的型別

陣列是物件

定義和初始化一維陣列

定義和初始化矩形陣列

初始化和定義交錯陣列(鋸齒陣列)

交錯陣列中的矩形陣列

比較矩形陣列 和交錯 陣列


●   陣列實際上是由一個變數名稱表示的一組同類型的資料元素,是一組相同型別的集合。 我們首先了解一下陣列中的一些重要定義開始:

秩/ 維度 : 陣列可以有任何為正數的維度數, 陣列的維度稱作秩。 意思就是說,該陣列是幾維陣列 ,[  ] 表示一維陣列, [ , ]  表示二維陣列。

維度長度: 陣列的每一個維度的長度, 就是這個方向的位置的元素個數.

陣列長度: 陣列的所有維度中的元素的總和稱為陣列的長度。

●   注意點:

陣列一旦建立並且初始化,大小就固定了,C# 不支援動態陣列。

陣列的索引從0開始。那麼陣列中的元素個數的索引範圍是 從0 到 n-1


陣列的型別


●  C#中有兩種型別的陣列,分別為一維陣列和多維陣列,多維陣列中還分矩形陣列和 交錯陣列(也稱為 鋸齒陣列)。

一維陣列: 指的是一組地址連續的相同型別的單行元素序列。

多維陣列:有多個秩,其中每一行的元素個數都相同。 不管多少維度,總是使用一個方括號,例如:

 ​​​​​​​ doule[,] myDouble = new double[3,4];

交錯陣列(也稱為 鋸齒陣列):有多個秩,其中每一行的元素個數不一定都相同。然後呢,為陣列的每一個維度使用一對方括號:


 int[][] myInt = new int[3][] { new int[] { 1, 2, 3 }, new int[] { 1 }, new int[] { 1, 2 } }; //正確

該陣列就是:

1  2  3  // 第一行

1         // 第二行
 
1 2 

 


陣列是物件


●   陣列的例項是從 System.Array 繼承的物件。那麼陣列是引用型別, 陣列的引用在棧上或者堆上, 陣列的元素總是在堆上。如圖:


●  陣列雖然是引用型別, 但是陣列的元素 可以是值型別, 也可以是引用型別(比如類)。

如果儲存的元素都是值型別, 陣列被稱為值型別陣列。

如果儲存的元素都是引用型別物件, 該陣列被稱為 引用型別陣列。

 


定義和初始化一維陣列


●  陣列在必須在訪問之前初始化,不能像這樣訪問陣列或者給陣列元素賦值:

int[] myIntArray;
myIntArray[10] = 5;  //錯誤, 該陣列沒有初始化

●  陣列初始化的第一種方式是:用字面值形式指定陣列的完整內容。該陣列的長度編譯器可以通過陣列中的元素個數來推斷長度。

int [] array= {0,1,2,3,4,5};

● 第二種方式是:指定陣列的大小,然後使用new來初始化陣列,但是該陣列的每一個元素都被自動初始化為該陣列型別的預設值。 對於預定義型別, 整型預設為 0,浮點型預設值為0.0, 布林型預設值為 false,  引用型別 預設值為 null。

int []intArr =new int[4];
該陣列執行的是預設初始化,並沒有真正的初始化


● 第三種方式是:組合上面的初始化方式:

int [] array = new int[5] {0,1,2,3,4};
 
int [] array = new int[10] {0,1,2,3,4}; //錯誤

注意:使用這樣的方式陣列的大小與元素個數必須一致,否則錯誤。

● 第四種方式是:組合上面的初始化方式: 這樣就不必輸入陣列的長度, 編譯器可以通過元素個數來判斷。

   int[] array = new int[] { 0, 1, 2, 3, 4 };

● 第五種方式是:也可以使用非常量的變數來進行初始化(c++ 中不可以這樣):

int a = 6;
int[] array = new int[a]; //輸出 6個0

int a = 6;
int[] array = new int[a];
array[0] = 12; //給第一個元素,初始化
for (int tt = 0; tt < a; ++tt)
{
   array[tt] = tt * 1;  // 迴圈給每一個元素初始化
}

● 第六種方式是:如果想使用非常量的變數來進行初始化,並且同時指定陣列元素的初始值,那麼該變數,必須是個常量:

const int arraySize = 5;
int[] myIntArray=new int[arraySize] {0,1,2,3,4};
 
 
const int arraySize = 4;
 int[] myIntArray = new int[arraySize] { 0, 1, 2 }; //錯誤,陣列大小和元素個數不一致

如果省略了關鍵字const,語法錯誤。注意:  這樣寫,陣列的大小與元素個數必須一致,否則錯誤。


定義和初始化矩形陣列


 ●  要顯式初始化矩形陣列,需要注意的有:

每一個初始值元素必須封閉在大括號內。

每一個維度也必須巢狀並封閉在大括號內。

除了初始值,每一個維度的初始化列表和組成部分也必須使用逗號分隔。

矩形陣列初始化的第一種方式:

  int[,] array = new int[,] { { 10,1},{ 2,10},{ 11,9} };

 

第二種方式:

    ​​​​​​​ double[,] myDouble = new double[3, 4];

第三種方式:這個通過字面值賦值,隱式定義了陣列的維度。


double[,] myDouble = {{1,2,3,4},{2,3,4,5},{3,4,5,6}};

第四種方式:

int c = 3, a = 4;
int[,] myInt = new int[c, a];  //正確

第五種方式:

             const int a = 3;
            const int b = 2;
            int[,] array = new int[a, b] { { 10, 1 }, { 2, 10 }, { 11, 9 } };

第六種方式:

 ​​​​​​​ double[,] myDouble = new double[3,4] { { 1, 2, 3, 4 }, { 2, 3, 4, 5 }, { 3, 4, 5, 6 } };

其實初始化的方式跟一維陣列的類似,只是維數不同罷了。

 


隱式型別陣列 (var關鍵字)


 ●  陣列可以是隱式型別的,比如:

當初始化陣列時,我們使用關鍵字 var, 可以讓編譯器根據初始化語句的型別來推斷陣列型別。

             int[] arr = new int[] { 10, 20 }; //一維陣列
            var arr2 = new[] { 10, 20, 30 };

            int[,]arr3=new int[,]{ { 1,2},{ 2,4} };
            var arr4=new[,] { { 1, 2 }, { 2, 4 } };

注意: 在隱式型別 arr4 宣告中, 我們仍然需要在初始化中提供 秩說明符。

看一個小程式碼:

           var myDouble =new[,] { { 1, 2, 3, 4 }, { 2, 3, 4, 5 }, { 3, 4, 5, 6 } };
            foreach (double height in myDouble)
            {
                WriteLine(height);
            }

初始化和定義交錯陣列(鋸齒陣列)


 ●  還有交錯陣列,其中每行的元素個數可能不同,其中的每一個元素都是包含另外一個數組。但是注意:這些陣列都必須有相同的基本型別。 例如:

 int[][] jagArr = new int[3][];

 ●   交錯陣列的宣告語法要求每一個維度都要有一對獨立的方括號。 方括號的數量決定了交錯陣列的維度。

交錯陣列可能的維度可以是大於1的任意整數。

和矩形陣列一樣, 在陣列型別的[ ] 號中不允許寫陣列的維度長度。

int[][] arr; //維度是2

 ●  交錯陣列第一種初始化方式:

 int[][] jagArr = new int[3][];

不能這樣宣告:

int[][] myInt =new[3][4];

也不可以這樣:

 int[][] myInt = { { 1, 3, 4 }, { 2, 3, 4, 5 }, { 22, 3 } };

 ● 第二種初始化方式: 

            int[][] Arr = new int[3][]; //例項化頂層陣列
//在陣列下標為0的位置, 該位置有又是一個數組,裡面有2個數字,元素個數不可以多,也不可以少
            Arr[0] = new int[2] { 10, 20}; //例項化頂層陣列
            Arr[1] = new int[4] { 40, 2, 3, 4 };  //例項化子陣列
            Arr[2] = new int[5] { 1, 2, 3, 4, 5 }; //例項化子陣列

 ● 第三種初始化方式:

             int[][] Arr = new int[3][];  //例項化頂層陣列
            //在陣列下標為0的位置, 該位置有又是一個數組,[]不指定子陣列的維度,讓編譯器根據元素個數去判斷
            Arr[0] = new int[] { 10, 20,30};  //例項化子陣列
            Arr[1] = new int[] { 40, 50, 60, 70 }; //例項化子陣列
            Arr[2] = new int[] { 80, 90, 100, 110, 120 }; //例項化子陣列

在第二種和第三種初始化方式要注意的是: 在程式碼中, 每一個子陣列的引用都賦值給了頂層陣列的元素。

 

 ● 第四種初始化方式:


            int[][] myInt = new int[3][] { new int[] { 1, 2, 3 }, new int[] { 1 }, new int[] { 1, 2 } }; //正確
            foreach (int[] divisor in myInt)
            {
                foreach (int temp in divisor)
                {
                    WriteLine(temp);
                }
            }

該交錯陣列有三行,new int[] { 1, 2, 3 } 表示,陣列下標為0的地方有3個元素, new int[] { 1 } 表示陣列下標為1的地方有1個元素,new int[] { 1, 2 } }表示陣列下標為2的地方有2個元素.  最後使用巢狀的 foreach 迴圈輸出 交錯陣列全部元素。

第五種初始化方式:

             int[][] myInt = { new int[] { 1, 2, 3 }, new int[] { 1 }, new int[] { 1, 2 } }; //正確
            foreach (int[] divisor in myInt)
            {
                foreach (int temp in divisor)
                {
                    WriteLine(temp);
                }
            }

 


交錯陣列中的矩形陣列


 ●   由於交錯陣列中的子陣列本身就是陣列, 因此交錯陣列中也可能有矩形陣列。 第六種初始化方式:

namespace HelloWorld_Console
{
 
    class Program
    {
        static void Main(string[] args)
        {

                   
          int[][,] Arr = new int[3][,];  // 例項化帶有3個二維陣列的交錯陣列
            Arr[0] = new int[,] { { 10, 20 },
                            { 100, 200 } };

            Arr[1] = new int[,] { { 30, 40, 50 },
                            { 300, 400, 500 } };

            Arr[2] = new int[,] { { 60, 70, 80, 90 },
                            { 600, 700, 800, 900 } };

            for (int i = 0; i < Arr.GetLength(0); i++)
            {
                for (int j = 0; j < Arr[i].GetLength(0); j++)
                {
                    for (int k = 0; k < Arr[i].GetLength(1); k++)
                    {
                        Console.WriteLine
                                 ("[{0}][{1},{2}] = {3}", i, j, k, Arr[i][j, k]);
                    }
                    Console.WriteLine("");
                }
                Console.WriteLine("");
            }
            ReadKey();
        }
    }
}

輸出結果為:

[0][0,0] = 10
[0][0,1] = 20

[0][1,0] = 100
[0][1,1] = 200


[1][0,0] = 30
[1][0,1] = 40
[1][0,2] = 50

[1][1,0] = 300
[1][1,1] = 400
[1][1,2] = 500


[2][0,0] = 60
[2][0,1] = 70
[2][0,2] = 80
[2][0,3] = 90

[2][1,0] = 600
[2][1,1] = 700
[2][1,2] = 800
[2][1,3] = 900

程式碼中使用了陣列的繼承 System.Array 的GetLength (int n) 方法來獲取陣列中指定維度的長度。

 


比較矩形陣列 和交錯 陣列


矩形陣列和交錯陣列的結構區別非常大。下圖演示了 3*3 的矩形陣列以及一個由3 個長度為3 的一維陣列構成的交錯陣列的結構。

首先兩個陣列都儲存了9個整數, 但是它們的結構去很不同。

矩形陣列只有單個數組物件, 而交錯陣列有4個數組物件 。

注意: 一維陣列有特定的指令用於效能優化, 矩形陣列沒有這些指令, 並且不在相同級別進行優化。 因此, 有時使用一維陣列(可以被優化)的交錯陣列比矩形陣列(不能被優化) 更有效率。

​​​​​​​