Tập hợp Số Nguyên Không Âm Sử Dụng Mảng Bit [Go]

Một tập hợp số nguyên không âm được xây dựng bằng mảng bit với các phương thức sau: - `func (s *NumSet) Contains(val int) bool`: Kiểm tra sự tồn tại của phần tử. - `func (s *NumSet) Insert(val int)`: Thêm phần tử vào tập hợp. - `func (s *NumSet) Size() int`: Trả về kích thước của tập hợp. - `func (s *NumSet) Delete(val int)`: Xóa phần tử khỏi tập hợp. - `func (s *NumSet) Reset()`: Xóa tất cả các phần tử trong tập hợp. - `func (s *NumSet) Clone() *NumSet`: Tạo bản sao của tập hợp. - `func (s *NumSet) Union(other *NumSet)`: Thực hiện phép hợp. - `func (s *NumSet) Intersection(other *NumSet)`: Thực hiện phép giao. - `func (s *NumSet) Difference(other *NumSet)`: Thực hiện phép hiệu. - `func (s *NumSet) SymmetricDifference(other *NumSet)`: Thực hiện phép hiệu đối xứng. Mã nguồn `numset.go`:

package numset

import (
	"bytes"
	"fmt"
	"log"
)

var popCount [256]byte

func init() {
	for i := range popCount {
		popCount[i] = popCount[i>>1] + byte(i&1)
	}
}

type NumSet struct {
	bits []uint64
}

func (s *NumSet) Contains(val int) bool {
	index := val / 64
	bit := val % 64
	return index < len(s.bits) && s.bits[index]&(1<= len(s.bits) {
		s.bits = append(s.bits, 0)
	}
	s.bits[index] |= 1 << bit
}

func (s *NumSet) Union(other *NumSet) {
	for i, otherBit := range other.bits {
		if i < len(s.bits) {
			s.bits[i] |= otherBit
		} else {
			s.bits = append(s.bits, otherBit)
		}
	}
}

func (s *NumSet) Intersection(other *NumSet) {
	minLen := len(s.bits)
	if len(other.bits) < minLen {
		minLen = len(other.bits)
	}
	for i := 0; i < minLen; i++ {
		s.bits[i] &= other.bits[i]
	}
	for i := minLen; i < len(s.bits); i++ {
		s.bits[i] = 0
	}
}

func (s *NumSet) Difference(other *NumSet) {
	for i, otherBit := range other.bits {
		if i < len(s.bits) {
			s.bits[i] &^= otherBit
		}
	}
}

func (s *NumSet) SymmetricDifference(other *NumSet) {
	temp := other.Clone()
	temp.Difference(s)
	s.Difference(other)
	s.Union(temp)
}

func countOnes(x uint64) int {
	return int(popCount[byte(x>>(0*8))] +
		popCount[byte(x>>(1*8))] +
		popCount[byte(x>>(2*8))] +
		popCount[byte(x>>(3*8))] +
		popCount[byte(x>>(4*8))] +
		popCount[byte(x>>(5*8))] +
		popCount[byte(x>>(6*8))] +
		popCount[byte(x>>(7*8))])
}

func (s *NumSet) Size() int {
	count := 0
	for _, bit := range s.bits {
		if bit == 0 {
			continue
		}
		count += countOnes(bit)
	}
	return count
}

func (s *NumSet) Delete(val int) {
	index, bit := val/64, uint(val%64)
	if index >= len(s.bits) {
		log.Printf("Phần tử không tồn tại: %d\n", val)
		return
	}
	s.bits[index] &^= 1 << bit
}

func (s *NumSet) Reset() {
	s.bits = []uint64{}
}

func (s *NumSet) Clone() *NumSet {
	clone := &NumSet{}
	clone.bits = make([]uint64, len(s.bits))
	copy(clone.bits, s.bits)
	return clone
}

func (s *NumSet) String() string {
	var buffer bytes.Buffer
	buffer.WriteByte('{')
	for i, bit := range s.bits {
		if bit == 0 {
			continue
		}
		for j := 0; j < 64; j++ {
			if bit&(1< 1 {
					buffer.WriteByte(' ')
				}
				fmt.Fprintf(&buffer, "%d", 64*i+j)
			}
		}
	}
	buffer.WriteByte('}')
	return buffer.String()
}
Mã nguồn kiểm thử `numset_test.go`:

package numset

import (
	"fmt"
	"testing"
)

func TestNumSet(t *testing.T) {
	var set1, set2 NumSet
	set1.Insert(1)
	set1.Insert(144)
	set1.Insert(9)
	fmt.Println(set1.String()) // "{1 9 144}"
	set2.Insert(9)
	set2.Insert(42)
	fmt.Println(set2.String()) // "{9 42}"
	set1.Union(&set2)
	fmt.Println(set1.String()) // "{1 9 42 144}"
	fmt.Println(set1.Contains(9), set1.Contains(123)) // "true false"
}

var testSet NumSet

func TestNumSet2(t *testing.T) {
	testSet.Insert(1)
	testSet.Insert(144)
	testSet.Insert(9)
	fmt.Println(testSet.Size())
	fmt.Println(testSet.String())
	testSet.Delete(10)
	fmt.Println(testSet.String())
	copySet := testSet.Clone()
	fmt.Println("testSet.Clone()", copySet.String())
	fmt.Println("testSet", testSet.String())
	testSet.Reset()
	fmt.Println("testSet.Reset()", testSet.String())
}

Thẻ: Go bit-array set-operations integer-set

Đăng vào ngày 7 tháng 7 lúc 09:19