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
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值