• 位排序算法



    title: 位图数据结构-位排序算法
    date: 2020-08-16
    tags: 算法;位排序

    位排序算法,一种占用内存小、运行时间快应用于特殊情况的算法

    0x01.问题背景

    • 问题描述:需要对磁盘中的文件进行排序,对时间效率要求高,文件中包含千万条记录,每条记录都是7位整数(百万)号码
      整数记录数据不重复,每条记录都是单一数据。
    • 输入:一个包含N个整数的文件,每个数都小于N=10^7,整数无重复
    • 输出:将输入的整数进行升序排序,输出有序的列表
    • 约束条件:大约有1MB的内存空间可用,充足的磁盘空间,时间控制在10s-8min之间

    0x02.解决方法

    1.归并排序

    磁盘文件最常用的排序算法就是归并排序,但是对于千万数量级别的数据,运行时间是以天为单位

    // 归并排序算法实现
    int mergeSortCore(int[] &array,int lo,int mid,int hi)
    {
        int len=array.size();   // 数组长度
        // 将数组进行备份
        int compare[array.size()];
        for(int k=0;k<len;k++)
        {
            compare[k]=array[k];
        }
    
        // 双指针进行比较赋值
        int i=lo;
        int j=mid+1;
        for(int k=lo;k<=hi;k++)
        {
            if(i>mid)       array[k]=compare[j++];
            else if(j>hi)   array[k]=compare[i++];
            else if(compare[i]>compare[j]) array[k]=compare[j++];
            else            array[k]=compare[i++];
        }
    
    }
    
    void mergeSort(int[] &arr,int left,int right)
    {
        if(left>right) return;
        int mid=(left+right)/2;
        mergeSort(arr,left,mid);
        mergeSort(arr,mid+1,right);
        mergeSortCore(arr,left,mid,right);
    
    }
    
    void sort(int []arr)
    {
    
        mergeSort(arr,0,arr.size());
    
    }
    
    

    2.分治+快速排序

    1MB的内存空间
    1MB=1024KB=1024x1024=1048576 byte

    每个数是7位百万级别的整数
    32bit=4byte可以表示的范围(04294967296,-21474836482147483647)
    1048576/4=262144
    10^7/40=250000

    • 解决办法:1MB大概可以存储250000个整数号码,将N=10^7文件分成40子文件
      (0249999,250000499999,...,9750000~999999),遍历输入40次
      每次的排序算法使用快速排序,达到效率最高

    • 快速排序
      快速排序最重要的是找到partition函数

    // define the swap function
    void swap(int[] &arr,int lo,int hi)
    {
        int temp=arr[lo];
        arr[lo]=arr[hi];
        arr[hi]=temp;
    }
    
    int partiton(int[] &arr,int left,int right)
    {
        // define the flag value and two pointer
        int flag=arr[left];
        int i=left+1;
        int j=right;
        // swap the value base the flag
    
        // need TODO
        // optimize
        while(i<j){
            if(arr[i]>flag && arr[j]<flag)
            {
                swap(arr,i,j);
                i++;
                j--;
            }
            else if(arr[i]<flag && arr[j]<flag)
            {
                i++;
            }
            else if(arr[i]>flag && arr[j]>flag)
            {
                j--;
            }
            else
            {
                i++;
                j--;
            }
        }
        swap(arr,lo,j);
        return j;
    }
    
    // optimization partition function
    int optPartition(int[] &arr,int lo,int hi)
    {
        int flag=arr[lo];
        // 注意这两个指针的开始位置
        int i=lo;
        int j=hi+1;
        while(true)
        {
            while(arr[++i]<flag) if(i==hi) break;
            while(flag<arr[--j]) if(j==lo) break;
            if(i>=j) break;
            swap(arr,i,j);
        }
        // 将flag放入正确的位置
        swap(arr,lo,j);
        return j;
    }
    
    void QuickSort(int[] &arr,int lo,int hi)
    {
        // break the recursive
        if(lo>=hi)
        {
            return;
        }
        int index=partiton(arr,lo,hi);
        QuickSort(arr,lo,index-1);
        QuickSort(arr,index+1,hi);
    }
    
    
    void sort(int[] &arr)
    {
        QuickSort(arr,0,arr.size());
    }
    
    

    3.位排序算法

    使用位图(位向量)来表示集合,用百万bit位的字符串来表示

    01010001100 这个字符串表示{2,4,8,9}四个数存在(下标位置)

    • 1.构建一个长度可以满足要求的bitarray,所有位置全部置0
    • 2.输入数字,找到对应的下标,并改为1
    • 3.遍历bitarray,只要是位置为1就进行输出

    10^7/8=1250000 大概是1.19MB,内存大小刚刚够

    // 伪代码,没有考虑文件的输入输出
    // 定义数组也是不对,只是为了说明问题
    #include<string>
    #define MAX_VLAUE 10000000
    
    int main()
    {
        string bitarray[MAX_VLAUE];
    
        // first step
        for(int i=0;i<MAX_VLAUE;i++)
        {
            bitarray[i]=0;
        }
        // second step
        // TODO condtion 表示文件中存在这个数
        for(int i=0;i<MAX_VLAUE && condition ;i++){
            bitarray[i]=1;
        }
        // third step
        for(int i=0;i<MAX_VLAUE && bitarray[i]==1;i++){
            printf("%d
    ",i);
        }
    
        return 0;
    }
    
  • 相关阅读:
    CCDictionary 用调试器查看问题
    博客 小记
    cocos2d-x 调试问题
    string知识
    静动态库
    fedora 20安装vim Transaction check error
    PyQt中ui编译成窗体.py,中文乱码
    centos编译安装vim7.4
    linux c驴杂记
    c++指针 c指针 改变值
  • 原文地址:https://www.cnblogs.com/GeekDanny/p/13513215.html
Copyright © 2020-2023  润新知