Go資料結構之集合

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

一、什麼是集合

集合就是不同對象的無序聚集。那麼鏈表和集合有什麼關係呢?我們來變個魔術。如是各種顏色組成的鏈表:

下面我們一步步把鏈表變成集合。
第一步砍去連結

第二步去掉重複

第三步放到一個框裡搖一搖就成集合了

可以看出集合有這些特點:

  • 無序:鏈表去掉連結,就是去掉元素間有序狀態。
  • 不重複:去掉重複的玫紅色。

雖然說集合是一種數學概念,但在實際生活中無處不透露著集合。比如一個班級的學生是一個集合。班級裡的男生又是一個集合。

二、集合的結構

大衛哥這裡為了簡化概念的描述,繼續用單鏈表來表示集合,但是在對集合做計算的時候單鏈表並不合適,資料量大的時候它的弊端就會顯現,在講到後面的資料結構和演算法的時候,我們再回頭來完善前面講的資料介面的實現。

三、介面說明及實現

2、Init
初始化集合,本質是初始化鏈表。

func (set *Set) Init(match ...MatchFun) {    lst := new(List)    (*set).list = lst    if len(match) == 0 {        lst.Init()    } else {        lst.Init(match[0])    }}

要比較集合中的元素,我們得傳入一個比較函數,這裡的match是我們的自訂類型MatchFun,大家可以查看代碼裡的定義。
2、Insert
把元素放入集合中。

func (set *Set) Insert(data Object) bool {    if (!set.IsMember(data)) {        return (*set).list.Append(data)    }    return false}

3、IsEmpty
是否是空集合。

func (set *Set) IsMember(data Object) bool {    return (*set).list.IsMember(data);}

4、IsMember
是否是集合元素。

func (set *Set) IsMember(data Object) bool {    return (*set).list.IsMember(data);}

5、Remove
刪除指定集合元素。

func (set *Set) Remove(data Object) bool {    return (*set).list.Remove(data)}

6、Union
並集計算。

func (set *Set) Union(set1 *Set) *Set {    if (set1 == nil) {        return nil    }    nSet := new(Set)    nSet.Init((*((*set).list)).myMatch)    if (set.IsEmpty() && set1.IsEmpty()) {         return nSet    }    for i := uint64(0); i < set.getSize(); i++ {        nSet.Insert(set.getAt(i))    }    var data Object    for i := uint64(0); i < set1.getSize(); i++ {        data = set1.getAt(i)        if (!nSet.IsMember(data)) {            nSet.Insert(data)        }    }    return nSet}

計算set和set1的並集。
7、InterSection
計算交集。

func (set *Set) InterSection(set1 *Set) *Set {    if (set1 == nil) {        return nil    }    nSet := new(Set)    nSet.Init((*((*set).list)).myMatch)    if (set.IsEmpty() || set1.IsEmpty()) {        return nSet    }    fSet := set    sSet := set1    lenth := set.getSize()    if (set1.getSize() < lenth) {        fSet = set1        sSet = set    }    var data Object    for i := uint64(0) ; i < lenth; i++ {        data = fSet.getAt(i)        if (sSet.IsMember(data)) {            nSet.Insert(data)        }    }    return nSet}

8、Difference
計算差集。

func (set *Set) Difference(set1 *Set) *Set {    if (set1 == nil) {        return nil    }    nSet := new(Set)    nSet.Init((*((*set).list)).myMatch)    if (set.IsEmpty()) {        return nSet    }    var data Object    for i := uint64(0); i < set.getSize(); i++ {        data = set.getAt(i)        if (!set1.IsMember(data)) {            nSet.Insert(data)        }    }    return nSet}

返回的集合是屬於set,但不屬於set1的集合。
9、IsSubSet

func (set *Set) IsSubSet(subSet *Set) bool {    if (set == nil) {        return false    }    if (subSet == nil) {        return true    }    for i := uint64(0); i < subSet.getSize(); i++ {        if (!(set.IsMember(subSet.getAt(i)))) {            return false        }    }    return true}

確認subSet是否是set的子集。
10、Equals

func (set *Set) Equals(set1 *Set) bool {    if (set == nil || set1 == nil) {        return false    }    if (set.IsEmpty() && set1.IsEmpty()) {        return true    }    nSet := set.InterSection(set1)    return (set.getSize() == nSet.getSize())}

判斷set和set1中集合元素是否一樣。

11、訪問集合元素
因為集合是沒有順序的,所以沒法用序號來訪問集合元素(雖然這裡是用單鏈表實現)。這裡我們用迭代器的方式來實現元素的訪問。首先我們定義一個迭代器的介面。
(1) Iterator

type Iterator interface{    HasNext() bool    Next() Object}

(2) SetIterator

type SetIterator struct {    index uint64    set *Set}

因為Iterator是介面,沒法儲存狀態,所以我們得定義一個類型來儲存每次訪問的遊標。這裡的遊標是序號。
(3) GetIterator
返回一個實現了Iterator介面的對象。

func (set *Set) GetIterator() *SetIterator {    iterator := new(SetIterator)    (*iterator).index = 0    (*iterator).set = set    return iterator}

(4) HasNext
是否有其他元素沒訪問到?

func (iterator *SetIterator) HasNext() bool {    set := (*iterator).set    index := (*iterator).index    return (index < set.getSize())}

這是Iterator中HasNext方法的實現。
(5) Next
擷取其他元素。

func (iterator *SetIterator) Next() Object {    set := (*iterator).set    index := (*iterator).index    if (index < set.getSize()) {        data := set.getAt(index)        (*iterator).index++        return data        }    return nil}

四、小結
集合在機率中有很多應用,這裡我們僅僅是用單鏈表簡單的實現了集合,在大量資料下,計算效率很低。隨著學習的深入,我們會最佳化這些資料介面的實現。
代碼下載

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.