自己用C++实现的Bitset类, 功能参考STL的bitset类, 由于VS2005不支持模板的分离编译, 所以都实现在了一个名为Bitset.h的头文件里. 肯定有一些bug, 请各位高手帮忙抓虫. 抛砖引玉, 博大家一晒.
1: #ifndef BIT_SET_H
2: #define BIT_SET_H
3: //Readme
4: //本程序实现了一个类似std::bitset的类, 经过了一些测试,
5: //但还没有全面测试
6:
7: #include <iosfwd> //前导定义
8: #include <string>
9: #include <cstdlib>
10: #include <string>
11: #include <algorithm>
12: #ifdef EXCEPTION_HANDLE
13: #include "exception.h"
14: #endif
15: using std::string;
16: using std::ostream;
17:
18: //Utility macros
19: #define CHAR_BITS 8
20: #define WORD_LEN (sizeof(unsigned int) * CHAR_BITS )
21: #define BITSET_WORD_CNT(n) ((n + WORD_LEN -1) / WORD_LEN) //辅助宏
22:
23: typedef unsigned int WORD;
24:
25: namespace imgen
26: {
27: template<size_t sz>
28: class bitset
29: {
30: class bit //辅助类,将比特位抽象为一个类,为bitset类服务
31: {
32: private:
33: bitset<sz>& bs;
34: size_t pos;
35:
36: public:
37: bit(bitset& bs, size_t pos):bs(bs),pos(pos){}
38:
39: //提供一系列操作
40: void flip()
41: {
42: bs.flip(pos);
43: }
44:
45: void set()
46: {
47: bs.set(pos);
48: }
49:
50: void reset()
51: {
52: bs.reset(pos);
53: }
54:
55: bool test()const
56: {
57: return bs.test(pos);
58: }
59:
60: //bool类型转换操作符
61: operator bool()const
62: {
63: return test();
64: }
65:
66: //赋值操作符
67: bit& operator = (int n)
68: {
69: if(n != 0)
70: bs.set(pos);
71: else
72: bs.reset(pos);
73: return *this;
74: }
75:
76: //赋值操作符
77: bit& operator = (const bit&rhs)
78: {
79: if(rhs.test())
80: bs.set(pos);
81: else
82: bs.reset(pos);
83: return *this;
84: }
85:
86: //赋值操作符
87: bit& operator = (bool b)
88: {
89: if(b)
90: bs.set(pos);
91: else
92: bs.reset(pos);
93:
94: return *this;
95: }
96:
97: bool operator !()
98: {
99: return !test();
100: }
101: };
102:
103:
104: private:
105: //用于存储比特位的数组
106: WORD *start, *end;
107: //字的数目
108: size_t szWord;
109:
110: //utility function
111: //设置refWord的第pos位为1
112: inline void pvSet(WORD& refWord, size_t pos)
113: {
114: WORD tmp = 0x80000000 >> pos;
115: refWord |= tmp;
116: }
117:
118: //设置refWord的第pos位为0
119: inline void pvReset(WORD& refWord , size_t pos)
120: {
121: WORD tmp = ~(0x80000000 >> pos);
122: refWord &= tmp;
123: }
124:
125: //统计refWord中1的个数
126: size_t count_bit_1(const WORD& refWord)const
127: {
128: WORD tmp = refWord ;
129: size_t cnt = 0;
130: while(tmp > 0)
131: {
132: tmp &= tmp-1;
133: ++cnt;
134: }
135:
136: return cnt;
137: }
138:
139: //侦测pWord数组中有无被置为1的位
140: bool testArrayAny(const WORD*pWord, size_t arraySize, size_t bitcount)const
141: {
142: for(const WORD* pw = pWord; pw < pWord + arraySize; ++pw)
143: {
144: if (*(pw))
145: return true;
146: }
147:
148: return false;
149: }
150:
151: //字符串转为字
152: void string_to_words(const string&str)
153: {
154: size_t len = str.length(), i;
155: WORD *pw = start;
156:
157: for(i = 0; i + WORD_LEN < len; i += WORD_LEN, ++pw)
158: {
159: string subStr = str.substr(i , WORD_LEN);
160: *pw = 0;
161: for(int j = 0; j < WORD_LEN; ++j)
162: {
163: if(subStr[j] == '1')
164: {
165: *pw |= 0x80000000 >> j;
166: }
167: }
168: }
169:
170: string left = str.substr(i, len - i);
171: for(int j = 0; j + i < len; ++j)
172: {
173: if(left[j] == '1')
174: {
175: *pw |= 0x80000000 >> j;
176: }
177: }
178: }
179:
180: //把字转为字符串
181: string bitset::word_to_string(const WORD& refWord )const
182: {
183: /*
184: static char*table[] = {"0000", "0001", "0010", "0011",
185: "0100", "0101", "0110", "0111",
186: "1000", "1001", "1010", "1011",
187: "1100", "1101", "1110", "1111"};
188: string str;
189: WORD tmp1, tmp2;
190:
191: for(size_t i = 0; i < WORD_LEN / 4; ++i)
192: {
193: tmp2 = (0xF0000000>>(4*i));
194: tmp1 = refWord & tmp2;
195: tmp1 >>= (WORD_LEN - 4 - 4*i);
196: str += table[tmp1];
197: }
198:
199: return str;
200: */
201: /*the below method is simpler, but its performance is not explicitly better or worse than
202: the above method*/
203: string str("00000000000000000000000000000000");
204: for(int i = 0; i < WORD_LEN ; ++i)
205: {
206: WORD tmp = 1 << i;
207: str[i] = (refWord & tmp)? '1':'0';
208: }
209:
210: return str;
211: }
212:
213: //反转src
214: WORD reverse_word(const WORD&src)const
215: {
216: WORD result = 0;
217: for(int i = 0; i < WORD_LEN; ++i)
218: {
219: if((1<<i) & src)
220: {
221: result |= 0x80000000 >> i;
222: }
223: }
224:
225: return result;
226: }
227:
228: //创建一个bitset
229: void create()
230: {
231: szWord = BITSET_WORD_CNT(sz);
232: start = new WORD[szWord];
233: end = start + szWord;
234:
235: reset();
236: }
237:
238: //clear the redundant bits of the last word
239: void clear()
240: {
241: size_t left = sz - WORD_LEN * (szWord-1);
242: WORD tmp = ~(0xFFFFFFFF >> left);
243: *(end-1) &= tmp;
244: }
245:
246: public:
247: //Type defines
248: typedef bitset& reference;
249: typedef const bitset& const_reference;
250:
251: //默认构造函数
252: bitset()
253: {
254: create();
255: }
256:
257: //用整数构造
258: bitset(unsigned long n)
259: {
260: create();
261: *start = reverse_word(n);
262: //clear the redundant bits of the last word
263: clear();
264: }
265:
266: //用字符串构造
267: bitset(string binarySeq)
268: {
269: if(binarySeq.empty())
270: {
271: create();
272: return;
273: }
274:
275: if(binarySeq.length() >= sz)
276: {
277: binarySeq = binarySeq.substr(0, sz);
278: }
279:
280: //翻转二进制序列
281: reverse(binarySeq.begin(), binarySeq.end());
282:
283: create();
284:
285: string_to_words(binarySeq);
286: }
287:
288: //复制构造函数
289: bitset(const bitset<sz>& rhs)
290: {
291: create();
292: for(WORD* pw = start, *pwRhs = rhs.start; pw < end; ++pw, ++pwRhs)
293: {
294: *pw = *pwRhs;
295: }
296: }
297:
298: //赋值操作符
299: bitset<sz>& operator = (const bitset<sz>&rhs)
300: {
301: for(WORD* pw = start, *pwRhs = rhs.start; pw < end; ++pw, ++pwRhs)
302: {
303: *pw = *pwRhs;
304: }
305:
306: return *this;
307: }
308:
309: //析构函数
310: ~bitset()
311: {
312: delete []start;
313: start = 0;
314: }
315:
316: //重置所有位为1
317: inline void set()
318: {
319: memset(start, -1, sizeof(WORD)*szWord);
320: clear();
321: }
322:
323: //重置pos位为1
324: void set(size_t pos)
325: {
326: #ifdef EXCEPTION_HANDLE
327: if(pos >= sz)
328: throw data_error();
329: #endif
330:
331: if(!test(pos))
332: {
333: size_t wordpos = pos / WORD_LEN;
334: size_t ofstInWord = pos % WORD_LEN;
335:
336: pvSet(*(start + wordpos ), ofstInWord );
337: }
338: }
339:
340: //重置所有位为0
341: inline void reset()
342: {
343: memset(start , 0 , sizeof(WORD)*szWord);
344: }
345:
346: //重置pos位为0
347: void reset(size_t pos)
348: {
349: #ifdef EXCEPTION_HANDLE
350: if(pos >= sz)
351: throw data_error();
352: #endif
353: if(test(pos))
354: {
355: size_t wordpos = pos / WORD_LEN;
356: size_t ofstInWord = pos % WORD_LEN;
357: pvReset(*(start + wordpos ), ofstInWord );
358: }
359: }
360:
361: //翻转所有位
362: void flip()
363: {
364: for(WORD*pw = start; pw < end; ++pw)
365: *(pw) = ~(*(pw));
366: }
367:
368: //翻转pos位
369: void flip(size_t pos)
370: {
371: #ifdef EXCEPTION_HANDLE
372: if(pos >= sz)
373: throw data_error();
374: #endif
375:
376: size_t wordpos = pos / WORD_LEN;
377: size_t ofstInWord = pos % WORD_LEN;
378: WORD tmp = ~(*(start + wordpos));
379: pvSet (tmp, ofstInWord );
380:
381: *(start + wordpos) ^= tmp;
382: }
383:
384: //测试pos位
385: bool test(size_t pos)const
386: {
387: #ifdef EXCEPTION_HANDLE
388: if(pos >= sz)
389: throw data_error();
390: #endif
391:
392: size_t wordpos = pos / WORD_LEN;
393: size_t ofstInWord = pos % WORD_LEN;
394: WORD tmp = 0x80000000 >> ofstInWord ;
395:
396: if((*start + wordpos) & tmp)
397: return true;
398: return false;
399: }
400:
401: //测试有没有被置为1的位
402: bool any()const
403: {
404: return testArrayAny(start, szWord, sz);
405: }
406:
407: //测试是否全为0
408: bool none()const
409: {
410: return !any();
411: }
412:
413: //返回1的个数
414: size_t count()
415: {
416: size_t bitCnt = 0;
417: for (WORD*pw = start; pw < end; ++pw)
418: {
419: bitCnt += count_bit_1(*pw);
420: }
421:
422: return bitCnt ;
423: }
424:
425: //转为字符串表示
426: string to_string()const
427: {
428: string str;
429: size_t lastwordleft = (sz + WORD_LEN - 1) % WORD_LEN + 1;
430:
431: for (WORD* pw = end; pw > start;--pw)
432: {
433: str += word_to_string(*(pw-1));
434: }
435:
436: str = str.substr(WORD_LEN - lastwordleft, str.length() - (WORD_LEN - lastwordleft));
437:
438: return str;
439: }
440:
441: //转为unsigned long
442: unsigned long to_ulong()const
443: {
444: #ifdef EXCEPTION_HANDLE
445: if(testArrayAny(start+1, szWord-1, sz - WORD_LEN))
446: throw data_error("This bitset cannot convert to unsigned long type value");
447: #endif
448: return static_cast<unsigned long>( reverse_word(start[0]) );
449: }
450:
451: //bitset大小
452: inline size_t size()const
453: {
454: return sz;
455: }
456:
457: //Operators
458:
459: bit operator [](size_t pos)const
460: {
461: #ifdef EXCEPTION_HANDLE
462: if(pos >= sz)
463: throw data_error();
464: #endif
465:
466: bit dummy(*this, pos);
467: return dummy;
468: }
469:
470: bit operator [](size_t pos)
471: {
472: #ifdef EXCEPTION_HANDLE
473: if(pos >= sz)
474: throw data_error();
475: #endif
476:
477: bit dummy(*this, pos);
478: return dummy;
479: }
480:
481: //logic operators
482: bool operator == (const bitset<sz>& rhs)const
483: {
484: #ifdef EXCEPTION_HANDLE
485: if(size() != rhs.size())
486: return false;
487: #endif
488:
489: for(WORD *pw = start, *pwRhs = rhs.start; pw < end; ++pw, ++pwRhs)
490: {
491: if(*pw != *pwRhs)
492: return false;
493: }
494:
495: return true;
496: }
497:
498: bool operator != (const bitset<sz>& rhs)const
499: {
500: return !(*this == rhs);
501: }
502:
503: bool operator < (const bitset<sz>& rhs)const
504: {
505: return to_string() < rhs.to_string();
506: }
507:
508: bool operator <= (const bitset<sz>& rhs)const
509: {
510: return (*this < rhs) || (*this == rhs);
511: }
512:
513: bool operator > (const bitset<sz>& rhs)const
514: {
515: return !(*this <= rhs);
516: }
517:
518: bool operator >=(const bitset<sz>& rhs)const
519: {
520: return !(*this < rhs);
521: }
522:
523: //bit operators
524: bitset<sz> operator &(const bitset<sz>& rhs)const
525: {
526: bitset<sz> retbt;
527: for(WORD *pw = start, *pwRhs = rhs.start, *pwRet = retbt.start; pw < end; ++pw, ++pwRhs, ++pwRet)
528: {
529: *pwRet = (*pw) & (*pwRhs);
530: }
531: return retbt;
532: }
533:
534: bitset<sz>& operator &=(const bitset<sz>& rhs)
535: {
536: for(WORD *pw = start, *pwRhs = rhs.start; pw < end; ++pw, ++pwRhs)
537: {
538: *pw &= *pwRhs;
539: }
540: }
541:
542: bitset<sz> operator |(const bitset<sz>& rhs)const
543: {
544: bitset<sz> retbt;
545: for(WORD *pw = start, *pwRhs = rhs.start, *pwRet = retbt.start; pw < end; ++pw, ++pwRhs, ++pwRet)
546: {
547: *pwRet = (*pw) | (*pwRhs);
548: }
549: return retbt;
550: }
551:
552: bitset<sz>& operator |=(const bitset<sz>& rhs)
553: {
554: for(WORD *pw = start, *pwRhs = rhs.start; pw < end; ++pw, ++pwRhs)
555: {
556: *pw |= *pwRhs;
557: }
558:
559: return *this;
560: }
561:
562: bitset<sz> operator ^(const bitset<sz>& rhs)const
563: {
564: bitset<sz> retbt;
565: for(WORD *pw = start, *pwRhs = rhs.start, *pwRet = retbt.start; pw < end; ++pw, ++pwRhs, ++pwRet)
566: {
567: *pwRet = (*pw) ^ (*pwRhs);
568: }
569:
570: return retbt;
571: }
572:
573: bitset<sz>& operator ^=(const bitset<sz>& rhs)
574: {
575: for(WORD *pw = start, *pwRhs = rhs.start; pw < end; ++pw, ++pwRhs)
576: {
577: *pw ^= *pwRhs;
578: }
579:
580: return *this;
581: }
582:
583: bitset<sz> operator ~()const
584: {
585: bitset<sz> retbt;
586:
587: for(WORD* pw = start, *pwRet = retbt.start; pw < end; ++pw, ++pwRet)
588: {
589: *pwRet = ~(*pw);
590: }
591:
592: retbt.clear();
593:
594: return retbt;
595: }
596:
597: bitset<sz> operator >>(size_t offset)
598: {
599: size_t size = sz;
600: bitset<sz> retbt;
601:
602: if(offset >= sz)
603: {
604: return retbt;
605: }
606:
607: size_t firstOffset, secondOffset, firstShift, secondShift;;
608: firstOffset = offset / WORD_LEN;
609: secondOffset = (offset + WORD_LEN - 1) / WORD_LEN;
610: firstShift = offset % WORD_LEN;
611: secondShift = WORD_LEN - firstShift;
612:
613: WORD *first, *second, *pwRet;
614: first = start + firstOffset;
615: second = start + secondOffset;
616: pwRet = retbt.start;
617:
618: while (first < end)
619: {
620: WORD tmp1 = *first++ << firstShift,
621: tmp2 = second < end ?(*second++ >> secondShift) : 0;
622: *pwRet++ = tmp1 | tmp2;
623: }
624:
625: return retbt;
626: }
627:
628: bitset<sz>& operator >>=(size_t offset)
629: {
630: size_t size = sz;
631:
632: //See if beyond the limit
633: if(offset >= size)
634: {
635: this->reset();
636: return *this;
637: }
638:
639: size_t firstOffset, secondOffset, firstShift, secondShift;;
640: firstOffset = offset / WORD_LEN;
641: secondOffset = (offset + WORD_LEN - 1) / WORD_LEN;
642: firstShift = offset % WORD_LEN;
643: secondShift = WORD_LEN - firstShift;
644:
645: WORD *first, *second, *pw;
646: first = start + firstOffset;
647: second = start + secondOffset;
648: pw = start;
649: while (first < end)
650: {
651: WORD tmp1 = (*first++ << firstShift),
652: tmp2 = second < end ?(*second++ >> secondShift) : 0;
653: *pw++ = tmp1 | tmp2;
654: }
655:
656: while(pw < end)
657: {
658: *pw++ = 0;
659: }
660:
661: return *this;
662: }
663:
664: //这段代码的算法相对复杂,故而略去注释
665: bitset<sz> operator <<(size_t offset)
666: {
667: size_t size = sz;
668: bitset<sz> retbt;
669:
670: if(offset >= size)
671: {
672: return retbt;
673: }
674:
675: size_t firstOffset, secondOffset, firstShift, secondShift;;
676: firstOffset = offset / WORD_LEN;
677: secondOffset = (offset + WORD_LEN - 1) / WORD_LEN;
678: firstShift = offset % WORD_LEN;
679: secondShift = WORD_LEN - firstShift;
680:
681: WORD *first, *second, *pwRet;
682: first = end - firstOffset;
683: second = end - secondOffset;
684: pwRet = retbt.end;
685:
686: while(first > start)
687: {
688: WORD tmp1 = *(first-- - 1) >> firstShift,
689: tmp2 = second > start? (*(second-- - 1) << secondShift) : 0;
690: *(pwRet-- - 1) = tmp1 | tmp2;
691: }
692:
693: return retbt;
694: }
695:
696: bitset<sz>& operator <<=(size_t offset)
697: {
698: size_t size = sz;
699:
700: if(offset >= size)
701: {
702: this->reset();
703: return *this;
704: }
705:
706: //Move right, because the order is opposite
707: size_t firstOffset, secondOffset, firstShift, secondShift;;
708: firstOffset = offset / WORD_LEN;
709: secondOffset = (offset + WORD_LEN - 1) / WORD_LEN;
710: firstShift = offset % WORD_LEN;
711: secondShift = WORD_LEN - firstShift;
712:
713: WORD *first, *second, *pw;
714: first = end - firstOffset;
715: second = end - secondOffset;
716: pw = end;
717:
718: while(first > start)
719: {
720: WORD tmp1 = *(first-- - 1) >> firstShift,
721: tmp2 = second > start? (*(second-- - 1) << secondShift) : 0;
722: *(pw-- - 1) = tmp1 | tmp2;
723: }
724:
725: while(pw > start)
726: {
727: *(pw-- - 1) = 0;
728: }
729:
730: return *this;
731: }
732:
733:
734: };
735:
736:
737: //输出操作符重载
738: template<int sz>
739: ostream& operator <<(ostream&os, bitset<sz>bs)
740: {
741: return os<<bs.to_string();
742: }
743: }
744:
745: #endif