[翻译]C#数据结构与算法 – 第六章BitArray类
BitArray類用于在資源有限的情況下表示一系列比特值。比特集合可以存儲于常規數組,但是如果我們使用專為比特集合設計的數據結構則可以創建更高效的程序。在本章中,我們將學習一下怎樣使用這種數據結構并研究一些可以使用比特集合來解決的問題。本章中同時復習了二進制數字,以及按位比較與移位運算符。
一個激起興趣的問題
讓我們看一個將最終使用BitArray類來解決的問題。這個問題的要求是找到質數。一個比較原始的方法是公元前三世紀的希臘哲學家埃拉托色尼發現的被稱為愛拉托遜斯篩法的方法。這個方法過濾掉可以整除其它數字的數字,直到剩下的數字均為質數為止。例如,讓我們找出前100個整數這個集合中的質數。我們由第一個質數2開始。我們遍歷集合移除所有2的倍數。然后我們繼續下一個質數3。我們再次遍歷集合,移除所有3的倍數。接著我們移動到5,如此繼續。當我們完成時,所有剩下的數字都是質數。
首先我們使用一個常規數組解決這個問題。我們將使用的這種方法與即將使用的用一個BitArray來解決問題的方法很類似,都是初始化數組的100個元素,并將每個元素的值置為1。由索引2開始(由于2是第一個質數),每個后來的數組索引都首先被查看值為1還是0。如果值為1,接著判斷索引數是否為2的倍數。如果是,將這個索引位置的值設置為0。然后我們移動到索引3,進行相同的處理并繼續。
要編寫代碼解決這個問題,我們將使用之前編寫的Carray類。首先要做的是創建一個方法來執行篩選。如下是代碼:
1 public void GenPrimes() 2 { 3 int temp; 4 for (int outer = 2; outer <= arr.GetUpperBound(0); outer++) 5 for (int inner = outer + 1; inner <= GetUpperBound(0); inner++) 6 if (arr[inner] == 1) 7 if ((inner % outer) == 0) 8 arr[inner] = 0; 9 }現在我們僅需要就是一個顯示質數的方法:
1 public void ShowPrimes() 2 { 3 for (int i = 2; i <= arr.GetUpperBound(0); i++) 4 if (arr[i] == 1) 5 Console.Write(i + " "); 6 }下面是一個測試我們代碼的程序:
1 static void Main() 2 { 3 int size = 100; 4 CArray primes = new CArray(size - 1); 5 for (int i = 0; i <= size - 1; i++) 6 primes.Insert(1); 7 primes.GenPrimes(); 8 primes.ShowPrimes(); 9 }這個方法展示了怎樣在整數數組中使用愛拉托遜斯篩法,但是更好的建議是使用比特來開發一個解決方案,因為這種數組中每個元素都是1或0。本章后面我們將學習怎樣使用BitArray類來同時實現愛拉托遜斯篩法與其他將自己借位給比特集合的問題。
位與位操作
在我們研究BitArray類之前,我們需要研究怎樣在VB.NET中使用位,由于在位一級操作是大多數VB.NET程序員所不熟悉的。在本節中,我們將學習怎樣在VB.NET中操作位,主要通過學習怎樣使用按位運算符操作比特值來學習。
二進制計數系統
在學習操作比特值之前,讓我們復習一下二進制計數系統。二進制數字是使用0與1兩個字符串來將基于10的(十進制)數字以基于2的數字來表示。例如,二進制中整數0表示如下:
00000000
整數1的二進制數字為:
00000001
如下是二進制中整數0-9所顯示的形式:
00000000—0d (where d signifies a decimal number)
00000001—1d
00000010—2d
00000011—3d
00000100—4d
00000101—5d
00000110—6d
00000111—7d
00001000—8d
00001001—9d
最佳的將一個二進制數字轉換為等值的十進制的方法是使用如下的方案。每一個二進制數字中,由最右端數字開始都代表了一個連續增大的2的冪。如果第一個位置上的數字是一個1,則其代表20。如果第二個位置有一個1,則其代表21,等等。
二進制數字:
00101010
等價于:
0 + 21 + 0 + 23 + 0 + 25 + 0 + 0 = 0 + 2 + 0 + 8 + 0 + 32 + 0 + 0 = 42
位通常顯示于8個位的集合中,這組成了一個字節。使用8個位可以表示的最大數字為255,二進制如下:
11111111
或
1 + 2 + 4 + 8 + 16 + 32 + 64 + 128 = 255
一個大于255的數字必須存儲于16位中。例如二進制數表示的256為:
00000001 00000000
雖然不是必須,但習慣上將低8位與高8位分隔。
操作二進制數字:按位操作與位移操作符
二進制數字并不使用基本算術運算符來操作。你必須使用按位操作運算符(And, Or, Not)或位移操作運算符(<<, >>, and >>>)。在這節中,我們解釋這些運算符怎樣工作并在后面的章節演示它們在VB.NET程序中的使用。
首先,我們研究按位操作運算符。這些大多數程序員已經熟悉的邏輯運算符 – 它們用來合并相關的表達式以便計算一個單一的布爾值。按位運算符操作二進制數字,逐位比較兩個二進制數字,迭代生成一個新的二進制數字。
按位運算符以操作布爾值相同的方式工作。當操作二進制數字時,True位等價于1,False位等價于0。我們使用一個真值表來展示按位運算符對位的操作,正如對布爾值操作使用的真值表那樣。一行中前兩列為操作數,第三列為運算結果。And操作的真值表(布爾值表示)如下:
| True | True | True |
| True | False | False |
| False | True | False |
| False | False | False |
等價的位值的真值表:
| 1 | 1 | 1 |
| 1 | 0 | 0 |
| 0 | 1 | 0 |
| 0 | 0 | 0 |
Or操作的布爾值真值表為:
| True | True | True |
| True | False | True |
| False | True | True |
| False | False | False |
等價的位值的真值表:
| 1 | 1 | 1 |
| 1 | 0 | 1 |
| 0 | 1 | 1 |
| 0 | 0 | 0 |
最后是Xor運算符。這是最不被了解的一個按位運算符,因為其不用于計算機程序執行的邏輯運算。當兩個位值進行Xor比較操作時,當兩個位操作數中恰有一個為1時結果為1,如下是真值表:
| 1 | 1 | 0 |
| 1 | 0 | 1 |
| 0 | 1 | 1 |
| 0 | 0 | 0 |
將這些表格記在腦子中,我們使用這些操作符合并二進制數來迭代生成新的二進制數。如下是一些例子:
00000001 And 00000000 -> 00000000
00000001 And 00000001 -> 00000001
00000010 And 00000001 -> 00000000
00000000 Or 00000001 -> 00000001
00000001 Or 00000000 -> 00000001
00000010 Or 00000001 -> 00000011
00000000 Xor 00000001 -> 00000001
00000001 Xor 00000000 -> 00000001
00000001 Xor 00000001 -> 00000000
現在,讓我們看一下一個VB.NET版的Windows應用程序更好的展示按位運算符的工作。
按位運算符應用程序
我們可以使用一個將這些運算符應用到一對值的Windows應用程序演示按位運算符的工作方式。我們將使用之前開發的ConvertBits方法幫助我們使用按位運算符。
首先,讓我們看一下程序的用戶界面,在解釋程序的工作方式的過程中這界面將一直伴隨著我們。
輸入兩個整數值,選擇一種按位運算符的按鈕。由每個整數值轉換而來的位值與由按位運算符計算而得的位字符串結果一起顯示出來。如下是一個例子,1與2這兩個值進行AND運算的結果:
如下是1與2這兩個值進行OR 運算的結果:
如下是操作的代碼:
1 using System; 2 using System.Drawing; 3 using System.Collections; 4 using System.ComponentModel; 5 using System.Windows.Forms; 6 using System.Data; 7 using System.Text; 8 9 public class Form1 : System.Windows.Forms.Form 10 { 11 private System.Windows.Forms.Button btnAdd; 12 private System.Windows.Forms.Button btnClear; 13 private System.Windows.Forms.Button btnOr; 14 private System.Windows.Forms.Button btnXor; 15 private System.Forms.Label lblInt1Bits; 16 private System.Forms.Label lblInt2Bits; 17 private System.Forms.TextBox txtInt1; 18 private System.Forms.TextBox txtInt2; 19 20 // other Windows app code here 21 private void btnAdd_Click(object sender, System.EventArgs e) 22 { 23 int val1, val2; 24 val1 = Int32.Parse(txtInt1.Text); 25 val2 = Int32.Parse(txtInt2.Text); 26 lblInt1Bits.Text = ConvertBits(val1).ToString(); 27 lblInt2Bits.Text = ConvertBits(val2).ToString(); 28 } 29 30 private StringBuilder ConvertBits(int val) 31 { 32 int dispMask = 1 << 31; 33 StringBuilder bitBuffer = new StringBuilder(35); 34 for (int i = 1; i <= 32; i++) 35 { 36 if ((val && bitMask) == 0) 37 bitBuffer.Append("0"); 38 else 39 bitBuffer.Append("1"); 40 val <<= 1; 41 if ((i % 8) == 0) 42 bitBuffer.Append(" "); 43 } 44 return bitBuffer; 45 } 46 47 private void btnClear_Click(object sender, System.EventArgs e) 48 { 49 txtInt1.Text = ""; 50 txtInt2.Text = ""; 51 lblInt1Bits.Text = ""; 52 lblInt2Bits.Text = ""; 53 lblBitResult.Text = ""; 54 txtInt1.Focus(); 55 } 56 57 private void btnOr_Click(object sender, System.EventArgs e) 58 { 59 int val1, val2; 60 val1 = Int32.Parse(txtInt1.Text); 61 val2 = Int32.Parse(txtInt2.Text); 62 lblInt1Bits.Text = ConvertBits(val1).ToString(); 63 lblInt2Bits.Text = ConvertBits(val2).ToString(); 64 lblBitResult.Text = ConvertBits(val1 || val2).ToString(); 65 } 66 67 private void btnXOr_Click(object sender, System.EventArgs e) 68 { 69 int val1, val2; 70 val1 = Int32.Parse(txtInt1.Text); 71 val2 = Int32.Parse(txtInt2.Text); 72 lblInt1Bits.Text = ConvertBits(val1).ToString(); 73 lblInt2Bits.Text = ConvertBits(val2).ToString(); 74 lblBitResult.Text = ConvertBits(val1 ^ val2).ToString(); 75 } 76 }?
移位操作符
一個二進制數字僅包含0與1,數字中每一位表示0或者一個2的冪值。C#中你可以使用3個運算符改變一個二進制數字中位的位置。它們是:左移運算符(<<)與右移運算符(>>)。
每個運算符都接受兩個操作數:一個值(左側操作數)與要將位移動的數目(右側操作數)。例如,如果我們這樣寫:
1 << 1
結果是00000010。通過2 >> 1這個表達式我們又可以將結果逆回去。
看一個更復雜的例子。3的二進制數表示是:
00000011
如果進行3 << 1,結果是:
00000110
而如果進行3 << 2,結果是:
00001100
右移位運算符以與左移位運算符正好相反的方式工作。例如,如果編寫3 >> 1
結果為00000001。
在本節的后面,我們將看到怎樣編寫一個Windows應用程序來展示移位運算符的使用。
整型到二進制轉換程序
在本節中,我們展示了怎樣使用一些位運算符來判斷一個整數值中的位模式。用戶輸入一個整數值并按下Display bits按鈕。整數值被轉換為二進制后以8位一組的方式顯示在一個label中。
我們用來將整數轉換為二進制形式的核心工具是掩碼。轉換函數使用掩碼來在顯示一個數字中一些位時隱藏另一些位。當掩碼與整數值(操作數)使用AND操作符合并時,結果是一個表示整數值二進制字符串。
首先,讓我們看一些整數值及其二進制的表示:
計算機中負整數的二進制不總是那么易懂,正如這個例子中展示的。更多信息,參考一本有關匯編語言或計算機組織的書。
正如你看到的,這最后一個值,65535,是可以放入16位的最大數值。如果我們將數值增到65536,我們將得到下面的結果:
最后,讓我們看一下將C#中可以存儲的最大整數轉換為二進制時會發生什么:
如果你嘗試輸入2147483648,你會看到一個錯誤。你可能會想最左邊位的位置是可用的,但是實際上不可以的,因為那個位是用來處理負整數情況的。
現在讓我們來看一下驅動這個程序的代碼。我們將首先列出程序然后解釋程序的工作方式:
1 using System; 2 using System.Drawing; 3 using System.Collections; 4 using System.ComponentModel; 5 using System.Windows.Forms; 6 using System.Data; 7 using System.Text; 8 9 public class Form1 : System.Windows.Forms.Form 10 { 11 // Windows generated code omitted here 12 private void btnOr_Click(object sender, System.EventsArgs e) 13 { 14 int val1, val2; 15 val1 = Int32.Parse(txtInt1.Text); 16 val2 = Int32.Parse(txtInt2.Text); 17 lblInt1Bits.Text = ConvertBits(val1).ToString(); 18 lblInt2Bits.Text = ConvertBits(val2).ToString(); 19 lblBitResult.Text = ConvertBits(val1 || val2).ToString(); 20 } 21 22 private StringBuilder ConvertBits(int val) 23 { 24 int dispMask = 1 << 31; 25 StringBuilder bitBuffer = new StringBuilder(35); 26 for (int i = 1; i <= 32; i++) 27 { 28 if ((val && bitMask) == 0) 29 bitBuffer.Append("0"); 30 else 31 bitBuffer.Append("1"); 32 val <<= 1; 33 if ((i % 8) == 0) 34 bitBuffer.Append(" "); 35 } 36 return bitBuffer; 37 } 38 }這個程序中大部分工作由ConvertBits函數來完成。dispMask這個變量存儲位掩碼,bitBuffer這個變量存儲函數構建的位字符串。bitBuffer被聲明為一個StringBuilder類型的變量,以方便我們使用它的Append方法來構建字符串而不是用連接。
for循環中構建了二進制的字符串,其進行了32此迭代,正是由于我們構建一個32位的字符串。要構建位字符串,我們將值與位掩碼進行AND運算。如果運算的結果是0,一個0被添加到字符串。如果結果是1,一個1被添加到字符串。然后我們在這個值上執行一次左移位以便接下來計算字符串中下一位。最后,沒8位,我們向字符串添加一個空格以便分隔字符串為4個8位的子字符串,這樣結果更易讀。
位移動演示程序
本節討論一個演示位移動運算符工作方式的Windows應用程序。這個程序提供兩個文本框用來輸入兩個操作數(一個要進行移位的值與要移動的位數),兩個label來顯示左側操作數與移位操作結果的位的原始的二進制表示。這個有兩個按鈕表示執行左移位還是右移位,以及一個清除按鈕和一個退出按鈕。
如下是程序的代碼:
1 using System; 2 using System.Drawing; 3 using System.Collections; 4 using System.ComponentModel; 5 using System.Windows.Forms; 6 using System.Data; 7 using System.Text; 8 9 public class Form1 : System.Windows.Forms.Form 10 { 11 // Windows generated code omitted 12 private StringBuilder ConvertBits(int val) 13 { 14 int dispMask = 1 << 31; 15 StringBuilder bitBuffer = new StringBuilder(35); 16 17 for (int i = 1; i <= 32; i++) 18 { 19 if ((val && bitMask) == 0) 20 bitBuffer.Append("0"); 21 else 22 bitBuffer.Append("1"); 23 24 val <<= 1; 25 if ((i % 8) == 0) 26 bitBuffer.Append(" "); 27 } 28 return bitBuffer; 29 } 30 31 private void btnOr_Click(object sender, System.EventsArgs e) 32 { 33 txtInt1.Text = ""; 34 txtBitShift.Text = ""; 35 lblInt1Bits.Text = ""; 36 lblOrigBits.Text = ""; 37 txtInt1.Focus(); 38 } 39 40 private void btnLeft_Click(object sender, System.EventsArgs e) 41 { 42 int value = Int32.Parse(txtInt1.Text); 43 lblOrigBits.Text = ConvertBits(value).ToString(); 44 value <<= Int32.Parse(txtBitShift.Text); 45 lblInt1Bits.Text = ConvertBits(value).ToString(); 46 } 47 48 private void btnRight_Click(object sender, System.EventsArgs e) 49 { 50 int value = Int32.Parse(txtInt1.Text); 51 lblOrigBits.Text = ConvertBits(value).ToString(); 52 value >>= Int32.Parse(txtBitShift.Text); 53 lblInt1Bits.Text = ConvertBits(value).ToString(); 54 } 55 }下面是運行中程序的一些例子。
如下是4<<2:
如下是256 >> 8:
BitArray類
BitArray類用于與位集合一起工作。一個位集合用于高效的表示一系列的布爾值。BitArray與ArrayList非常類似,如當添加位會超過數組的上界時無需擔心,因為BitArray大小可以被動態的調整。
使用BitArray類
向構造函數中傳入你想要的比特位的數目這樣可以初始化一個BitArray對象:
1 BitArray BitSet = new BitArray(32);這個BitArray對象的32個位均被設置為False。如果我們想讓它們為True,我們可以這樣初始化位數組:
1 BitArray BitSet = new BitArray(32, true);這個類的構造函數有許多不同形式的重載,但是這里我們將僅僅再看另外一種構造函數。你可以使用一個字節(Byte)數組來初始化一個BitArray。例如:
1 byte[] ByteSet = new byte[] { 1, 2, 3, 4, 5 }; 2 BitArray BitSet = new BitArray(ByteSet);這個比特集合 – BitArray目前包含了字節值1,2,3,4和5的位。
位存儲于BitArray時,最重要的位放在最左側(索引0處)的位置。當你閱讀二進制數字的習慣是自右向左時這可能會引起閱讀的混亂。例如,如下是一個與數字1等值的一個8位BitArray的內容:
True False False False False False False False
當然,我們更習慣查看一個最主要位在右側二進制數字,如:
0 0 0 0 0 0 0 1
我們將不得不編寫我們自己的代碼來更改顯示方式為位值(而不是布爾值)與位值常用的顯式順序。
如果BitArray中有字節值,每個字節值的每個位在遍歷數組時將顯示。如下是一個簡單的遍歷一個字節值的BitArray的程序片段:
1 byte[] ByteSet = new byte[] { 1, 2, 3, 4, 5 }; 2 BitArray bitSet = new BitArray(ByteSet); 3 for (int bits = 0; bits <= bitSet.Count - 1; bits++) 4 Console.Write(bitSet.Get(bits) + " ");如下是輸出:
這種輸出幾 乎不可讀,它幾乎沒法真實的反應數組中存儲的內容。稍后我們將看到怎樣使這類BitArray變得簡單易理解。首先,我們需要了解怎樣由一個BitArray中檢索位值。
BitArray中存儲的單獨的位使用Get方法來檢索。這個方法接受一個整型的參數 - 即希望檢索的值的索引,并返回true或false表示的位置。Get方法用于代碼段的前部來顯示BitArray中的位值。
如果我們存儲于BitArray的數據實際上是二進制值(那樣,值應該被表示為0與1),我們需要以恰當的順序 - 由右側開始而不是左側來使用0與1這種方式顯示值。雖然我們不能改變BitArray類使用的內部代碼,我們可以編寫外部代碼得到想要的輸出。
如下程序創建了一個有5個字節值(1,2,3,4,5)的BitArray,并以恰當的二進制格式顯示每個字節:
1 using System; 2 using System.Collections; 3 4 class chapter6 5 { 6 static void Main() 7 { 8 int bits; 9 string[] binNumber = new string[8]; 10 int binary; 11 byte[] ByteSet = new byte[] { 1, 2, 3, 4, 5 }; 12 BitArray BitSet = new BitArray(ByteSet); 13 bits = 0; 14 binary = 7; 15 for (int i = 0; i <= BitSet.Count - 1; i++) 16 { 17 if (BitSet.Get(i) == true) 18 binNumber[binary] = "1"; 19 else 20 binNumber[binary] = "0"; 21 bits++; binary--; 22 if ((bits % 8) == 0) 23 { 24 binary = 7; 25 bits = 0; 26 for (int j = 0; j <= 7; j++) 27 Console.Write(binNumber[j]); 28 } 29 } 30 } 31 }如下是輸出:
00000001
00000010
00000100
00000101
這個程序中使用了兩個數組。第一個數組,BitSet,是一個BitArray,存儲字節值(位格式)。第二個數組,binNumber,只是一個字符串數組用于存儲一個二進制字符串。這個二進制字符串將由每一個比特值的位構建,由最后一個位置(7)開始向前移動至第一個位置(0)。
每次當一個位值被處理的時候,其首先轉換為1(如果是true)或0(如果為false),然后被放置于適當的位置。兩個變量指示我們的處理過程在BitSet數組(位)與binNumber數組(二進制)的位置。我們也需要知道當我們將8個位轉換后結果是一個數字。我們通過將當前位值(在位變量中)對8去模來完成這個工作。如果當前不再有剩余則我們到了第8個位并得到一個數字的結果,否則將繼續這個循環。
我們將這個程序完全實現于Main()函數中,但是在本章最后的聯系中你將有機會通過創建一個類甚至是擴展BitArray類包含這個轉換技術來完善這個程序。
更多BitArray類方法與屬性
在本節,我們討論另外一些使用BitArray類時你最有可能用到的方法與屬性。
Set方法將用于給一個特定的位指定一個值。這個方法使用方式如下:
BitArray.Set(bit, value)
要設置的位通過索引(第一個參數)來指定,第二個參數value(布爾類型)是你希望給這個位指定的布爾值。(雖然布爾值是應該在這里考慮使用的,事實上你也可以使用其它值,如0與1。在下一節你將看到怎樣實現這個功能)
SetAll方法允許你將所有的位值設置為一個你通過參數傳入的值,如BitSet.SetAll(false)。
你可以在一對BitArray對象的所有位上使用And,Or,Xor與Not方法完成逐位操作。例如,我們有兩個BitArray,bitSet1與bitSet2,我們可以按如下方式執行一個按位Or操作:
1 bitSet1.Or(bitSet2);如下表達式:
1 bitSet.Clone();返回一個BitArray的淺拷貝,而如下表達式:
1 bitSet.CopyTo(arrBits);將BitArray的內容拷貝到一個名為arrBits的普通數組。
結束這些概覽后,現在我們可以開始了解怎樣使用一個BitArray來編寫愛拉托遜斯篩法。
使用BitArray完成愛拉托遜斯篩法
在本章開始處,我們展示了怎樣使用一個基本數組編寫程序來實現愛拉托遜斯篩法。在本節,我們展示了相同的算法,這次使用BitArray來實現這個查找素數的方法。
我們編寫的這個程序接受用戶輸入的整數值,并判斷這個數是否為素數,同時展示了一個由1到1024中所有的素數的列表。下面是這個程序的部分截圖:
當這個數字不是素數時將會有如下結果:
下面讓我們看一下代碼:
1 using System; 2 using System.Drawing; 3 using System.Collections; 4 using System.ComponentModel; 5 using System.Windows.Forms; 6 using System.Data; 7 using System.Text; 8 9 public class Form1 : System.Windows.Forms.Form 10 { 11 // Windows generated code omitted 12 private void btnPrime_Click(object sender, System.EventsArgs e) 13 { 14 BitArray bitSet = new BitArray(1024); 15 int value = Int32.Parse(txtValue.Text); 16 BuildSieve(bitSet); 17 if (bitSet.Get(value)) 18 lblPrime.Text = (value + " is a prime number."); 19 else 20 lblPrime.Text = (value + " is not a prime number."); 21 } 22 23 private void BuildSieve(BitArray bits) 24 { 25 string primes; 26 for (int i = 0; i <= bits.Count - 1; i++) 27 bits.Set(i, true); 28 29 int lastBit = Int32.Parse(Math.Sqrt(bits.Count).ToString()); 30 for (int i = 2; i <= lastBit - 1; i++) 31 if (bits.Get(i)) 32 for (int j = 2 * i; j <= bits.Count - 1; j++) 33 bits.Set(j, false); 34 35 int counter = 0; 36 for (int i = 1; i <= bits.Count - 1; i++) 37 if (bits.Get(i)) 38 { 39 primes += i.ToString(); 40 counter++; 41 if ((counter % 7) == 0) 42 primes += "\n"; 43 else 44 primes += "\n"; 45 } 46 txtPrimes.Text = primes; 47 } 48 }如下這個循環中分配了篩子:
1 int lastBit = Int32.Parse(Math.Sqrt(bits.Count).ToString()); 2 for (int i = 2; i <= lastBit - 1; i++) 3 if (bits.Get(i)) 4 for (int j = 2 * i; j <= bits.Count - 1; j++) 5 bits.Set(j, false);這個循環遍歷了從開始一直到BitArray項的數目的平方根那個數的倍數,這個過程中去掉2,3,4,5等數字的倍數。
一旦數組使用篩子構建完畢,我們可以執行一個對BitArray的簡單調用:
1 bitSet.Get(value)如果這個值可以找到,這個值就是一個素數。如果找不到,則它已經被篩子過濾掉,這個數不是素數。
使用BitArray與Array實現的比較
使用BitArray類處理有布爾值或比特值參與的問題被認為是更高效的。一些看起來不涉及這樣類型值的問題可以被重新設計以便BitArray可以派上用場。
如果對一個使用BitArray與一個使用基本數組完成的愛拉托遜斯篩法進行計時,使用BitArray的方法一般要快2倍。在練習中你將有機會親身查看這些結果。
摘要
BitArray類用于存儲位的集合。雖然比特通常用0與1表示,但是BitArray類存儲True或False來取而代之。當你需要存儲一系列的布爾值BitArray就很有用,但是當你需要操作比特時BitArray更有用,因為你可以在比特值與布爾值之間輕松的轉換。
正如本章與其中之一聯系所展示的那樣,可以使用數字數組解決的問題可以使用比特數組更有效的解決。雖然一些讀者可能只將這當成一種新奇(或者已經不再感覺新奇)的編程技巧,但一些特定場景下這種高效存儲比特值或布爾值的方法是不能被拒絕的。
練習
1. 編寫你自己的BitArray類(不要繼承自BitArray類),其中包括一個可以接受布爾值并將其轉換為比特值的方法。提示:使用BitArray類作為你編寫的類的主要的數據結構,然后添加你實現的其它方法。
2. 重新實現題目1所要求的問題,但這次你的類需繼承自BitArray,然后你再添加自己的方法。
3. 使用題目1或2中設計的任意一個BitArray類,編寫一個方法取得一個整數值,將其比特值反轉,并將新值以10進制顯示。
4. 在編程珠璣這本經典編程著作中,作者Jon Bentley討論了有關使用BitArray的編程問題的解決方案,雖然書中稱BitArray為比特向量。在下面的網站閱讀這個問題:
http://www.cs.bell-labs.com/cm/cs/pearls/cto.html
使用VB.NET設計你的解決方案,最小化這個問題所用的數據存儲。當然你不需要使用書中所用的那么大的文件,找一些足夠測試你的實現的東西就好。
5. 編寫一個程序比較使用BitArray與使用基本數組實現愛拉托遜斯篩法的耗時。你的結果如何?
轉載于:https://www.cnblogs.com/lsxqw2004/archive/2010/02/10/1682329.html
總結
以上是生活随笔為你收集整理的[翻译]C#数据结构与算法 – 第六章BitArray类的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用System.Transaction
- 下一篇: s3c2410开发环境建立