本文問題取自<<編程珠璣>>.ios
須要給一個磁盤文件排序編程
該文件最多包含n個正整數,每一個數都小於n且n = 10^7,而且該文件中不會有重複數據spa
按照升序排序code
磁盤空間充足,但內存只有1Morm
由於內存很小,因此最樸素的方式爲多趟排序,每次讀入一部分到內存進行排序。但分析後會發現最大的特色是沒有重複數據,若是使用1個bit位表明一個數據則1M最多可標記1024*1024*8的數字。所以用位圖排序在時間和空間上都很高效。排序
/** * @brief file for 編程珠璣 chapter 1 * @note 讀取文件使用位圖排序 */ #include <fstream> #include <iostream> #include <cstdio> #include <cstdlib> //#define DEBUG #define DBG(format, args...) \ do { \ printf("[ file: %-20s ,fun: %-20s , line: %-10d ] :"format, __FILE__, __func__, __LINE__, ##args); \ } while (0) namespace fileSort{ class bmpSort{ public: bmpSort(const unsigned int &valMax){ bmpAlloc(valMax); } void bmpSet(const unsigned int val){ if(val >= blen) return; bmp[val >> 5] |= 1 << (0x1f & val); } ~bmpSort(void) { bmpDestory(); } friend std::ifstream& operator >> (std::ifstream&, bmpSort&); friend std::ofstream& operator << (std::ofstream&, bmpSort&); private: void bmpAlloc(const unsigned int &len){ unsigned int tlen = len < 0? 0 : len; arrayPosMax = (tlen >> 5) + (tlen & 0x1f ? 1 : 0); bitPosMax = 33; bmp = new unsigned int[arrayPosMax]; blen = len; } void bmpDestory(void){ if(bmp) delete bmp; } void initSearch(void){ arrayPos = 0; bitPos = 0; } int nextVal(unsigned int &val){ if(bitPos >= bitPosMax){ arrayPos++; bitPos = 0; } if(arrayPos >= arrayPosMax) return -1; if(0 == bmp[arrayPos]) bitPos = 0; while(0 == bmp[arrayPos] && arrayPos < arrayPosMax) arrayPos++; if(arrayPos >= arrayPosMax) return -1; while( 0 == (bmp[arrayPos] & (1 << bitPos)) ){ bitPos++; } if( bitPos >= bitPosMax) return -1; val = (arrayPos << 5) + bitPos; bmp[arrayPos] &= ~(1 << bitPos); bitPos++; return 0; } int arrayPos; int arrayPosMax; int bitPos; int bitPosMax; unsigned int * bmp; unsigned int blen; }; std::ifstream& operator >> (std::ifstream& in, bmpSort& bs){ int val; while(in >> val){ #ifdef DEBUG DBG("read %d\n", val); #endif bs.bmpSet(val); } return in; } std::ofstream& operator << (std::ofstream& out, bmpSort& bs){ unsigned int val; bs.initSearch(); while( 0 == bs.nextVal(val)){ out << val << "\n"; if(out.fail()) return out; } out << std::endl; return out; } }; using namespace std; using namespace fileSort; int main(int argc, char *argv[]) { unsigned int maxVal; if(4 != argc){ DBG("error params\n"); return -1; } ifstream in; ofstream out; maxVal = (unsigned int)atoll(argv[1]); in.open(argv[2], ios::in); if(in.fail()){ DBG("open file for read fail\n"); return -1; } out.open(argv[3], ios::out); if(out.fail()){ DBG("open file for write fail\n"); return -1; } bmpSort bs(maxVal); in >> bs; out << bs; return 0; }