天天看點

二維數組名代表什麼_C#學習筆記04--排序/查找/二維數組/交叉數組

一. 冒泡排序(重點)

思路:

每次比較把較小的放在前面, 大的放到後面;

圖解:

下圖是最壞情況下的排序

二維數組名代表什麼_C#學習筆記04--排序/查找/二維數組/交叉數組

冒泡排序m個元素, 就有(m-1)趟排序, 第一趟m-1次, 第二趟 m-2次.... 總結下來就是趟數加上次數就等于總的元素數;

核心算法:
int[] intNums = new int[] { 5, 4, 3, 2, 1 };
            int temp;
            // 第一層循環 控制趟數 n - 1 趟
            for (int i = 0; i < intNums.Length - 1 ; i++)
            {
                // 第二層循環 控制次數 n - i, 因為下标是從 0 開始的, 所有還要再減1 , 要不然會溢出
                for (int j = 0; j < intNums.Length - 1 - i; j++)
                {
                    // 判斷 元素大小 進行交換
                    if (intNums[j] > intNums[j + 1])
                    {
                        temp = intNums[j];
                        intNums[j] = intNums[j + 1];
                        intNums[j + 1] = temp;
                    }
                }
            }
            foreach (int item in intNums)
            {
                Console.WriteLine(item);
            }
           
優化:

上述寫的代碼有個很大的問題, 總體效率太低. 隻有當數組初始排序是最壞情況的時候, 才需要走完所有的趟數和次數(兩層循環). 但如果初始排序時已經有一部分是有序的, 例如 {5, 1, 2, 3, 4}這樣的一個順序, 當執行完一趟的時候 其實已經得到了最終的結果, 沒有必要再進行一趟趟的循環.

當資料量小的時候影響還不是很大, 但是如果數量上升到一定等級這個時間消耗就很可怕了. 是以我們有必要對它進行一些優化; 如果已經排好順序就可以提前終止循環, 那麼如何判斷?

顯而易見, 當一趟中沒有發生任何交換, 即内層for循環裡的if如果沒有被激活, 就代表順序已經排好了. 那麼我們就可以用一個标簽來進行記錄.

int[] intNums = new int[] { 5, 4, 3, 2, 1 };
            int temp;
            bool tag = true; //定義一個tag标簽 用來進行判斷 
            // 在循環條件中加一個邏輯與運算符, 如果tag為true那麼就繼續進行循環, 如果為false就終止循環, 不用使用break來終止了;
            for (int i = 0; i < intNums.Length - 1 && tag; i++)
            {
                tag = false; // 這裡是必不可少的, 少了tag 就會一直為真, 無法起到終止循環的目的.
                for (int j = 0; j < intNums.Length - 1 - i; j++)
                {
                    if (intNums[j] > intNums[j + 1])
                    {
                        // 如果激活了 if 語句, 就讓 tag 為真, 表示循環還需要繼續執行
                        tag = true;
                        temp = intNums[j];
                        intNums[j] = intNums[j + 1];
                        intNums[j + 1] = temp;
                    }
                }
            }
            foreach (int item in intNums)
            {
                Console.WriteLine(item);
            }
           

二.選擇排序

思路:

以數組 array = {5, 4, 3, 2, 1}為例:

第一趟用第一個元素和剩下的元素比較大小, 找到最小的元素, 然後把它的下标和值記錄下來, 這一趟結束後将其和第一個元素進行交換;

第二趟用第二進制素和它之後的元素進行比較, 找到最小值, 最後再進行交換, 以此類推.

總的來說就是, 每趟找到數組中最小的數,将它們依次放到前面來.

圖解:
二維數組名代表什麼_C#學習筆記04--排序/查找/二維數組/交叉數組
核心算法:
int[] array = new int[] { 5, 4, 3, 2, 1 };

            for (int i = 0; i < array.Length - 1; i++)
            {
                int min = array[i]; // min用來存放最小值
                int index = i; // index就用來存放最小值的下标
                for (int j = i + 1; j <= array.Length - 1; j++)
                {
                    if (min > array[j])
                    {
                        min = array[j];
                        index = j;
                    }
                }
                array[index] = array[i];
                array[i] = min;


            }
            foreach (int item in array)
            {
                Console.Write(item + " ");
            }    
           

三.二分查找

查找元素在開發中經常會使用到, 沒有任何技巧的查找方法就是一個個周遊, 對比我們的期望元素. 這種查找方法有一個非常緻命的缺點, 在資料量龐大時, 對性能的消耗非常大; 是以我們還需要學習一些有關查找的算法, 今天就介紹一下二分查找.

說明:

二分查找又稱為折半查找, 這種查找是有前提的:

要查找的數組必須是有序的,

升序和降序均可; 以升序數組為例, 首先拿到已知元素(num)與數組中間位置的元素(mid)進行比較, 如果 mid > num, 說明 mid右邊的數一定都比num大, 那麼就可以把mid右邊的數都pass, 直接從mid 左邊的數裡查找有沒有num. 同理, 如果mid < num , 就說明mid左邊的數都小于num , 就可以把它們都pass了. 這樣反反複複直到查找到num為止.

圖解:
二維數組名代表什麼_C#學習筆記04--排序/查找/二維數組/交叉數組
核心算法:
int[] sortNums = new int[] { 5, 12, 16, 36, 45, 99, 102 };
            int start = 0, end = sortNums.Length - 1; // 定義開頭和結尾的旗
            Console.WriteLine("請輸入你想要查找的數:");
            int num = int.Parse(Console.ReadLine());
            while(start <= end) // 如果start > end說明num不在查找的數組裡, 就可以終止循環了
            {

                int mid = (start + end) / 2; // 每次都用中間的元素和num比較
                if (sortNums[mid] > num)
                {
                    // 如果 mid 大于 num 說明 mid 右邊的數都比num大就沒有比較的必要了, 把 end 放到mid-1的位置來.
                    end = mid - 1;
                    
                }
                else if(sortNums[mid] < num)
                {
                    start = mid + 1;
                }
                else
                {
                    Console.WriteLine("查到了, 在第 {0} 個位置", mid + 1);
                    break;
                }
            }
            if (start > end)
            {
                Console.WriteLine("對不起元素沒有找到.");
            }
           

四.二維數組(重點)

4.1二維數組的聲明和初始化 聲明
資料類型[,] 數組名= new 資料類型[行數, 列數];
初始化

: 分為動态初始化和靜态初始化 , 花括号裡面的各個花括号代表一行

第一種動态初始化:

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

第二種動态初始化:

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

靜态初始化:

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

注意: 二維數組靜态初始化定義時, 行數可以是任意的, 但是列數必須是相同的, 即 每個内層花括号中元素的個數必須要相同.

4.2 二維數組的周遊

C#中通過 GetLength方法可以得到二維數組的行數和列數

array.GetLength(0) 得到行數;

array.GetLength(1) 得到列數;

int[,] array = new int[2, 3] { { 7, 6, 3 }, { 2, 8, 5 } };
for(int i = 0; i < array.GetLength(0); i++)
{
       for(int j = 0; j < array.GetLength(1); j++)
       {
            Console.Write(array[i, j] + " " );
       }
        Console.WriteLine();
}
           
練習

1.定義一個數組, 将該數組的轉置存到另一個數組中;

int[,] array = new int[2, 3] { { 7, 6, 3 }, { 2, 8, 5 } };
            int[,] newArray = new int[array.GetLength(1), array.GetLength(0)];
             for(int i = 0; i < array.GetLength(0); i++)
            {
                for(int j = 0; j < array.GetLength(1); j++)
                {
                    newArray[j, i] = array[i, j];
                }
            }



            Console.WriteLine("轉置為:");
            for (int i = 0; i < newArray.GetLength(0); i++)
            {
                for (int j = 0; j < newArray.GetLength(1); j++)
                {
                    Console.Write(newArray[i, j] + " ");
                }
                Console.WriteLine();
            }     
           

2.有一個3行4列的二維數組, 要求程式設計找出最大元素, 并輸出所在的行和列.

int[,] array = new int[,] { { 25, 6, 78, 5 }, { 4, 55, 8, 6 }, { 11, 2, 6, 74 } };
            int max = array[0, 0], r = 0, c = 0; 
            for (int i = 0; i < array.GetLength(0); i++)
            {
                for (int j = 0; j < array.GetLength(1); j++)
                {
                    if(max < array[i, j])
                    {
                        max = array[i, j];
                        r = i;
                        c = j;
                    }
                }
            }
            Console.WriteLine("最大值為: {0}, 在{1}行 {2}列", max, r+1, c+1);
           

五.交錯數組

5.1 交錯數組中包含一維數組 聲明:
int[][] 數組名= new int[行數][列數]; 行數必須寫, 但是列數可以不寫

初始化:

int[][] array = new int[3][];
array[0] = new int[] { 1, 2, 3, 4 };
array[1] = new int[] { 6, 7, 8 };
array[2] = new int[] { 1, 4 };
// 指派的時候必須動态指派
int[][] array1 =
{
new int[] {1, 2, 3},
new int[] {3, 4, 5,6}
};
           
取值:

直接把寫上行号和列号就可以, 例如, 如果我們要取 array1 中的元素2, 就可以寫 array1[0][1];

周遊:

交錯數組的周遊要比二維數組更簡單一些, 交錯數組可以被拆分開

int[][] array = new int[3][];
            array[0] = new int[] { 1, 2, 3, 4 };
            array[1] = new int[] { 6, 7, 8 };
            array[2] = new int[] { 1, 4 };
            // array.Length得到該交錯數組一共有多少行
            for(int i = 0; i < array.Length; i++)
            {
                // array[i].Length 可以得到每行中有多少列
                for(int j = 0; j < array[i].Length; j++)
                {
                    Console.Write(array[i][j] + " " );
                }
                Console.WriteLine();
            }
           
5.2 交錯數組中包含二維數組

這個直接上代碼會比較清晰

聲明:
二維數組名代表什麼_C#學習筆記04--排序/查找/二維數組/交叉數組

每一行都是一個二維數組, 聲明時先定義好一共幾行, 初始化的時候再具體定義每一行的二維數組;

取值:
二維數組名代表什麼_C#學習筆記04--排序/查找/二維數組/交叉數組
周遊:

先周遊每一行的元素, 針對各個行再用周遊二維數組的方法周遊;

二維數組名代表什麼_C#學習筆記04--排序/查找/二維數組/交叉數組

=======================================================

思維導圖

二維數組名代表什麼_C#學習筆記04--排序/查找/二維數組/交叉數組