位图排序

声明

    本文问题取自<<编程珠玑>>.ios

概述

  1. 须要给一个磁盘文件排序编程

  2. 该文件最多包含n个正整数,每一个数都小于n且n = 10^7,而且该文件中不会有重复数据spa

  3. 按照升序排序code

  4. 磁盘空间充足,但内存只有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;
}
相关文章
相关标签/搜索