回到简体

This commit is contained in:
chai2010
2016-02-15 11:06:34 +08:00
parent 9e878f9944
commit 2b37b23285
177 changed files with 2354 additions and 2354 deletions

View File

@@ -1,8 +1,8 @@
## 6.5. 示例: Bit數組
## 6.5. 示例: Bit数组
Go言里的集合一般用map[T]bool這種形式表示T代表元素型。集合用map類型來表示然非常活,但我可以以一更好的形式表示它。例如在數據流分析域,集合元素通常是一個非負整數,集合包含很多元素,且集合會經常進行併集、交集操作,這種情況bit數組會比map表更加理想。(譯註:這里再充一例子,比如我們執行一http下載任務把文件按照16kb一塊劃分爲很多,需要有一全局變量來標識哪些塊下載完成了,這種時候也需要用到bit數組)
Go言里的集合一般用map[T]bool这种形式表示T代表元素型。集合用map类型来表示然非常活,但我可以以一更好的形式表示它。例如在数据流分析域,集合元素通常是一个非负整数,集合包含很多元素,且集合会经常进行并集、交集操作,这种情况bit数组会比map表更加理想。(译注:这里再充一例子,比如我们执行一http下载任务把文件按照16kb一块划分为很多,需要有一全局变量来标识哪些块下载完成了,这种时候也需要用到bit数组)
bit數組通常用一個無符號數或者稱之爲“字”的slice或者表示,每一元素的每一位都表示集合里的一值。集合的第i位被設置時,我們才説這個集合包含元素i。下面的這個程序展示了一個簡單的bit數組類型併且實現了三個函數來對這個bit數組來進行操作:
bit数组通常用一个无符号数或者称之为“字”的slice或者表示,每一元素的每一位都表示集合里的一值。集合的第i位被设置时,我们才说这个集合包含元素i。下面的这个程序展示了一个简单的bit数组类型并且实现了三个函数来对这个bit数组来进行操作:
<u><i>gopl.io/ch6/intset</i></u>
```go
@@ -39,9 +39,9 @@ func (s *IntSet) UnionWith(t *IntSet) {
}
```
每一字都有64個二進製位,所以了定位x的bit位用了x/64的商作字的下標,併且用x%64得到的值作爲這個字內的bit的所在位置。UnionWith這個方法里用到了bit位的“或”邏輯操作符號|來一次完成64元素的或算。(在練習6.5中我們還會程序用到這個64位字的例子。)
每一字都有64个二进制位,所以了定位x的bit位用了x/64的商作字的下标,并且用x%64得到的值作为这个字内的bit的所在位置。UnionWith这个方法里用到了bit位的“或”逻辑操作符号|来一次完成64元素的或算。(在练习6.5中我们还会程序用到这个64位字的例子。)
當前這個實現還缺少了很多必要的特性,我把其中一些作爲練習題列在本小節之後。但是有一方法如果缺失的話我們的bit數組可能會比較難混:IntSet作爲一個字符串打印。里我們來實現它,讓我們來給上面的例子添加一String方法似2.5中做的那
当前这个实现还缺少了很多必要的特性,我把其中一些作为练习题列在本小节之后。但是有一方法如果缺失的话我们的bit数组可能会比较难混:IntSet作为一个字符串打印。里我们来实现它,让我们来给上面的例子添加一String方法似2.5中做的那
```go
// String returns the set as a string of the form "{1 2 3}".
@@ -66,9 +66,9 @@ func (s *IntSet) String() string {
}
```
里留意一下String方法是不是和3.5.4中的intsToString方法很相似bytes.Buffer在String方法里經常這麽用。當你爲一個複雜的類型定了一String方法fmt包就特殊對待這種類型的值,這樣可以讓這些類型在打印的候看起更加友好而不是直接打印其原始的值。fmt直接調用用戶定義的String方法。這種機製依賴於接口和類型斷在第7章中我們會詳細介紹
里留意一下String方法是不是和3.5.4中的intsToString方法很相似bytes.Buffer在String方法里经常这么用。当你为一个复杂的类型定了一String方法fmt包就特殊对待这种类型的值,这样可以让这些类型在打印的候看起更加友好而不是直接打印其原始的值。fmt直接用用户定义的String方法。这种机制依赖于接口和类型断在第7章中我们会详细介绍
在我就可以在實戰中直接用上面定好的IntSet了
在我就可以在实战中直接用上面定好的IntSet了
```go
var x, y IntSet
@@ -86,7 +86,7 @@ fmt.Println(x.String()) // "{1 9 42 144}"
fmt.Println(x.Has(9), x.Has(123)) // "true false"
```
里要意:我們聲明的String和Has兩個方法都是以指針類型*IntSet來作爲接收器的,但實際上對於這兩個類型來説,把接收器聲明爲指針類型也沒什麽必要。不另外兩個函數就不是這樣了,因另外兩個函數操作的是s.words象,如果你不把接收器聲明爲指針對象,那麽實際操作的是拷貝對象,而不是原的那個對象。因此,因爲我們的String方法定在IntSet指上,所以當我們的變量是IntSet型而不是IntSet指針時,可能有下面這樣讓人意外的情
里要意:我们声明的String和Has两个方法都是以指针类型*IntSet来作为接收器的,但实际上对于这两个类型来说,把接收器声明为指针类型也没什么必要。不另外两个函数就不是这样了,因另外两个函数操作的是s.words象,如果你不把接收器声明为指针对象,那么实际操作的是拷贝对象,而不是原的那个对象。因此,因为我们的String方法定在IntSet指上,所以当我们的变量是IntSet型而不是IntSet指针时,可能有下面这样让人意外的情
```go
fmt.Println(&x) // "{1 9 42 144}"
@@ -94,9 +94,9 @@ fmt.Println(x.String()) // "{1 9 42 144}"
fmt.Println(x) // "{[4398046511618 0 65536]}"
```
在第一Println中打印一*IntSet的指針,這個類型的指針確實有自定的String方法。第二Println直接調用了x量的String()方法;這種情況下編譯器會隱式地在x前插入&操作符,這樣相當遠我們還是調用的IntSet指的String方法。在第三Println中IntSet類型沒有String方法所以Println方法直接以原始的方式理解打印。所以在這種情況&是不能忘的。在我們這種場景下你把String方法定到IntSet象上而不是IntSet指上可能更合一些,不過這也需要具體問題具體分析。
在第一Println中打印一*IntSet的指针,这个类型的指针确实有自定的String方法。第二Println直接用了x量的String()方法;这种情况下编译器会隐式地在x前插入&操作符,这样相当远我们还是调用的IntSet指的String方法。在第三Println中IntSet类型没有String方法所以Println方法直接以原始的方式理解打印。所以在这种情况&是不能忘的。在我们这种场景下你把String方法定到IntSet象上而不是IntSet指上可能更合一些,不过这也需要具体问题具体分析。
練習6.1: bit數組實現下面些方法
练习6.1: bit数组实现下面些方法
```go
func (*IntSet) Len() int // return the number of elements
@@ -105,9 +105,9 @@ func (*IntSet) Clear() // remove all elements from the set
func (*IntSet) Copy() *IntSet // return a copy of the set
```
**練習 6.2**義一個變參方法(*IntSet).AddAll(...int)這個方法可以爲一組IntSet值求和比如s.AddAll(1,2,3)。
**练习 6.2**义一个变参方法(*IntSet).AddAll(...int)这个方法可以为一组IntSet值求和比如s.AddAll(1,2,3)。
**練習 6.3** (*IntSet).UnionWith用|操作符計算兩個集合的交集,我們再爲IntSet實現另外的幾個函數IntersectWith(交集元素在A集合B集合均出),DifferenceWith(差集:元素出在A集合未出在B集合),SymmetricDifference(差集:元素出在A但有出在B或者出在B有出在A)。
練習6.4: 實現一個Elems方法集合中的所有元素,用做一些range之的遍操作。
**练习 6.3** (*IntSet).UnionWith用|操作符计算两个集合的交集,我们再为IntSet实现另外的几个函数IntersectWith(交集元素在A集合B集合均出),DifferenceWith(差集:元素出在A集合未出在B集合),SymmetricDifference(差集:元素出在A但有出在B或者出在B有出在A)。
练习6.4: 实现一个Elems方法集合中的所有元素,用做一些range之的遍操作。
**練習 6.5**們這章定的IntSet里的每字都是用的uint64但是64位的值可能在32位的平台上不高效。改程序使其使用uint型,這種類型對於32位平台來説更合適。當然了,里我可以不用簡單粗暴地除64可以定義一個常量來決定是用32是64里你可能用到平台的自動判斷的一智能表32 << (^uint(0) >> 63)
**练习 6.5**们这章定的IntSet里的每字都是用的uint64但是64位的值可能在32位的平台上不高效。改程序使其使用uint型,这种类型对于32位平台来说更合适。当然了,里我可以不用简单粗暴地除64可以定义一个常量来决定是用32是64里你可能用到平台的自动判断的一智能表32 << (^uint(0) >> 63)