利用哈希表实现11位电话号码的快速排序

来源:互联网 发布:windows输错密码锁定 编辑:程序博客网 时间:2024/04/28 12:41

1 问题提出

设一个文件包含10亿条数据,其中每一条数据都是一个13开头的11位移动电话号码,且电话号码不重复,请用尽可能小的内存空间,将这些整数按升序进行排列,要求排序算法的时间复杂度为O(n)。

2 求解思路

难点包括两方面:时间复杂度和空间复杂度
1)时间复杂度:如果通过比较关键值(元素,电话号码)来排序,较快的算法时间复杂度也为O(nlogn),但是要求为O(n)。
2)空间复杂度,一条电话号码长度为11,10亿条大概需要4G内存,如何利用更小的内存来解决这个问题
方法:
可以使用位串数组的方式,来构造散列表,即如果某一电话号码存在可以令该电话号码为位串数组下标,并将相应位串元素置1。

算法实现步骤:
1)构造一个空的散列表:unsigned char ch[125000000] = {0}
2) 编写insert_ele子函数,实现在位串中插入一个元素
3)读取电话号码存放的文件,并调用insert_ele子函数,生成位串散列表
4)读取散列表,将位串中值为1的元素转换成相应的电话号码,存入文件中

C++程序
主函数

#include<iostream>#include<stdlib.h>#include<fstream>#include"myatol.h"using namespace std;/*********************************************************//*      11位电话号码的排序,要求时间复杂度为O(n)         *//*                利用位串实现,排序                     *//*********************************************************/// 算法实现步骤:// 1)构造一个空的散列表:unsigned char ch[125000000] = {0}// 2) 编写insert_ele子函数,实现在位串中插入一个元素// 3)读取电话号码存放的文件,并调用insert_ele子函数,生成位串散列表// 4)读取散列表,将位串中值为1的元素转换成相应的电话号码,存入文件中/*********************************************************/void insert_ele(unsigned char ch[], long long elementary);void generate_hash(unsigned char ch[]);void sort_by_hash(unsigned char ch[]);void main(){    unsigned char ch[125000000] = {0};    generate_hash(ch);//从电话文件中读取电话号码,并置位位串相应位置的元素,构成哈希表    sort_by_hash(ch);//从位串中顺序读取已经排序好的电话号码到文件中       system("pause");}void insert_ele(unsigned char ch[],long long elementary){ int i = (elementary % 1000000000)/8; int j = elementary % 8; ch[i] = ch[i] | (0x01 << j); cout<<"ch[i]: "<<i<<endl; cout<<"ch[i][j]: "<<j<<endl;}void generate_hash(unsigned char ch[]){    char str[12];    ifstream in("data.txt");    while(! in.eof())    {        in.getline(str,12,'\n');        cout << "str: "<<str <<endl;        myatol a;        long long b = a.myAtoll((str));        if(b)        insert_ele(ch,b);        cout<< "b: "<<b <<endl;    }    in.close();}void sort_by_hash(unsigned char ch[]){ ofstream out("data1.txt"); for(int i = 0;i < 125e6;i++) {      for(int j = 0; j < 8;j++)  {      unsigned char n = 1;      n = n << j;   if((ch[i]&n))       {           long long data = 13e9 + i*8 +j;           out <<data<<endl;           cout <<data<<endl;           //cout<<i*8 +j<<endl;        }   }  } out.close();}

头文件函数

#ifndef MYATOL_H_#define MYATOL_H_#include<iostream>using namespace std;class myatol{public:    long long myAtoll(const char * str)    {     long long res = 0;     int flag = 1;     int i = 0;     int count = 0;     while(str[i] == ' ')         i++;     if(str[i] == '-')     {      flag = -1;      i++;      count++;     }     else         if(str[i] == '+')         {          flag = 1;          i++;          count++;//当出现两个符号时,输出0              }    if(count > 1) return 0;    if(str[i]> '9' || str[i] < '0')     {      return 0;     }    int numcount = 0;    for(;str[i];i++)    {      if( str[i] >='0' && str[i] <= '9')     {         numcount++;         res = res * 10 +(str[i] - '0');         if(numcount > 12)         {          cout<<"数字超出上界"<<endl;          break;         }     }    }    return res;    }};#endif
原创粉丝点击