一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Golang - Golang中Bit數(shù)組的實現(xiàn)方式

Golang中Bit數(shù)組的實現(xiàn)方式

2021-06-09 00:55天易獨尊 Golang

這篇文章主要介紹了Golang中Bit數(shù)組的實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧

Go語言里的集合一般會用map[T]bool這種形式來表示,T代表元素類型。集合用map類型來表示雖然非常靈活,但我們可以以一種更好的形式來表示它。

例如在數(shù)據(jù)流分析領域,集合元素通常是一個非負整數(shù),集合會包含很多元素,并且集合會經(jīng)常進行并集、交集操作,這種情況下,bit數(shù)組會比map表現(xiàn)更加理想。

一個bit數(shù)組通常會用一個無符號數(shù)或者稱之為“字”的slice來表示,每一個元素的每一位都表示集合里的一個值。當集合的第i位被設置時,我們才說這個集合包含元素i。

下面的這個程序展示了一個簡單的bit數(shù)組類型,并且實現(xiàn)了三個函數(shù)來對這個bit數(shù)組來進行操作:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package main
import (
    "bytes"
    "fmt"
)
// An IntSet is a set of small non-negative integers.
// Its zero value represents the empty set.
type IntSet struct {
    words []uint
}
const (
    bitNum = (32 << (^uint(0) >> 63)) //根據(jù)平臺自動判斷決定是32還是64
)
// Has reports whether the set contains the non-negative value x.
func (s *IntSet) Has(x int) bool {
    word, bit := x/bitNum, uint(x%bitNum)
    return word < len(s.words) && s.words[word]&(1<<bit) != 0
}
// Add adds the non-negative value x to the set.
func (s *IntSet) Add(x int) {
    word, bit := x/bitNum, uint(x%bitNum)
    for word >= len(s.words) {
        s.words = append(s.words, 0)
    }
    s.words[word] |= 1 << bit
}
//A與B的交集,合并A與B
// UnionWith sets s to the union of s and t.
func (s *IntSet) UnionWith(t *IntSet) {
    for i, tword := range t.words {
        if i < len(s.words) {
            s.words[i] |= tword
        } else {
            s.words = append(s.words, tword)
        }
    }
}

因為每一個字都有64個二進制位,所以為了定位x的bit位,我們用了x/64的商作為字的下標,并且用x%64得到的值作為這個字內(nèi)的bit的所在位置。

例如,對于數(shù)字1,將其加入比特數(shù)組:

?
1
2
3
4
5
6
7
8
func (s *IntSet) Add(x int) {
 word, bit := x/bitNum, uint(x%bitNum) //0, 1 := 1/64, uint(1%64)
 for word >= len(s.words) { // 條件不滿足
  s.words = append(s.words, 0)
 }
 s.words[word] |= 1 << bit // s.words[0] |= 1 << 1
}
// 把1存入后,words數(shù)組變?yōu)榱薣]uint64{2}

同理,假如我們再將66加入比特數(shù)組:

?
1
2
3
4
5
6
7
8
func (s *IntSet) Add(x int) {
 word, bit := x/bitNum, uint(x%bitNum) //1, 2 := 66/64, uint(66%64)
 for word >= len(s.words) { // 條件滿足
  s.words = append(s.words, 0) // 此時s.words = []uint64{2, 0}
 }
 s.words[word] |= 1 << bit // s.words[1] |= 1 << 2
}
// 繼續(xù)把66存入后,words數(shù)組變?yōu)榱薣]uint64{2, 4}

所以,對于words,每個元素可存儲的值有64個,每超過64個則進位,即添加一個元素。(注意,0也占了一位,所以64才要進位,第一個元素可存儲0-63)。

所以,對于words中的一個元素,要轉(zhuǎn)換為具體的值時:首先取到其位置i,用 64 * i 作為已進位數(shù)(類似于每10位要進位), 然后將這個元素轉(zhuǎn)換為二進制數(shù),從右往左數(shù),第多少位為1則表示相應的有這個值,用這個位數(shù) x+64 *i 即為我們存入的值。

相應的,可有如下String()函數(shù)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// String returns the set as a string of the form "{1 2 3}".
func (s *IntSet) String() string {
 var buf bytes.Buffer
 buf.WriteByte('{')
 for i, word := range s.words {
  if word == 0 {
   continue
  }
  for j := 0; j < bitNum; j++ {
   if word&(1<<uint(j)) != 0 {
    if buf.Len() > len("{") {
     buf.WriteByte(' ')
    }
    fmt.Fprintf(&buf, "%d", bitNum*i+j)
   }
  }
 }
 buf.WriteByte('}')
 return buf.String()
}

例如,前面存入了1和66后,轉(zhuǎn)換過程為:

?
1
2
3
4
// []uint64{2 4}
// 對于2: 1 << 1 = 2; 所以 x = 0 * 64 + 1
// 對于4: 1 << 2 = 4; 所以 x = 1 * 64 + 2
// 所以轉(zhuǎn)換為String為{1 66}

實現(xiàn)比特數(shù)組的其他方法函數(shù)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
func (s *IntSet) Len() int {
    var len int
    for _, word := range s.words {
        for j := 0; j < bitNum; j++ {
            if word&(1<<uint(j)) != 0 {
                len++
            }
        }
    }
    return len
}
func (s *IntSet) Remove(x int) {
    word, bit := x/bitNum, uint(x%bitNum)
    if s.Has(x) {
        s.words[word] ^= 1 << bit
    }
}
func (s *IntSet) Clear() {
    s.words = append([]uint{})
}
func (s *IntSet) Copy() *IntSet {
    intSet := &IntSet{
        words: []uint{},
    }
    for _, value := range s.words {
        intSet.words = append(intSet.words, value)
    }
    return intSet
}
func (s *IntSet) AddAll(args ...int) {
    for _, x := range args {
        s.Add(x)
    }
}
//A與B的并集,A與B中均出現(xiàn)
func (s *IntSet) IntersectWith(t *IntSet) {
    for i, tword := range t.words {
        if i >= len(s.words) {
            continue
        }
        s.words[i] &= tword
    }
}
//A與B的差集,元素出現(xiàn)在A未出現(xiàn)在B
func (s *IntSet) DifferenceWith(t *IntSet) {
    t1 := t.Copy() //為了不改變傳參t,拷貝一份
    t1.IntersectWith(s)
    for i, tword := range t1.words {
        if i < len(s.words) {
            s.words[i] ^= tword
        }
    }
}
//A與B的并差集,元素出現(xiàn)在A沒有出現(xiàn)在B,或出現(xiàn)在B沒有出現(xiàn)在A
func (s *IntSet) SymmetricDifference(t *IntSet) {
    for i, tword := range t.words {
        if i < len(s.words) {
            s.words[i] ^= tword
        } else {
            s.words = append(s.words, tword)
        }
    }
}
//獲取比特數(shù)組中的所有元素的slice集合
func (s *IntSet) Elems() []int {
    var elems []int
    for i, word := range s.words {
        for j := 0; j < bitNum; j++ {
            if word&(1<<uint(j)) != 0 {
                elems = append(elems, bitNum*i+j)
            }
        }
    }
    return elems
}

至此,比特數(shù)組的常用方法函數(shù)都已實現(xiàn),現(xiàn)在可以來使用它。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
func main() {
    var x, y IntSet
    x.Add(1)
    x.Add(144)
    x.Add(9)
    fmt.Println("x:", x.String()) // "{1 9 144}"
    y.Add(9)
    y.Add(42)
    fmt.Println("y:", y.String()) // "{9 42}"
    x.UnionWith(&y)
    fmt.Println("x unionWith y:", x.String())         // "{1 9 42 144}"
    fmt.Println("x has 9,123:", x.Has(9), x.Has(123)) // "true false"
    fmt.Println("x len:", x.Len())                    //4
    fmt.Println("y len:", y.Len())                    //2
    x.Remove(42)
    fmt.Println("x after Remove 42:", x.String()) //{1 9 144}
    z := x.Copy()
    fmt.Println("z copy from x:", z.String()) //{1 9 144}
    x.Clear()
    fmt.Println("clear x:", x.String()) //{}
    x.AddAll(1, 2, 9)
    fmt.Println("x addAll 1,2,9:", x.String()) //{1 2 9}
    x.IntersectWith(&y)
    fmt.Println("x intersectWith y:", x.String()) //{9}
    x.AddAll(1, 2)
    fmt.Println("x addAll 1,2:", x.String()) //{1 2 9}
    x.DifferenceWith(&y)
    fmt.Println("x differenceWith y:", x.String()) //{1 2}
    x.AddAll(9, 144)
    fmt.Println("x addAll 9,144:", x.String()) //{1 2 9 144}
    x.SymmetricDifference(&y)
    fmt.Println("x symmetricDifference y:", x.String()) //{1 2 42 144}
    for _, value := range x.Elems() {
        fmt.Print(value, " ") //1 2 42 144
    }
}

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持服務器之家。如有錯誤或未考慮完全的地方,望不吝賜教。

原文鏈接:https://blog.csdn.net/qq_34434641/article/details/80418124

延伸 · 閱讀

精彩推薦
  • Golanggo語言制作端口掃描器

    go語言制作端口掃描器

    本文給大家分享的是使用go語言編寫的TCP端口掃描器,可以選擇IP范圍,掃描的端口,以及多線程,有需要的小伙伴可以參考下。 ...

    腳本之家3642020-04-25
  • GolangGolang中Bit數(shù)組的實現(xiàn)方式

    Golang中Bit數(shù)組的實現(xiàn)方式

    這篇文章主要介紹了Golang中Bit數(shù)組的實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    天易獨尊11682021-06-09
  • Golanggolang的httpserver優(yōu)雅重啟方法詳解

    golang的httpserver優(yōu)雅重啟方法詳解

    這篇文章主要給大家介紹了關于golang的httpserver優(yōu)雅重啟的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,...

    helight2992020-05-14
  • Golanggo日志系統(tǒng)logrus顯示文件和行號的操作

    go日志系統(tǒng)logrus顯示文件和行號的操作

    這篇文章主要介紹了go日志系統(tǒng)logrus顯示文件和行號的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    SmallQinYan12302021-02-02
  • GolangGolang通脈之數(shù)據(jù)類型詳情

    Golang通脈之數(shù)據(jù)類型詳情

    這篇文章主要介紹了Golang通脈之數(shù)據(jù)類型,在編程語言中標識符就是定義的具有某種意義的詞,比如變量名、常量名、函數(shù)名等等,Go語言中標識符允許由...

    4272021-11-24
  • Golanggolang如何使用struct的tag屬性的詳細介紹

    golang如何使用struct的tag屬性的詳細介紹

    這篇文章主要介紹了golang如何使用struct的tag屬性的詳細介紹,從例子說起,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看...

    Go語言中文網(wǎng)11352020-05-21
  • Golanggolang 通過ssh代理連接mysql的操作

    golang 通過ssh代理連接mysql的操作

    這篇文章主要介紹了golang 通過ssh代理連接mysql的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    a165861639710342021-03-08
  • Golanggolang json.Marshal 特殊html字符被轉(zhuǎn)義的解決方法

    golang json.Marshal 特殊html字符被轉(zhuǎn)義的解決方法

    今天小編就為大家分享一篇golang json.Marshal 特殊html字符被轉(zhuǎn)義的解決方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧 ...

    李浩的life12792020-05-27
主站蜘蛛池模板: 男人使劲躁女人小视频 | 国产肥女bbwbbw| 91精品国产免费久久国语蜜臀 | 欧美bbb人妖 | 日本中年japanesebear | 毛片免费视频观看 | 国产目拍亚洲精品一区二区三区 | 国产精品污双胞胎在线观看 | 国产自拍视频一区 | 翁公与小莹在客厅激情 | 国内精品伊人久久大香线焦 | 天天爽天天干天天操 | 日本-区二区三区免费精品 日本破处 | 日韩一区二三区无 | 91看片淫黄大片.在线天堂 | 国产精品视频第一区二区三区 | 久久久久久久电影 | 人人爽人人射 | 国产精品igao视频网网址 | 9420高清视频在线观看网百度 | 娇小8一12xxxx第一次 | 女人狂吮男人命根gif视频 | 色综合天天五月色 | 成人国产在线观看 | 99视频全部看免费观 | 999精品视频在线观看热6 | 日韩国产欧美一区二区三区 | 蛮荒的童话未删减在线观看 | 精品久久久久久久国产潘金莲 | 天堂俺去俺来也www久久婷婷 | 日韩色综合 | 欧美区视频 | 2019nv天堂| 国色天香论坛社区在线视频 | 久久亚洲免费视频 | 欧美人妖草草xxoo | 日韩在线一区二区三区 | 成人1234| 欧美色在线 | 瘦老汉gay | 亚洲经典 |