【資料結構】堆疊

【資料結構】堆疊

【資料結構】堆疊

 

堆疊(Stack)是一種後進先出(Last In First Out, LIFO)的有序串列,亦即資料處理的方式都是在同一邊進行,也就是由相同的一端來進行插入與刪除動作。而我們日常生活中,也有一些是堆疊的例子,例如堆盤子、書本裝箱…等,都是一層一層的堆上去,如果想要取出箱子中某一本書,也只能從最上面開始取出。

 

定義

1.一群相同性質元素的組合,即有序串列(ordered List) 。

2.具有後進先出 (Last In First Out, LIFO) 的特性。

3.將一個項目放入堆疊的頂端,這個動作稱為Push(加入)。

4.從堆疊頂端拿走一個項目,這個動作稱為Pop(取出)。

5.Push/Pop的動作皆發生在同一端,則稱此端為Top(頂端)。

6.要取出資料時,則只能從Top(頂端)取出,不能從中間取出資料。

 

 

【堆疊的操作示範】

 

堆疊常用的操作

  1.  Push  :加入新項目到堆疊的頂端。
  2. Pop  :取出堆疊頂端一個項目。
  3. TopItem  :查看堆疊頂端的項目內容。
  4. IsEmpty  :判斷堆疊是否為空,若為空則傳回真(True),否則傳回假(False)。
  5. IsFull  :判斷堆疊是否為滿,若為滿則傳回真(True),否則傳回假(False)。

【C#-Stack類別】

Stack.Push 方法 (Object)

using System;
using System.Collections; //C#的Stack所在的命名空間
public class SamplesStack
{

    public static void Main()
    {

        // Creates and initializes a new Stack. 建立並初始化一個新的堆疊
        Stack myStack = new Stack();
        myStack.Push("The");
        myStack.Push("quick");
        myStack.Push("brown");
        myStack.Push("fox");

        // Displays the Stack. //印出堆疊內容
        Console.Write("堆疊元素::");
        PrintValues(myStack, '\t'); //呼叫下方PrintValues方法

        // Removes an element from the Stack. 從堆疊裏移除一個元素
        Console.WriteLine("(Pop)\t\t{0}", myStack.Pop());

        // Displays the Stack. 印出堆疊內容
        Console.Write("堆疊元素::");
        PrintValues(myStack, '\t');

        // Removes another element from the Stack. 從堆疊裏移除另一個元素
        Console.WriteLine("(Pop)\t\t{0}", myStack.Pop());

        // Displays the Stack. 印出堆疊內容
        Console.Write("堆疊元素::");
        PrintValues(myStack, '\t');

        // Views the first element in the Stack but does not remove it.
        //檢視堆疊裏的第一個元素,但不移除該元素,注意動作與pop不同
        Console.WriteLine("(Peek)\t\t{0}", myStack.Peek());

        // Displays the Stack.
        Console.Write("堆疊元素::");
        PrintValues(myStack, '\t');
    }


    public static void PrintValues(IEnumerable myCollection, char mySeparator)
    {
        foreach (Object obj in myCollection) //對每一個在myCollection集合裏的物件obj
            Console.Write("{0}{1}", mySeparator, obj);
        Console.WriteLine();
    }

}


/* 
程式輸出:
堆疊元素::     fox     brown   quick   The
(Pop)           fox
堆疊元素::     brown   quick   The
(Pop)           brown
堆疊元素::     quick   The
(Peek)          quick
堆疊元素::     quick   The
請按任意鍵繼續 . . .
*/

 

【堆疊在運算式上的應用】

在日常生活中,我們所使用的四則運算都屬於中序(infix order)運算式,亦即運算子位於兩個運算元之間的表示法。但是,此種表示法電腦並無法直接的處理,因為中序式可能會含有括號,並且運算子可能有不同的優先順序權。因此,若要使用電腦來處理運算式時,則必須要先將「中序式」轉換成「後序式」(postfix order)。

算術式表示的方式有三種:

  1. 中序(Infix)表示法: A+B
  2. 前序(prefix)表示法: +AB
  3. 後序(postfix)表示法: AB-

【中序(Infix)表示法】

【定義】數學上的表示方式,就是屬於中序式,它是把運算子放在兩個運算元的中間。

【表示式】<運算元1 > <運算子> <運算元2 >

【例如】A+B。

【缺點】電腦無法一次依序讀取運算式,因運算式可能含有括號,且未定義運算子優先順序。

 

【前序 (prefix)表示法】

【定義】指將中序表示法中的運算子和運算元重新調整順序,只是運算子的順序是在運算元前面。

【表示式】<運算子> <運算元1 > <運算元2 >

【例如】+AB。

 

【後序 (postfix)表示法】

【定義】後序表示法和前序表示法相類似,使得運算子放於運算元後面的表示法。

【表示式】<運算元1 > <運算元2 > <運算子>

【例如】AB+。

【優點】 不必使用括號,方便電腦使用。

 

【運算式的轉換】

大部份的運算式(expression)都是由運算元(operand)與運算子(operator)所組成。

【例如】A*B+(C/D)-E   其中: A,B,C,D,E為運算元(operand),  +,-,*,/為運算子(operator)

【運算原則】

  • Œ括號內先處理
  • 優先權較高的運算子先執行
  • Ž同優先權者,則由結合性,來決定是由左而右,還是由右而左執行。

 

【中序式→前序式】

假設有一個中序式為:A×B+C×D,欲轉換成前序式,其步驟如下:

1.先用括號將優先順序分出來

((A×B)+(C×D))

2.將運算子移到左括號右邊

Œ((×AB)+(×CD))

(+(×AB)(×CD))

3.把括弧全部拿掉,即為所得。

+×AB×CD

 

【中序式→後序式】

假設有一個中序式為:A×B+C×D,欲轉換成後序式,其步驟如下:

1.先用括號將優先順序分出來

((A×B)+(C×D))

2.將運算子移到右括號左邊

Œ((AB×)+(CD×))

((AB×)(CD×)+)

3.把括弧全部拿掉,即為所得。

AB×CD×+

練習:

1.  A+B*C-D/E

Ans:  依優先順序括上括弧

(A+(B*C))-(D/E))

後序式係將運算子移到右括號左邊

(A(BC*)+)(DE/)-)

去掉括弧:

ABC*+DE/-

 

2. (A+B)*C/(D-E/F)

Ans:  依優先順序括上括弧

(((A+B)*C)/(D-(E/F)))

後序式係將運算子移到右括號左邊

(((AB+)C*)(D(EF/)-)/)

去掉括弧:

AB+C*DEF/-/

後序式求解:

設A=1, B=2, C=3, D=4, E=5, F=2,求下面後序式的值為何?

1.AB*C-DE**

=(((AB*)C-)(DE*)*)

=(((A*B)-C)*(D*E))

=(((1*2)-3)*(4*5))

=-20

2.ABC*+DE/-

=((A(BC*)+)(DE/)-)

=((A+(B*C))-(D/E))

=((1+(2*3))-(4/5))

=1+6-0.8

=6.2

3.AB+C*DEF/-/

=(((AB+)C*)(D(EF/)-)/)

=(((A+B)*C)/(D-(E/F)))

=(((1+2)*3)/(4-(5/2)))

=3*3/(4-2.5)

=9/1.5

=6

以上方法是我們人員用來進行的中序轉後序/前序的快速方法,應付考試相當快捷,但是,若要用程式來實現轉換方法,需要特定的資料結構來協助,一般來說有二種作法:堆疊與二元樹。

考試時,一般不會考程式,所以不用特別注意堆疊的演算法,大家要記得的是去括弧法與二元樹法。(考試必考!)

 

【C# – 中序到後序的轉換程式】

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace Infix
{
   class Program
   {
 
      static bool InfixToPostfixConvert(ref string infixBuffer, out string postfixBuffer)
      {
         int priority = 0;
         postfixBuffer = "";
 
         Stack<Char> s1 = new Stack<char>();
 
         for (int i = 0; i < infixBuffer.Length; i++)
         {
            char ch = infixBuffer[i];
            if (ch == '+' || ch == '-' || ch == '*' || ch == '/')
            {
               // check the precedence
               if (s1.Count <= 0)
                  s1.Push(ch);
               else
               {
                  if (s1.Peek() == '*' || s1.Peek() == '/')
                     priority = 1;
                  else
                     priority = 0;
                  if (priority == 1)
                  {
                     if (ch == '+' || ch == '-')
                     {
                        postfixBuffer += s1.Pop();
                        i--;
                     }
                     else
                     { // Same
                        postfixBuffer += s1.Pop();
                        i--;
                     }
                  }
                  else
                  {
                     if (ch == '+' || ch == '-')
                     {
                        postfixBuffer += s1.Pop();
                        s1.Push(ch);
                     }
                     else
                        s1.Push(ch);
                  }
               }
            }
            else
            {
               postfixBuffer += ch;
            }
         }
         int len = s1.Count;
         for (int j = 0; j < len; j++)
            postfixBuffer += s1.Pop();
         return true;
      }
 
      static void Main(string[] args)
      {
         string infixBuffer = "";
         string postfixBuffer = "";
 
         if (args.Length == 1)
         {
            infixBuffer = args[0];
           
            InfixToPostfixConvert(ref infixBuffer, out postfixBuffer);
            System.Console.WriteLine("InFix  :\t" + infixBuffer);
            System.Console.WriteLine("PostFix:\t" + postfixBuffer);
         }
         else
         {
            infixBuffer = "a+b*c";
 
            InfixToPostfixConvert(ref infixBuffer, out postfixBuffer);
            System.Console.WriteLine("InFix  :\t" + infixBuffer);
            System.Console.WriteLine("PostFix:\t" + postfixBuffer);
            System.Console.WriteLine();
           
            infixBuffer = "a+b*c/d-e";
            InfixToPostfixConvert(ref infixBuffer, out postfixBuffer);
            System.Console.WriteLine("InFix  :\t" + infixBuffer);
            System.Console.WriteLine("PostFix:\t" + postfixBuffer);
            System.Console.WriteLine();
           
            infixBuffer = "a+b*c/d-e+f*h/i+j-k";
            InfixToPostfixConvert(ref infixBuffer, out postfixBuffer);
            System.Console.WriteLine("InFix  :\t" + infixBuffer);
            System.Console.WriteLine("PostFix:\t" + postfixBuffer);
            System.Console.WriteLine();
         }        
      }
   }
}

/* 程式輸出
中序  : a+b*c
後序:   abc*+

中序  : a+b*c/d-e
後序:   abc*d/+e-

中序  : a+b*c/d-e+f*h/i+j-k
後序:   abc*d/+e-fh*i/+j+k-

請按任意鍵繼續 . . .

*/

 

 

【程式設計-C#】Array陣列的操作

陣列的排序

Array.Sort() 方法
可用來對指定的一維陣列物件由小而大做遞增排序。
語法1:將一維陣列物件中的元素做由小到大排序 :將一維陣列物件中的元素做由小到大排序
Array.Sort(陣列物件);
語法2:
用來將 陣列物件1 中的元素做由小到大排序,
且 陣列物件2 的元素會隨著 陣列物件1 的
索引位置跟著做排序的動作。
Array.Sort(陣列物件1, 陣列物件2);

陣列的反轉

Array.Reverse() 方法
用來反轉整個一維陣列的順序。
上例用Array.Sort() 方法對指定陣列由小而大遞增排序。
若希望改由大而小作遞減排序,需再將已做完遞增排序
的陣列再用 Array.Reverse() 方法即可將陣列由大而小
作遞減排序。
Array.Reverse() 語法:
Array.Reverse(陣列物件);

[例] 欲對陣列名稱avg做由大而小遞減排序,寫法:
Array.Sort(avg);
Array.Reverse(avg);
若同時有兩個相關陣列 name 和 avg,若以 avg 陣列
為基準由大而小做遞減排序,相關陣列需要同時 ,相關陣列需要同時反轉,
寫法:
Array.Sort(avg,name);
Array.Reverse(avg);
Array.Reverse(name);

陣列的搜尋

.NET Framework 類別程式庫的 Array 類別提供
1. Array.IndexOf()方法
2. Array. BinarySearch() 方法
用來搜尋某個資料是否在陣列物件中。
1. Array.IndexOf()方法
使用 Array.IndexOf 可用來搜尋陣列中是否有相符
資料。
 若有找到,則會傳回該陣列元素的註標值。
若沒有找到,會傳回-1。
語法:
Array.IndexOf(陣列名稱 ,查詢資料 [ ,起始註標] [ ,查詢距離] );

[例] 假設字串陣列 name 中有
{“Jack”,”Tom”,”Fred”,”Mary”,”Lucy”, “Jane” }
共六個陣列元素,觀察下列各陳述式輸出結果:
 Array.IndexOf(name,”Tom”);
[結果] 由註標0開始找起,傳回值為1。
Array.IndexOf(name, ”Tom”, 3) ;
[結果] 由註標3開始找起,傳回值為-1。
若str1=”Lucy” , start=1, offset=2
Array.IndexOf(name, str1, start, offset);
[結果] 由註標1開始往下找2個陣列元素的內容是否
有 ”Lucy” 字串。傳回值為-1。

 

2. Array.BinarySearch()方法
– 用來搜尋陣列中的資料,陣列未經排序 ,陣列未經排序,每次
搜尋資料都由最前面開始,資料量大時,愈後
面的資料查詢所花費的時間愈多,資料平均搜
尋時間不平均。
– 為不管資料前後次序,使得資料平均搜尋時間都
差不多,在 .NET Framework 類別程式庫另提供
此二分化搜尋方法來搜尋資料是否在陣列中。
– 此方法使用前陣列 才可使用
適用於資料量大的陣列。
語法:Array.BinarySearch(陣列名稱, 查詢資料);

陣列的拷貝

將某個陣列複製給另一個陣列時,可用 Array.Copy()
方法進行拷貝陣列。
語法:
Array.Copy (srcAry , srcIndex , dstAry , dstIndex , length );
srcAry :來源陣列即被拷貝的陣列。
srcIndex:代表 srcAry 來源陣列的註標,由指定的註標開始複製。
dstAry :接收資料的目的陣列。
dstIndex:代表 dstAry 目的陣列的註標,由指定的註標開始儲存。
length :表示要複製的陣列元素個數。

陣列的清除

當需要將某個陣列中指定範圍內的陣列元素的內容
清除,可透過 Array.Clear() 方法。語法:
Array.Clear(aryname, startindex, length);
【例1】將 myary 陣列中,註標為 3~4 陣列元素的內容
清除, 寫法:
Array.Clear(myary, 3, 2);
【例2】 將 myary 陣列中所有陣列元素的內容清除,
假設該 陣列共有六個陣列元素。寫法:
Array.Clear(myary, 0, 6);

 

 

【資料結構】陣列

陣列的觀念

【定義】陣列是指一群具有相同名稱及資料型態的變數之集合。

【特性】

  1. 佔用連續記憶體空間。
  2. 用來表示有序串列之一種方式。
  3. 各元素的資料型態皆相同。
  4. 支援隨機存取(Random Access)與循序存取(Sequential Access)。
  5. 插入或刪除元素時較為麻煩。因為須挪移其他元素。

 

【優點】

(1)利用註標(Index)可以快速的輸入資料。

輸入:for(i=0;i<5;i++) //利用「迴圈結構」

A[i]=i*2+1; //快速「輸入資料」到「陣列」中

(2) 利用註標(Index)一次可以輸出大批的資料。

輸出:for(i=0;i<5;i++) //利用「迴圈結構」

WriteLine(A[i]); //從「陣列」一次「輸出大批」的資料

【定義】宣告陣列時,其括弧內的「註標」個數,只有一個時稱為「一維陣列」。在一維陣列中,常使用的運算指令有五種。

  1. 讀取(Read)
  2. 寫入(Write)
  3. 插入(Insert)
  4. 刪除(Delete)
  5. 複製(Copy)

讀取(Read)

【定義】利用註標(Index)來「讀取」資料。

【例如】將A陣列的第二個元素放到X目的變數中。

【寫法】X= A[1]; //陣列的註標是從0開始

【圖解】

%e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-1

 

寫入(Write)

【定義】利用註標(Index)來「寫入」資料。

【例如】將數值50寫入到陣列的第二個索引位置中。

【寫法】A[1]=50; //陣列的註標是從0開始

【圖解】
%e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-2

插入(Insert)

【定義】在指定的註標 i 的位置插入一項新元素,原來註標 i 和之後的元素都必須要再往後挪移一個位置。

【例如】將在註標1的位置插入一項新元素(15)。

【演算法】

Procedure ArrayInsert(int A[],int Max,int i ,int value)  
Begin
  If(i>0 && i<=Max)  //判斷欲插入位置i是否存在,如果有,則
{
  for(count=Max-1;count>i;count--)   //i位置及後面的元素逐一往後挪
    A[count]=A[count-1];
  A[i]=value;                        //最後再將新元素插入到第i位置
}
   Else                              //如果欲插入位置i不存在,則
     Return 0;                      //傳回0
End
End Procedure

 

【圖解】
%e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-3
【說明】

首先將30往後挪移一個位置,再將A[1]的元素20,往後挪移放到A[2]位置中,最後再插入15到A[1]中。

刪除(Delete)

【定義】指刪除指定的註標 i 位置的元素,原來註標 i的元素被刪除,為了避免浪費記憶體空間,因此,之後的元素都必須要再往前挪一個位置。

【例如】將在註標1的位置刪除一項舊元素(20)。

【演算法】

Procedure ArrayDelete(int A[],int Max,int i)  
Begin
  If(i>0 && i<=Max)                                       //判斷欲刪除元素位置i是否存在,如果有,則
  {
    for(count=i;count<Max-1;count++)     //i位置後面的元素逐一往前挪
    A[count]=A[count+1];
    A[Max-1]=0;                                           //最後再將0放到最後一個位置
  }
   Else                                                             //如果欲插入位置i不存在,則
     Return 0;                                                   //傳回0
End
End Procedure

【圖解】

%e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-4

 

【說明】 首先將A[1]的元素20刪除,再將A[2]的元素30往前挪移一個位置,最後再寫入0到A[2]中。

複製(Copy)

【定義】指將「來源陣列」的元素內含值全部逐一copy到「目的陣列」。

【例如】將A陣列的元素內含值全部逐一copy到B陣列中。

【演算法】

Procedure ArrayCopy(int A[],int B[], int Max)  
Begin
  If(Max>0)                                                    //判斷陣列是否有元素內含值,如果有,則
{
  for(count=0;count<Max-1;count++)    //A陣列全部逐一copy到B陣列
    B[count]=A[count];
}
   Else                                                             //如果陣列沒有元素,則
     Return 0;                                                   //傳回0
End
End Procedure

【圖解】

%e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-5

【說明】

A陣列的元素內含值全部逐一copy到B陣列中,例如A[0]元素會被copy到B[0]中,A[1]元素放到B[1]中,以此類推。

陣列的宣告

(1) 變數宣告

int A, B, C;  //宣告三個變數(A,B,C)為整數型態

以上三個變數與變數之間都是個別獨立的記憶體空間。

(2) 陣列宣告

int A[3];  //宣告一維陣列A,共有A[0]、A[1]、A[2]三個元素

以上三個記憶體空間,可以讓我們連續儲存多項資料,並且資料與資料之間都是按照順序排列的記憶體空間。

 

陣列的儲存方式

【定義】陣列名稱之後加上“註標”即可存取陣列元素。

【舉例】宣告一個A[3]的陣列,並分別儲存10,20,30

 C#
Procedure ArrayCopy(int A[],int B[], int Max)  
Begin
  If(Max>0)                                                    //判斷陣列是否有元素內含值,如果有,則
{
  for(count=0;count<Max-1;count++)    //A陣列全部逐一copy到B陣列
    B[count]=A[count];
}
   Else                                                             //如果陣列沒有元素,則
     Return 0;                                                   //傳回0
End
End Procedure

 

【實例】請依序輸入六位同學的成績到陣列中,並計算及輸出「總和」

第一種寫法:使用陣列,但未使用for迴圈演算法

int A[6] = {100, 98, 88, 67, 75, 90};
int sum = A[0] + A[1] + A[2] + A[3] + A[4] + A[5];
Console.WriteLine("總和為:" + Sum);

第二種寫法:使用陣列,並且使用for迴圈演算法 (最佳)

int A[6] = {100, 98, 88, 67, 75, 90};
int sum = 0;
for (int i = 0; i < 6; i++) {
  sum = sum  + A[i];
}
Console.WriteLine("總和為:" + Sum);

二維陣列的觀念

在前面所介紹一維陣列,可以視為直線方式來存取資料,這對於一般的問題都可以順利的處理,但是對於比較複雜的問題時,那就必須要使用二維陣列來處理。否則會增加程式的複雜度。

例如:計算4位同學的5科成績之總分與平均的問題。

【定義】宣告陣列時,其括弧內的「註標」個數,有兩個時稱為「二維陣列」。

【語法】資料型態 陣列名稱[M][N];

【說明】M代表列數,N代表行數

【存取方法】利用二維陣列中的兩個註標來表示。

 

多維陣列的觀念

【定義】宣告陣列時,其括弧內的「註標」個數,是二個以上時,就稱為「多維陣列」。其中最常見是三維陣列,其圖形為三度空間的立體圖形,並且我們可以將三維陣列視為多個二維陣列的組合。

【語法】資料型態 陣列名稱[L][M][N];

【說明】L代表二維陣列個數,M代表列數,N代表行數

【舉例】設計有某一個大學,3次月考,全班4位同學的5科目成績時。利用三維陣列來存取每人學生的成績。

%e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-6

【說明】

此例子中Score陣列共有三個註標,故Score陣列是一個三維 陣列。

//其中,第一個註標為:二維陣列的個數: 0~2 共有3個二維陣列

第二個註標為:列註標表示範圍: 0~3 共有4列

第三個註標為:行註標表示範圍: 0~4 共有5行

【圖解】

%e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-7

【說明】宣告Score是由3個(0~2)二維陣列,每個二維陣列包含4列  (0~3),5行(0~4)組合而成的整數三維陣列。並且共計有3×4×5=60元素。

 

陣列在記憶體中的表示法

陣列是由一連串的記憶體組合而成,其陣列元素之儲存位址計算,

大致上,可分為一維陣列與二維陣列來說明:

Ⅰ. 一維陣列

[題目1]若陣列A有N個元素,其陣列的起始位址為Lo,並且索引值從0開始,d 為元素大小,則A[i]的起始位置為多少?

 

%e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-8

令:ŒLo為起始位址,d為元素大小,則A[i]之位置計算=Lo+i*d。

【舉例】假設每一個整數佔用2個byte,若A陣列的起始位址是100開始,則A[5]的起始位址為多少?

令:Œ起始位址Lo=100

元素大小d=2

則A[5]之位置計算=Lo+i*d =100+5*2=100+10=110

[題目2]若陣列A的索引從L到U,其陣列的起始位址為Lo, d為元素大小,則A[i]的起始位置為多少?

 

宣告方式:A[L…U]

%e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-9

令:ŒLo為起始位址,d為元素大小,則A[i]之位置計算=Lo+(i-L)*d

【舉例】假設每一個整數佔用2個byte,若A[10]起始位址是200開始,則A[20]的位址為多少?

令:ŒLo起始位址=200 ,d元素大小=2

則A[20]之位置計算=Lo+(i-L)*d =200+(20-10)*2=200+10*2=220

二維陣列

宣告方式:A[0…M-1, 0…N-1], 其中:M代表列數(Row),橫向,N代表行數(Column),縱向。所以,共有M*N格。

%e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-10

說明:¡圖的儲存位置:A[1,4],△圖的儲存位置:A[2,1],o圖的儲存位置:A[M-1,N-2]

Row-major(以列為主)

【定義】以列為主的二維陣列要轉為一維陣列時,是將二維陣列「由上往下」一列一列讀入一維陣列。亦即將二維陣列儲存的邏輯位置轉換成實際電腦中主記憶體的存儲方式。

【圖解】

%e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-11

【以列為主的儲存公式】

Œ令Lo為起始位址,d為元素大小,則二維陣列A[i,j]位置會儲存到一維陣列的那一個位置呢?

公式=Lo+[i*N+j]*d

%e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-12

Column-major(以行為主)

【定義】以行為主的二維陣列要轉為一維陣列時,必須將二維陣列「由左往右」一行一行讀入一維陣列。亦即將二維陣列儲存的邏輯位置轉換成實際電腦中主記憶體的存儲方式。

【圖解】

%e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-13

【以行為主的儲存公式】

Œ令Lo為起始位址

d為元素大小

則二維陣列A[i,j]位置會儲存到一維陣列的那一個位置呢?

公式=Lo+[j*M+i]*d

%e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-14

 

多項式(polynomials)

多項式(polynomial)的表示式為
%e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-30

其中Ai為非零項的係數,且多項式的每一項均使用三個欄位來表示(分別為 coef, exp, link) 。其節點的資料結構如下所示:

%e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-15

其中:Coef:表示該變數的係數

Exp:表示該變數的指數

Link:表示指向下一個節點的指標

【表示方法】

【方法一】依照指數高低依序儲存係數

【作法】假設最高指數為n,則準備一個一維陣列A[1..n+2],

其內容如下:

%e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-16

【練習】假設f(x)=7X4+5X2+3X

因為最高指數為4,則準備一個一維陣列A[1..6],

【解答】

步驟一:準備一個一維陣列A[1..6]

%e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-17

步驟二:存入最高指數及分別存入Xn, Xn-1,…,X0之係數

%e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-18

【優點】

(1)只要儲存係數,比較節省儲存指數空間。

(2)適用於零項次較少的多項式。

【缺點】

不適用於零項次極多的多項式,儲存時非常浪費空間。

Ex: f(X)=5X100+1

則必須要準備一個一維陣列A[1..102],在實際使用上只用了3格,因此,會浪費99格。

 

【方法二】只儲存非零項次的係數與指數

【作法】假設多項式有K個非零項次,則準備一個一維陣列A[1..2K+1],其內容如下:

%e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-19

 

【練習】假設f(X)=5X100+1

因為有2個非零項次,則準備一個一維陣列A[1..5]

【解答】

步驟一:準備一個一維陣列A

步驟二:存入K 、係數及指數

%e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-20

【優點】適用於零項次極多的多項式。

【缺點】當非零項次極多時,不適用。

矩陣(Matrices)

【定義】

類似二維陣列,它是利用一個m × n矩陣來表示這個矩陣擁有

m列(Rows)和n行(Columns)。

一般而言,資料結構上常用到的矩陣有四種:

  • 矩陣轉置(Matrix Transposition)
  • 矩陣相加(Matrix Addition)
  • 矩陣相乘(Matrix Multiplication)
  • 稀疏矩陣(Sparse Matrix)

 

矩陣轉置(Matrix Transposition)

【定義】

假設有一個(m × n)矩陣A,則我們可以將A矩陣轉置為(n × m)的B矩陣,並且B矩陣的第j列第i行的元素等於A矩陣的第i列第j行的元素,

以數學式來表示為:Bji=Aij

【假設】A矩陣與B矩陣的m與n都是從1開始計算,因此,A,B矩陣的表示如下:

%e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-21

說明:A矩陣的第i列第j行的元素等於B矩陣的第j列第i行的元素

【演算法】

Procedure Matrix_Transpose(int m, int n, int A[m][n], int B[n][m])
Begin
  for(i = 1; i <= m; i++)         //外迴圈,先掃瞄第1列到第m列
    for(j = 1; j <= n; j++)       //內迴圈,再掃瞄第1行到第n行
//將A陣列的第i列第j行的元素放到B陣列的第j列第i行的元素中
        B[j][i] = A[i][j];        
End
End Procedure

矩陣相加(Matrix Addition)

【定義】

假設A,B都是(m × n)矩陣,則我們可以將A矩陣加上B矩陣以得到一個C矩陣,並且此C矩陣亦為(m × n)矩陣。因此:

在C矩陣上的第i列第j行的元素必定等於A矩陣的第i列第j行的元素加上B矩陣的第i列第j行的元素。

以數學式來表示為:Cij= Aij+Bij

【假設】A、B、C矩陣的m與n都是從1開始計算,因此,A,B兩個矩陣相加等於C矩陣,其表示如下:

%e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-22 %e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-23

【演算法】

Procedure Matrix_Add(int m, int n, int A[m][n], int B[m][n], int C[m][n])
Begin
for(i = 1; i <= m; i++)          //外迴圈,先掃瞄第1列到第m列
     for(j = 1; j <= n; j++)         //內迴圈,再掃瞄第1行到第n行
       /*將A陣列的第i列第j行的元素加上B陣列的第i列第j行的元素之後,
          放到C陣列的第i列第j行的元素中 */
      C[i][j] = A[i][j] + B[i][j];
End
End Procedure

矩陣相乘(Matrix Multiplication)

【定義】

假設A為(m × n)矩陣,而B為(n × p)矩陣,則我們可以將A矩陣乘上B矩陣以得到一個(m × p)的C矩陣,因此,在C矩陣上的第i列第j行的元素必定等於A矩陣的第i列乘上B矩陣的第j行(兩個向量的內積),以數學式來表示為:

%e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-24

【假設】A、B、C矩陣的m與n都是從1開始計算,因此,A,B兩個矩陣相乘等於C矩陣,其表示如下:

%e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-25

 

%e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-26

【演算法】

Procedure Matrix_Mul(int m, int n, int p, int A[m][n], int B[n][p], int C[m][p])
Begin
  for(i = 0; i < m; i++)      //外迴圈,先掃瞄第1列到第m列
    for(j = 0; j < n; j++)     //內迴圈,再掃瞄第1行到第n行
      {
        C[i][j]=0;
/*將A矩陣的第i列第j行的元素加上B矩陣的第i列第j行的
元素的結果放到C矩陣上的第i列第j行的元素中*/
        for(k=0;k<p;k++)
          C[i][j] = C[i][j] + A[i][k] * B[k][j];
     }
End
End Procedure

 

C#程式

#include <iostream>  
 
void MultiplyWithOutAMP() {  
 
    int aMatrix[3][2] = {{1, 4}, {2, 5}, {3, 6}};  
    int bMatrix[2][3] = {{7, 8, 9}, {10, 11, 12}};  
    int product[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};  
 
    for (int row = 0; row < 3; row++) {  
        for (int col = 0; col < 3; col++) {  
            // Multiply the row of A by the column of B to get the row, column of product.  
            for (int inner = 0; inner < 2; inner++) {  
                product[row][col] += aMatrix[row][inner] * bMatrix[inner][col];  
            }  
            std::cout << product[row][col] << "  ";  
        }  
        std::cout << "\n";  
    }  
}  
 
void main() {  
    MultiplyWithOutAMP();  
    getchar();  
}

稀疏矩陣(Sparse Matrix)

【定義】 是指矩陣中大部份元素都沒有使用,元素稀稀落落,所以稱為稀疏矩陣。

【概念】在M × N 的矩陣中,多數的資料值為0。

【處理方法】

【方法一】直接利用M × N的二維陣列來一一對應儲存。

【缺點】

1. 浪費空間:因為多數為0。

2. 浪費時間:因為要處理一些不必要的計算。

%e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-27

【方法二】利用3-tuple結構來儲存非零元素

【作法】假設有一個M*N的稀疏矩陣中共有K個非零元素,則必須要準備一個二維陣列A[0..K,0..2]

%e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-28

%e8%b3%87%e6%96%99%e7%b5%90%e6%a7%8b-%e9%99%a3%e5%88%97-29

 

【資料結構-題庫】陣列

1.陣列是一組變數的集合,而這些變數:
(A) 具有不同的資料型態,並且分散存在記憶體空間
(B) 具有相同的資料型態,並且分散存在記憶體空間
(C) 具有相同的資料型態,並且線性相鄰的存在記憶體空間
(D) 具有不同的資料型態,並且線性相鄰的存在記憶體空間

Answer
C

2.有關陣列下列那一項敘述有誤?

(A)佔用連續記憶體空間

(B)插入或刪除元素非常容易

(C)各元素的資料型態皆相同

(D)支援隨機存取(Random Access)與循序(Sequential Access)

Answer
B

3.存取陣列中的元素時,需指定要存取元素在陣列中的?

(A)記憶體位址

(B)索引編號

(C)元素值

(D)以上皆可

Answer
B

4.在一維陣列中,常使用的運算指令有五種,下列那一種不是?

(A)讀取(Read)

(B)寫入(Write)

(C)複製(Copy)

(D)貼上(Past)

Answer
D

5.在一維陣列中,那一個運算指令執行時,會往後挪一個位置?

(A)讀取(Read)

(B)寫入(Write)

(C)刪除(Delete)

(D)插入(Insert)

Answer
D

6.假設有n個整數利用陣列(Array)儲存,將存放於最前面及最後面的資料印出時,請問所需之時間複雜度以下列何者表示最為適當?

(A)O(1)

(B)O(log n)

(C)O(n)

(D)O(n2)

Answer
A

7.假設有一陣列A儲存已排序的n個數字資料,刪除最大數值的資料需多少時間?

(A)O(1)

(B)O(log n)

(C)O(n)

(D)O(n2)

Answer
A

8.假設有一陣列A儲存已排序好的資料(a1,a2,…,an),請問下列何者錯誤?

(A)找第k大的資料需要O(log n)

(B)刪除需要O(n)的時間

(C)插入需要O(n)的時間

(D)以上皆非

Answer
B

9.請問在陣列中「讀取」某一元素的時間複雜度為何?

(A)O(1)

(B)O(log n)

(C)O(n)

(D)O(n2)

Answer
A

7.請問在陣列中「寫入」某一元素的時間複雜度為何?

(A)O(1)

(B)O(log n)

(C)O(n)

(D)O(n2)

Answer
A

8.假設有一陣列A儲存已排序的n個數字資料,請問「插入」某一元素的時間複雜度為何?

(A)O(1)

(B)O(log n)

(C)O(n)

(D)O(n2)

Answer
C

 

9.假設有一陣列A儲存已排序的n個數字資料,請問「刪除」某一元素的時間複雜度為何?

(A)O(1)

(B)O(log n)

(C)O(n)

(D)O(n2)

Answer
C

 

10.假設有一陣列A陣列的元素內含值欲全部逐一複製到B陣列中,請問時間複雜度為何?

(A)O(1)

(B)O(log n)

(C)O(n)

(D)O(n2)

Answer
C

11. 關於「變數宣告」與「陣列宣告」的敘述,下列何者有誤?

(A) 變數宣告時,會產生不連續的記憶體空間的配置

(B) 變數宣告時,會產生連續的記憶體空間的配置

(C) 陣列宣告時,會產生連續的記憶體空間的配置

(D) 變數宣告時,變數與變數之間都是個別獨立的記憶體空間。

Answer
B

12.在陣列宣告時,如果宣告int A[10];,請問陣列註標的範圍為多少?

(A) A[0]、A[1]、A[2],…,A[10]

(B) A[0]、A[1]、A[2],…,A[9]

(C) A[1]、A[2],…,A[10]

(D) A[1]、A[2],…,A[11]

Answer
B

13.有一整數陣列int A[0…29] ; (假設int資料型態佔用2個位元組),則此陣列共佔多少位元組?
(A) 40

(B) 30

(C) 4

(D) 60

Answer
D

14.陣列A[註標]中,註標不可為:

(A)整數

(B)運算式

(C)變數

(D)字串

Answer
D

【2-3  二維陣列的觀念,以下不在期中考的範圍內】

1.二維陣列宣告int Score[23],陣列中含有多少元素:

(A)2

(B)3

(C)6

(D)12

Answer
C

2.若有一個二維陣列A[1..5][2…3],假設其中存放的每個元素佔2byte,則在記憶體中存放A陣列需要多少bytes?

(A)10

(B)20

(C)30

(D)40

 

 

3.在BASIC 語言中宣告陣列為Dim A(5,6),試問陣列A 中有多少個元素?
(A)42個

(B)36 個

(C)35個

(D)30 個

4.有一整數二維陣列int A[0…29, 0…19]; (假設int資料型態佔用2個位元組), 則此陣列共佔多少位元組?
(A) 20  (B) 30  (C) 600  (D) 1200

 

 

5.執行下列BASIC程式片段時,請問陣列A佔用記憶體多少bytes的儲存空間?

Dim A ( 3 , 4 ) As Double

(A)48  (B)96  (C)80  (D)160

 

 

2-4 多維陣列的觀念

1.有一個整數陣列int Score[3][4][5],假設sizeof(int)=2,請問此陣列共佔多少位元組?  (A) 60 (B) 120 (C) 180 (D) 240

 

 

2.在我們撰寫程式時,不小心時常發生陣列的「subscript out of range」的錯誤訊息時,它是表示程式執行時遇到那一種狀況?

(A) 語法錯誤

(B) 記憶體存取錯誤

(C) 整數的overflow

(D) 整數的underflow

 

 

3.有一個整數陣列int A[8][10][5],假設sizeof(int)=1,請問此陣列共佔多少位元組?

(A) 112 (B) 400 (C) 800 (D) 1600

 

 

2-5 陣列在記憶體中的表示法

1.有一整數陣列int A[0…29]; (假設int資料型態佔用2個位元組),若A[0]在記憶體中的位址為100,則元素A[21] 的起始位址為何?
(A) 84       (B) 100       (C) 120       (D) 142

 

 


2.有一整數陣列int A[0…29]; (假設int資料型態佔用2個位元組),若A[5]在記憶體中的位址為100,則元素A[21] 的起始位址為何?
(A) 16       (B) 21       (C) 132       (D) 142

 

 

3.有一整數二維陣列int A[0…9, 0…9]; 則第二列第五行的儲存位置如何表示?
(A) A[2,5]   (B) A[1,4]    (C) A[3,6]    (D) A[1,5]

 

 

4.若陣列A 之宣告為DIM A(2,3) As Integer,A 之內容如圖所示,執行

Print A(A(1,2)-1,A(2,3)+1)指令後,答案為何?

(A)1  (B)0  (C)3  (D)2

 

 

2-5.1 Row-major(以列為主)

1.假設一個二維陣列A[1…5, 1…6],如果以列為主,則A(3,3)排在第幾個?

(A)13  (B)14  (C)15  (D)16

 

 

2.陣列A共有6列8行資料,以列為主儲存在記憶體中,A[1,1]起始位址為20。假設陣列每份資料佔2個記憶單位,則第3列第6行的位址為何?

(A)62  (B)64  (C)66  (D)68

 

 

3.陣列A共有6列8行資料,以列為主儲存在記憶體中,A[0,0]起始位址為20。假設陣列每份資料佔2個記憶單位,則第3列第6行的位址為何?

 

(A)80  (B)82  (C)84  (D)88

 

 

4.給予一個二維陣列A[-4..3, -3..2],Lo=100, d=1,採用Row-major方式,請計算A[2,2]的位置。

(A)140  (B)141  (C)146  (D)143

 

 

 


2-5.2 Column-major(以行為主)

1.假設一個二維陣列A[1…5, 1…6],如果以行(Column)為主,則A(3,3)排在第幾個?

(A)13  (B)14  (C)15  (D)16

 

 

2.陣列A共有6列8行資料,以行為主儲存在記憶體中,A[1,1]起始位址為20。假設陣列每份資料佔2個記憶單位,則第3列第6行的位址為何?

(A)82  (B)84  (C)86  (D)88

 

 

3.陣列A共有6列8行資料,以行為主儲存在記憶體中,A[0,0]起始位址為20。假設陣列每份資料佔2個記憶單位,則第3列第6行的位址為何?

(A)90  (B)92  (C)94  (D)98

 

 

4.給予一個二維陣列A[-4..3, -3..2],Lo=100, d=1,採用以行為主方式,請計算A[2,2]的位置。

(A)140  (B)141  (C)146  (D)143

 

 

2-6 多項式(polynomials)

1.假設多項式為:f(x)=7X5+5X2+3X+1,請依照指數高低依序儲存係數於一維陣列中,並寫出其內容?
2.假設多項式為:f(x)=7X5+5X2+3X,請儲存非零項次的係數與指數於一維陣列中,並寫出其內容?

 

 

2-7  矩陣(Matrices)

1.關於資料結構中的矩陣單元之敘述,下列何者正確?

(A)矩陣類似二維陣列

(B)矩陣是利用一個m × n陣列來表示

(C)矩陣是由m列(Rows)和n行(Columns)所組成。

(D)以上皆是

 

 

2.下列何者不是資料結構中所探討的矩陣?

(A)矩陣轉置

(B)矩陣相加

(C)矩陣相乘

(D)矩陣相除

 

 

2-7.1 矩陣轉置(Matrix Transposition)

1.假設有一個(m × n)矩陣A,如果將A矩陣轉置為(n × m)的B矩陣時,

其時間複雜度為:

(A) O(m2)

(B) O(m × n )

(C) O(n2)

(D) O(m + n )

  1. 將原矩陣中的行座標元素與列座標元素相互調換,此現象稱為?

(A) 矩陣轉移

(B) 矩陣轉動

(C) 矩陣交換

(D) 矩陣轉置

 

 

3.假設有一個(m × n)矩陣A在轉置之後儲存到B矩陣中,請問在撰寫程式時,其主要的指令為何?(設定i=1~m, j=1~n)

(A) B [j][i] = A [i][j]

(B) A[j][i] = B [i][j]

(C) B [i][j] = A [i][j]

(D) B[j][i] = A[j][i]

 

 

2-7.2 矩陣相加(Matrix Addition)

  1. 將A矩陣內的元素與B矩陣內的元素相加之後,存放到C矩陣,此現象稱為?

(A) 矩陣合併

(B) 矩陣相加

(C) 矩陣結合

(D) 矩陣合成

 

 

  1. 假設A,B都是(m × n)矩陣,則我們可以將A矩陣加上B矩陣以得到一個C矩陣,並且此C矩陣亦為(m × n)矩陣,其主要的指令為何?

(設定i=1~m, j=1~n)

(A) C[i][j] = A[i][j] + B[i][j]

(B) C[i][j] = A[j][i]+B [i][j]

(C) C[i][j] = B [j][j] +A [j][j]

(D) C[i][j] = B[j][i]+A[j][i]

 

 

2-7.3 矩陣相乘(Matrix Multiplication)

1.兩個矩陣A: m×n, B: n×p相乘,其時間複雜度為:
(A) O(n3)     (B) O(mnp)     (C) O(n2)    (D) O(n4)

 

 

  1. 假設想要將A矩陣(m × n)內的元素與B矩陣(n × p)內的元素相乘之後,存放到C矩陣,請問C矩陣要提供「幾列幾行」才能存放呢?

(A) (m × n)

(B) (n × p)

(C) (m × n)

(D) (m × p)

 

 

2-7.4  稀疏矩陣(Sparse Matrix)

1.假設一矩陣A有12(4×3)個元素,其中只有2個非零元素,請問其矩陣的使用率為何?
(A)1/3  (B)1/4  (C)1/5  (D)1/6

 

 

2.假設有一個m×n的整數矩陣,其中有k個非零元素。如果用陣列來儲存這個

稀疏矩陣(Sparse Matrix)的k個非零元素。請問我們需要多少儲存整數的記憶體?

(A)k  (B)2k+1  (C)3(k+1)  (D)4k

 

 

3.假設有一個m×n的整數矩陣,其中有2個非零元素。如果用陣列來儲存這個

稀疏矩陣(Sparse Matrix)的2個非零元素。請問我們需要多少儲存整數的記憶體?

(A)2  (B)5  (C)9  (D)10

 

 

4.假設有一個矩陣,其元素大部分都沒有使用,元素稀稀落落,請問在資料結構中,將此矩陣稱為:

(A) 稀疏矩陣

(B) 上三角矩陣

(C) 下三角矩陣

(D) 零矩陣

 

 

5.使用二維陣列來儲存稀疏矩陣中的全部元素,下列敘述何者正確?

(A)容易管理

(B)記憶體最佳利用

(C)節省空間

(D)浪費空間

 

6.在處理稀疏矩陣的方法中,下列那一種方法可以減少記憶體空間的浪費?

(A)一維陣列

(B)二維陣列

(C)2-tuple結構

(D)3-tuple結構

 

 

2-8 特殊矩陣

1.除了常見的四種矩陣(矩陣轉置、矩陣相加、矩陣相乘及 稀疏矩陣)之外,在資料結構中尚有一些比較特殊的矩陣,請問下列何者正確?

(A)上三角矩陣

(B)下三角矩陣

(C)對稱矩陣

(D)以上皆是

 

 

2-8.1 上三角矩陣(Upper-Triangular Matrix)

1.假設一矩陣A為 n×n的二維矩陣,當對角線以上的元素均為零時稱之為上三角矩陣。欲將此矩陣對映到一個一維陣列,請問需要多大的記憶體空間來儲存?

(A) n  (B)n×n  (C)        (D)

 

 

2.假設一矩陣A為 4×4的二維矩陣,當對角線以上的元素均為零時稱之為上三角矩陣。欲將此矩陣對映到一個一維陣列,請問需要多大的記憶體空間來儲存?

(A) 4  (B)8  (C)10    (D)15

 

 

3.假設一矩陣A為 n×n的二維矩陣,當對角線以上的元素均為零時稱之為上三角矩陣。請問零元素個數有多少?

(A) n  (B)n×n  (C) n2–          (D) n2

 

 

 

 

 

 

4.假設一矩陣A為 4×4的二維矩陣,當對角線以上的元素均為零時稱之為上三角矩陣。請問零元素個數有多少?

(A)4  (B)5  (C)6  (D)15

 

 

5.假設有一矩陣A為4×4的上三角矩陣,以列為主,請問元素a33對映到一維陣列的位置為何?

(A) 7  (B)8  (C) 9  (D) 10

 

 

6.假設有一矩陣A為4×4的上三角矩陣,以行為主,請問元素a33對映到一維陣列的位置為何?

(A) 5  (B)6  (C) 7  (D)8

 

 

2-8.2 下三角矩陣(Lower-Triangular Matrix)

1.假設一矩陣A為 n×n的二維矩陣,當對角線以上的元素均為零時稱之為下三角矩陣。欲將此矩陣對映到一個一維陣列,請問需要多大的記憶體空間來儲存?

(A) n  (B)n×n  (C)         (D)

 

 

2.假設一矩陣A為 3×3的二維矩陣,當對角線以上的元素均為零時稱之為下三角矩陣。欲將此矩陣對映到一個一維陣列,請問需要多大的記憶體空間來儲存?

(A)3  (B)6  (C)9  (D)12

 

 

3.假設一矩陣A為 n×n的二維矩陣,當對角線以上的元素均為零時稱之為下三角矩陣。請問零元素個數有多少?

(A) n  (B)n×n  (C) n2–         (D) n2

 

 

4.假設一矩陣A為 3×3的二維矩陣,當對角線以上的元素均為零時稱之為下三角矩陣。請問零元素個數有多少?

(A)1  (B)2  (C)3  (D)5

 

 

 

5.假設有一矩陣A為4×4的下三角矩陣,以列為主,請問元素a33對映到一維陣列的位置為何?

(A)5  (B)6  (C) 7  (D)8

 

 

6.假設有一矩陣A為4×4的上三角矩陣,以行為主,請問元素a33對映到一維陣列的位置為何?

(A) 7  (B)8  (C) 9  (D)10

 

【資料結構-題庫】資料結構導論

1.欲將「資料」轉換成「資訊」,則必須要經過一連串處理過程,而這一連串的處理過程,就俗稱為什麼呢?

(A)流程再造

(B)資料處理

(C)資訊整合

(D)資料結構

Answer
B

2.某一公司的老闆要做某一項決策時,下列那一項對他最有幫助:

(A)事實的記錄

(B)具體的記錄

(C)資料

(D)資訊

Answer
D

3. 資料結構的種類通常不包含下列何者?

(A)模組(Module)

(B)佇列(Queue)

(C)圖形(Graph)

(D)陣列(Array)

Answer
A

4.下列何者不是一種資料結構(Data Structure)?

(A)佇列(Queue)

(B)堆疊(Stack)

(C)資料庫(Database)

(D)鏈結串列(Linked List)

Answer
C

5.用來描述處理問題的方法與步驟稱之為?

(A)資料結構

(B)演算法

(C)程式語言

(D)作業系統

Answer
B

6. 關於演算法的述敘,下列何者正確?

(A)步驟愈多愈可以解決問題

(B)較少的步驟來解決問題

(C)文字敘述方式優於流程圖

(D)文字敘述方式優於虛擬碼

Answer
B

7.下列有關演算法的敘述,何者有誤?

(A)不一定要有輸入

(B)只有一個輸出

(C)程序明確可行

(D)強調正確性。

Answer
B

8.演算法所具備的條件中,何者是指演算法必須在有限步驟內結束?

(A) 正確性

(B) 明確性

(C) 有限性

(D) 輸入資料

Answer
C

9. 完整的演算法包括?

(A)明確的輸入資料

(B)詳細且有限的執行步驟

(C)明確的輸出資料

(D)以上皆是

Answer
D

9.電腦程式演算法不需滿足以下何條件?

(A)一定要有輸入

(B)一定要有輸出

(C)一定要能在有限的步驟內執行完成

(D)演算法中各指令的意義都必須是明確不模糊的

Answer
A

10.下列何者不是演算法的特性?

(A) 正確性

(B) 明確性

(C) 有限性

(D) 快速性

Answer
D

11.在流程圖中符號”◇”表示何種意義?

(A)輸出

(B)處理

(C)判斷

(D)開始

Answer
C

12.在流程圖中符號”□”表示何種意義?

(A)輸出

(B)處理

(C)判斷

(D)開始

Answer
B

13.描述演算法有三種方法,下列那一種不是?

(A)文字敘述

(B)流程圖

(C)虛擬碼

(D)知識地圖

Answer
D

14.下列那一種演算法是在文字摻雜程式語言,以描述解題步驟與方法?

(A)虛擬碼(Pseudo Code)

(B)文字描述

(C)流程圖

(D)以上皆非

Answer
A

15.下列撰寫程式步驟何者是正確的?

(A) 需求、演算法、偵錯、程式碼、可執行

(B) 演算法、需求、程式碼、偵錯、可執行

(C) 需求、演算法、程式碼、偵錯、可執行

(D) 程式碼、偵錯、演算法、需求、可執行

Answer
C

16.請問程式設計師在撰寫程式步驟中,在那一個階段就必須要選擇適當的程式語言呢?

(A)第一階段

(B)第二階段

(C)第三階段

(D)第四階段

Answer
C

17.下列對於演算法與程式的差異何者是正確的?

(A)演算法可執行無限迴路

(B)程式可執行無限迴路

(C)程式與演算法皆具有「有限性」

(D)以上皆非

Answer
B

18.下列對於演算法的敘述何者錯誤?

(A) 強調「可讀性」

(B) 以「電腦」為主

(C) 以「人」為主

(D) 可利用虛擬碼來說明

Answer
B

19.下列有關撰寫程式的目的何者正確?

(A)展現能力與技巧

(B)解決複雜問題

(C)解決容易的題目

(D)解決無解的問題

Answer
B

20.你認為人腦與電腦最大的差異為何?

(A)人腦較能處理重複性的問題

(B)人腦與電腦都不能處理重複性的問題

(C)電腦較能處理重複性的問題

(D)以上皆是

Answer
C

21. 請決定下列迴圈中指定敘述(sum = sum + 1;)執行的次數。

for (int i = 0 ;  i <= n ;  i++)
           sum = sum + 1;           //次數=終值-初值+1=n-0+1=n+1

(A) 1  (B) n-1  (C) n  (D) n+1

Answer
D

22.請決定下列迴圈中指定敘述(sum = sum + 1;)執行的次數。

    for ( i = 1; i < n ; i ++)
        for ( j = 1 ; j < n ; j++)           
            sum = sum + 1 ;

(A) n (n-1)  (B) n (n+1)  (C) (n-1)2  (D) n2

Answer
C

23.下列何者是用來評估一個好程式的條件?

(A)正確性

(B)效率性

(C)可維護性

(D)以上皆是

Answer
D

24.下列何者是一個好程式最基本的要求?

(A)正確性

(B)效率性

(C)可維護性

(D)以上皆非

Answer
A

25.有關「頻率次數(Frequency Count)」的敘述,下列何者正確?

(A)頻率次數愈低,代表執行時間愈長

(B)頻率次數愈高,代表執行時間愈長

(C)頻率次數愈高,代表執行時間愈低

(D)以上皆非

Answer
B

26.在撰寫程式時,適時的加入「註解」,此技巧是屬於評估一個好程式的那一個條件?

(A)正確性

(B)效率性

(C)可維護性

(D)以上皆是

Answer
C

27.一個好的程式,不只需要有效率地被正確地執行之外,也必須要考慮那些要素呢?

(A)程式的可讀性

(B)程式的未來修改

(C)程式的擴充性

(D)以上皆是

Answer
D

28.下列何者不是程式可維護性的要素之一?

(A)結構化程式設計

(B)縮排

(C)註解

(D)版權聲明

Answer
D

29.有關好程式的敘述何者有誤?

(A)程式要小

(B)段落分明

(C)達到系統功能

(D)易懂易維護

Answer
A

30.在結構化程式設計中,將程式分解成多個具有獨立功能的模組,它是利用那一種技巧?

(A)由上而下

(B)由下而上

(C)由外而內

(D)由內而外

Answer
A

 31.結構化程式設計所提供的三種結構,下列何者不是?

(A)排序

(B)重複

(C)選擇

(D)循序

Answer
A

32.在結構化程式設計中,盡量少用那一種技巧?

(A)循序

(B)重複

(C)選擇

(D)Goto

Answer
D

33.下列何者非結構化程式設計的特性?

(A)藕合性強

(B)內聚力強

(C)少用Goto

(D)由上而下設計

Answer
A

34.何者不是結構化程式語言的基本控制結構

(A)跳躍

(B)循序

(C)決策分支

(D)迴圈

Answer
A

35.在下列的情況中,那一種情況不會使用到循序結構呢?

(A)計算攝氏與華氏

(B)判斷奇數或偶數

(C)計算平均成績

(D)計算總和

Answer
B
 

36.在下列的情況中,那一種情況會使用到選擇結構呢?

(A)計算攝氏與華氏

(B)判斷同意或不同意

(C)計算平均成績

(D)計算總和

Answer
B
 

37.在下列的情況中,那一種情況較不適合使用重複結構呢?

(A)計算全班50位同學成績

(B)計算2位同學成績

(C)九九乘法表

(D)次數固定的題目

Answer
B

38.下列何者不是用來評估一個演算法的效率方式?

(A)時間複雜度

(B)空間複雜度

(C)時間與空間複雜度

(D)配置複雜度

Answer
D

39.為何在評估「時間複雜度」時,往往只考慮到執行的次數呢?

(A)評估撰寫的演算法比較不客觀

(B)評估機器的CPU執行速度比較不客觀

(C)評估記憶體的容量比較不客觀

(D)以上皆非

Answer
B

40.主程式呼叫副程式時,往往會佔用到記憶體空間,請問在進行演算法的效率評估時,是屬於那一種評估方法?

(A)時間複雜度

(B)空間複雜度

(C)時間與空間複雜度

(D)配置複雜度

Answer
B

41.下列時間複雜度(Time Complexity) 何者的時間最少?

(A) O (n!)

(B) O (nlog2n)

(C) O (n)

(D) O (log2 n)

Answer
D

42.下列複雜度 1.O(n2)  2. O(n)  3. O(n log2 n )  4.O(log2 n)  5.O(2n),依序由小到大為:

(A) 12345

(B) 42315

(C) 34215

(D) 42351

Answer
B

43.若一程式的執行時間是 60n2+20nlgn,則時間複雜度為何?
(A) O(60n2)

(B) O(nlog2n)

(C) O(n2)

(D) O(20nlog2n)

Answer
C

44.如果一個程式的時間複雜度為O(N2) ,其中N為輸入資料量, 則當資料量增加為原來的100倍時, 計算的時間增加為原來的幾倍?

(A) 10

(B) 102

(C) 103

(D) 104

Answer
D

45.時間複雜度O(N2)、O(N log2N)、O(N3)、O(2N) ,何者效率最佳?

(A) O(N2)

(B)O(N log2N)

(C)O(N3)

(D)O(2N)

Answer
B

46.計算下面程式的時間複雜度(請使用Big-O表示)

for(i=0; i < n; ++i) Console.WriteLine(“{0}”, i);

(A) O (n!)

(B) O (nlog2n)

(C) O (n)

(D) O (log2 n)

Answer
C

47.如果一個程式的頻率計數為3n3 +6n2 + 4n + 9,則時間複雜度為何?

(A) O(n)

(B) O(1)

(C) O(n2)

(D) O(n3)

Answer
D

48.時間複雜度O(n2)、O(nlogn)、O(n!)、O(2n),那一個最沒有效率?

(A) O(n2)

(B) O(nlogn)

(C) O(n!)

(D) O(2n)

Answer
C

49.時間複雜度O(n2)、O(nlogn)、O(n!)、O(2n),那一個最有效率?

(A) O(n2)

(B) O(nlogn)

(C) O(n!)

(D) O(2n)

Answer
B

50.若兩個矩陣大小均為n × n,則此二個矩陣相加的時間複雜度為何?

(A) O(n)

(B) O(n2)

(C) O(n log n)

(D) O(n3)

Answer
B

51.若矩陣大小為n × n,則此矩陣轉置的時間複雜度為何?

(A) O(n)

(B) O(n2)

(C) O(n log n)

(D) O(n3)

Answer
B

52.若兩個矩陣大小均為n × n,則此二個矩陣相乘的時間複雜度為何?

(A) O(n)

(B) O(n2)

(C) O(n log n)

(D) O(n3)

Answer

D
矩陣相乘的程式碼:

#include <iostream>  

void MultiplyWithOutAMP() {  

    int aMatrix[3][2] = {{1, 4}, {2, 5}, {3, 6}};  
    int bMatrix[2][3] = {{7, 8, 9}, {10, 11, 12}};  
    int product[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};  

    for (int row = 0; row < 3; row++) {  
        for (int col = 0; col < 3; col++) {  
            // Multiply the row of A by the column of B to get the row, column of product.  
            for (int inner = 0; inner < 2; inner++) {  
                product[row][col] += aMatrix[row][inner] * bMatrix[inner][col];  
            }  
            std::cout << product[row][col] << "  ";  
        }  
        std::cout << "\n";  
    }  
}  

void main() {  
    MultiplyWithOutAMP();  
    getchar();  
}

 

53.若有一個矩陣大小均為n,此矩陣內的元素相加的時間複雜度為何?

(A) O(n)

(B) O(n2)

(C) O(n log n)

(D) O(n3)

Answer
A

54.程式本身的指令空間是屬於空間複雜度的那一個需求?

(A)固定的空間需求

(B)變動空間需求

(C)立體空間需求

(D)時間空間需求

Answer
A

55.遞迴函數執行是屬於空間複雜度的那一個需求?

(A)固定的空間需求

(B)變動空間需求

(C)立體空間需求

(D)時間空間需求

Answer
B

【C#-題庫】運算子 Operator

1.以下何者能夠正確地將一個變數加1?

  1. ++a++;
  2. a += 1;
  3. a ++ 1;
  4. a = a +1;
  5. a = +1;

A. 1, 3
B. 2, 4
C. 3, 5
D. 4, 5
E. None of these (以上皆非)

Answer
B

2. 底下程式碼的輸出為何?

byte b1 = 0xF7;
byte b2 = 0xAB;
byte temp;
temp = (byte)(b1 & b2);
Console.Write (temp + " ");
temp = (byte)(b1^b2);
Console.WriteLine(temp);

A. 163 92
B. 92 163
C. 192 63
D. 0 1

Answer
A

3. 下列何者不是數值運算子?
A. **
B. +
C. /
D. %
E. *

Answer
A

4. 以下何者不是關係運算子?

  1. >=
  2. !=
  3. Not
  4. <=
  5. <>=

A. 1, 3
B. 2, 4
C. 3, 5
D. 4, 5
E. None of these

Answer
C

5. 以下何者不是逐位元(Bitwise)運算子?

A. &
B. |
C. <<
D. ^
E. ~

Answer
C

6. 何者對底下程式的敘述正確?

int d;
d = Convert.ToInt32( !(30 < 20) );

A.  0會被指定給d。
B.  1會被指定給d。
C.  -1會被指定小d。
D. 程式有錯誤。
E.  若!被換成Not的話,上面程式就會正常運作。

Answer

B

範例程式:

bool falseFlag = false;
bool trueFlag = true;

Console.WriteLine("{0} converts to {1}.", falseFlag,
Convert.ToInt32(falseFlag));
Console.WriteLine("{0} converts to {1}.", trueFlag,
Convert.ToInt32(trueFlag));

範別輸出:

False converts to 0.
True converts to 1.

7. 底下程式的輸出為何?

Console.WriteLine(13 / 2 + " " + 13 % 2);

A. 6.5 1
B. 6.5 0
C. 6 0
D. 6 1
E. 6.5 6.5

Answer
D

 

8. 以下何者是邏輯(Logical)運算子?

  1. &&
  2. ||
  3. !
  4. Xor
  5. %

A. 1, 2, 3
B. 1, 3, 4
C. 2, 4, 5
D. 3, 4, 5
E. None of these

Answer
A

9. 設n是一個Byte型態的變數,我們想要檢查n的第4個位元(從右邊算起)是0(OFF)還是1(ON)的話,要如何做?
A.

if ((n&16) == 16)
Console.WriteLine("Fourth bit is ON");

B.

if ((n&8) == 8)
Console.WriteLine("Fourth bit is ON");

C.

if ((n ! 8) == 8)
Console.WriteLine("Fourth bit is ON");

D.

if ((n ^ 8) == 8)
Console.WriteLine("Fourth bit is ON");

E.

if ((n ~ 8) == 8)
Console. WriteLine("Fourth bit is ON");
Answer

B
byte myByte = 153; // 字元表示 為 10011001

byte n = 8; // In 字元表示為  00001000
(1是從右邊算過來的第4個位元)

進行邏輯AND 運算(n & myByte)

10011001
00001000
————-
00001000 此值非0,因此評估為true。
———
因為結果為true,可以判斷myByte第4個位元是ON。

10. 底下程式碼的輸出為何?

int num = 1, z = 5;

if (!(num <= 0))
Console.WriteLine( ++num + z++ + " " + ++z );
else
Console.WriteLine( --num + z-- + " " + --z );

A. 5 6
B. 6 5
C. 6 6
D. 7 7

Answer
D

11. 設n是Byte字元型態,我們若想對其第4個位元關閉的話(設為0),且要不影響到其他的位元,要如何做?
A. n = n && HF7
B. n = n & 16
C. n = n & 0xF7
D. n = n & HexF7
E. n = n & 8

Answer
C

12. 底下程式的輸出為何?

byte b1 = 0xAB;
byte b2 = 0x99;
byte temp;
temp = (byte)~b2;
Console.Write(temp + " ");
temp = (byte)(b1 << b2);
Console.Write (temp + " ");
temp = (byte) (b2 >> 2);
Console.WriteLine(temp);

A. 102 1 38
B. 108 0 32
C. 102 0 38
D. 1 0 1

Answer
C

13. 以下何者不是指定運算子?
A. \=
B. /=
C. *=
D. +=
E. %=

Answer
A

14. 底下程式的輸出為何?

int i, j = 1, k;
for (i = 0; i < 5; i++)
{
  k = j++ + ++j;
  Console.Write(k + " ");
}

A. 8 4 16 12 20
B. 4 8 12 16 20
C. 4 8 16 32 64
D. 2 4 6 8 10

Answer
B

15. 底下程式的輸出為何?

int a = 10, b = 20, c = 30;
int res = a < b ? a < c ? c : a : b;
Console.WriteLine(res);

A. 10
B. 20
C. 30
D. Compile Error / Syntax Error

Answer
C

14. 關於底下程式的描述何者正確?

int a = 10;
int b = 20;
bool c;
c = !(a > b);
  1. 程式沒有錯誤。
  2. 一個錯誤會發生,因為!僅能使用在int上。
  3. 1會指定給變數c。
  4. true會指定給變數c。
  5. false會指定給變數c。

A. 1, 3
B. 2, 4
C. 4, 5
D. 1, 4
E. None of these

Answer
D

 

【C#-題庫】資料型態

1.以下那一個關於資料型態的敘述是正確的??

  1. 如果整數文字(指寫在程式裏的整數文字)超出其範圍時,會產生編譯錯誤。
  2. 我們不可以隱含地將較大的數值放到一個較小的數值型態。
  3. Byte型態不可以隱含地轉換成float型態。
  4. 一個字元僅可以被隱含地轉換成int資料型態。
  5. 我們可以轉換整數的型態。

A. 1, 3, 5
B. 2, 4
C. 3, 5
D. 1, 2, 5

Answer
D

2.何者是一個8位元組的整數?
A. Char
B. Long
C. Short
D. Byte
E. Integer

Answer
B

3.何者不是一個整數(Integer)?
A. Char
B. Byte
C. Integer
D. Short
E. Long

Answer
A

4. 下列何者敘述正確?
A. 在進行縮小化的轉換時,資訊不會遺失。
B. CInteger()被用來轉換一個Single到Integer。
C. Widening conversions take place automatically. 擴展轉換是自動發生的。
D. 指定一個Integer到一個Object型態是所熟知的Unboxing(拆箱)。
E. 3.14 能以 3.14F的形式當成一個 Decimal 型態。

Answer
C

5. 以下何者是數值型態?
1.Integer
2.Array
3.Single
4.String
5.Long
A. 1, 2, 5
B. 1, 3, 5
C. 2, 4
D. 3, 5

Answer
B

6. 下列何者不儲存正負號?
A. Short
B. Integer
C. Long
D. Byte
E. Single

Answer
D

7. Decimal的大小?
A. 4 byte
B. 8 byte
C. 16 byte
D. 32 byte

Answer
C

8. 當底下的程式碼執行時,輸出為?

int x = 1;
float y = 1.1f;
short z = 1;
Console.WriteLine((float) x + y * z - (x += (short) y));

A. 0.1
B. 1.0
C. 1.1
D. 11

Answer
A

9. 對於下面的程式,那一個敘述是正確的?

short s1 = 20;
short s2 = 400;
int a;
a = s1 * s2;

A.  一個8000的數值將指定給a。
B. 一個負值將指定給a。
C. 在進行數值的運算時,如果結果超出了範圍,那麼結果超出範圍的部份將會被消去。
D. 進行擴展轉換時不會發生任何的錯誤。
E. 由於相乘的結果超出了一個Short整數範圍,會發生一個溢位的錯誤。

Answer
A

10. Decimal 資料型態的正確大小?
A. 8 Bytes
B. 4 Bytes
C. 10 Bytes
D. 16 Bytes
E. None of the above.

Answer
D

11.以下那一個敘述是正確的??

  1. 我們可以指定任何型態的值給object型態的變數。
  2. 當一個數值型態的變數被轉換成object型態,稱之為拆箱(unboxed)。
  3. 當一個object型態的變數被轉換為數值型態時,稱之為裝箱(boxed)。
  4. 布林Boolean 變數不可以為null。
  5. 當一個數值變數被裝箱時,一個全新的object必須被配置且建置。

A. 2, 5
B. 1, 5
C. 3, 4
D. 2, 3

Answer
B

12. 下列何者是正確的方式來設定 3.14給變數pi,使得該變數的值不會被修改?
A. float pi = 3.14F;
B. #define pi 3.14F;
C. const float pi = 3.14F;
D. const float pi; pi = 3.14F;
E. pi = 3.14F;

Answer
C

 

14.

以下何者正確地對i與j變數初始化為10?

1 int i = 10; int j = 10;
2 int i, j;
i = 10 : j = 10;
3 int i = 10, j = 10;
4 int i, j = 10;
5 int i = j = 10;
A. 2, 4
B. 1, 3
C. 3, 5
D. 4, 5

Answer
B

14. 以下何者正確地指定33給變數c?
byte a = 11, b = 22, c;
A. c = (byte) (a + b);
B. c = (byte) a + (byte) b;
C. c = (int) a + (int) b;
D. c = (int)(a + b);
E. c = a + b;

Answer
A

15. 以下何者是Boolean 的預設值?
A. 0
B. 1
C. True
D. False
E. -1

Answer
D

【程式設計-C#】電費計算器(非時間電價,非營業用)

  • 台電 – 電價表

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            double D = Convert.ToDouble(textBox1.Text); //將輸入的度數字串轉成浮點數double
            double MS = 0, MW = 0; //MS夏日電費, MW非夏日電費;
            int L120 = 120, L330 = 330, L500 = 500, L700 = 700, L1000 = 1000;
            double s163 = 1.63, s238 = 2.38, s352 = 3.52, s461 = 4.61, s542 = 5.42, s613 = 6.13; //夏日費率
            double w163 = 1.63, w210 = 2.10, w289 = 2.89, w379 = 3.79, w442 = 4.42, w483 = 4.83; //非夏日費率

            //計算夏日電費
            if (D <= L120) MS = D * s163;
            else if (D <= L330)  MS = L120 * s163 + (D - L120) * s238 ;
            else if (D <= L500)  MS = L120 * s163 + (L330 - L120) * s238 + (D - L330) * s352;
            else if (D <= L700)  MS = L120 * s163 + (L330 - L120) * s238 + (L500 - L330) * s352 + (D - L500) * s461;
            else if (D <= L1000) MS = L120 * s163 + (L330 - L120) * s238 + (L500 - L330) * s352 + (L700 - L500) * s461 + (D - L700) * s542; 
            else                 MS = L120 * s163 + (L330 - L120) * s238 + (L500 - L330) * s352 + (L700 - L500) * s461 + (L700 - L1000) * s542 + (D - L1000) * s613; ;

            //計算非夏日電費
            if (D <= L120) MW = D * w163;
            else if (D <= L330) MW = L120 * w163 + (D - L120) * w210;
            else if (D <= L500) MW = L120 * w163 + (L330 - L120) * w210 + (D - L330) * w289;
            else if (D <= L700) MW = L120 * w163 + (L330 - L120) * w210 + (L500 - L330) * w289 + (D - L500) * w379;
            else if (D <= L1000) MW = L120 * w163 + (L330 - L120) * w210 + (L500 - L330) * w289 + (L700 - L500) * w379 + (D - L700) * w442;
            else MW = L120 * w163 + (L330 - L120) * w210 + (L500 - L330) * w289 + (L700 - L500) * w379 + (L700 - L1000) * w442 + (D - L1000) * w483; ;

            if (radioButton1.Checked) label4.Text = MS.ToString();
            else label4.Text = MW.ToString();
        }

        private void S2NS(object sender, EventArgs e) //2個RadioBuuton 的 共同 Click事件函式
        {
            RadioButton rb = (RadioButton)sender;
            if (rb.Checked) button1_Click(rb, e);
        }
    }
}