自己实现的Bitset类

来源:互联网 发布:java file类路径 编辑:程序博客网 时间:2024/06/08 19:08

自己用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