algorithm-位向量

在這裏插入圖片描述
【實現位向量】

//問題描述:
//有一組非負整數,實現一個位向量類型,能在O(1)時間內完成插入、刪除和查找等操作。
//要點:
//實現Has(uint)、Add(uint)、Remove(uint)、Clear()、Copy()、String()、AddAll(…uint)、UnionWith()、IntersectWith()、DifferenceWith()、SymmetricDifference()方法。
//拓展:
//使用uint存儲而不是uint32或uint64這樣限定字長的類型。

//代碼實現:
package main

import (
	"bytes"
	"fmt"
)

func (s *IntSet) countBit(n uint) int {
	count := 0
	for n != 0 {
		n = n & (n - 1)
		count += 1
	}
	return count
}
func (s *IntSet) calWordBit(x int) (word int, bit uint) {
	word, bit = x/wordSize, uint(x%wordSize)
	return
}

//判斷操作系統位數 https://www.jianshu.com/p/14a9750e5adf
//首先 uint 類型 不是一個固定長度的類型
//所以對無符號的 uint(0) 取反將得到最大值
//^uint(0) 在 32位系統 上返回的是 0xFFFFFFFF,也就是 232
//^uint(0) 在 64位系統 上返回的是 0xFFFFFFFFFFFFFFFF,也就是 264
//然後 左移(<<) 和 右移(>>) 運算順序都是從左到右的,^爲位反
const wordSize = 32 << (^uint(0) >> 63)

func main(){
	a := IntSet{}
	a.Add(4)
	a.Add(5)
	a.Add(66)
	a.Add(96)
	fmt.Println(a.Has(6))
}
// An IntSet is a set of small non-negative integers.
// Its zero value represents the empty set.
type IntSet struct {
	words []uint
}

// Has reports whether the set contains the non-negative value x.
func (s *IntSet) Has(x int) bool {
	word, bit := s.calWordBit(x)
	fmt.Println(word,bit,s.words[word],1<<bit)
	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 := s.calWordBit(x)
	fmt.Println("111",word,bit)
	for word >= len(s.words) {
		s.words = append(s.words, 0)
		fmt.Println("222",s.words)
	}
	fmt.Println("333",1 << bit)
	s.words[word] |= 1 << bit
	fmt.Println("444",s.words)
}
func (s *IntSet) AddAll(nums ...int) {
	for _, n := range nums {
		s.Add(n)
	}
}

// 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)
		}
	}
}

// Set s to the intersection of s and t.
func (s *IntSet) IntersectWith(t *IntSet) {
	for i, tword := range t.words {
		if i < len(s.words) {
			s.words[i] &= tword
		} else {
			s.words = append(s.words, tword)
		}
	}
}

// Set s to the difference of s and t.
func (s *IntSet) DifferenceWith(t *IntSet) {
	for i, tword := range t.words {
		if i < len(s.words) {
			s.words[i] &^= tword
		} else {
			s.words = append(s.words, tword)
		}
	}
}

// Set s to the symmetric對稱的 difference of s and t.
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)
		}
	}
}

// return the number of elements
func (s *IntSet) Len() int {
	count := 0
	for _, word := range s.words {
		count += s.countBit(word)
	}
	return count
}

// remove x from the set
func (s *IntSet) Remove(x int) {
	word, bit := s.calWordBit(x)
	s.words[word] &^= 1 << bit
}

// remove all elements from the set
func (s *IntSet) Clear() {
	for i := range s.words {
		s.words[i] = 0
	}
}

// return a copy of the set
func (s *IntSet) Copy() *IntSet {
	new := &IntSet{}
	new.words = make([]uint, len(s.words))
	copy(new.words, s.words)
	return new
}

// 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 < wordSize; j++ {
			if word&(1<<uint(j)) != 0 {
				if buf.Len() > len("{") {
					buf.WriteByte(' ')
				}
				fmt.Fprintf(&buf, "%d", wordSize*i+j)
			}
		}
	}
	buf.WriteByte('}')
	return buf.String()
}

// Return set elements.
func (s *IntSet) Elems() []int {
	e := make([]int, 0)
	for i, word := range s.words {
		for j := 0; j < wordSize; j++ {
			if word&(1<<uint(j)) != 0 {
				e = append(e, i*wordSize+j)
			}
		}
	}
	return e
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章