前面发了两篇内排序的文章。(一)中当时归并排序并没有写出,(二)中今天发现在非递归quickSort中stack<node*> 存在内存泄露,并且主程序选项功能支持不是很好,所以今天又练习写了一遍。
大规模排序时,发现1million整形数据大小为6.8M,int在当前平台占4B
1million = 1000000 = 106 ≈220 总容量=4B*220 =4M≈6.8M,因为这里面还有空格、回车还有文件自身的一些信息占容量。100million数据大小为673M,1billion数据大小为6.6G。各种文件系统大小限制在下有说明。当前系统最大申请内存可达400G。
C/C++源码:sort.cpp
功能:七种常见内排序算法
void bubble(int A[],int n);
void select(int A[],int n);
void insert(int A[],int n);
void shell(int A[],int n);
void merge(int A[],int n);
void heap(int A[],int n);
void quick(int A[],int n);
//return 0 success 1 fail
int deal_opt(string& in, string& out, int& n, int& times, int argc, char *argv[]);
int deal_in(int*& A,int& n,int N, string file);
int deal_out(int A[],int n,string file);
typedef void (*FUNC)(int A[],int n);
FUNC sort_func[]={bubble,select,insert,shell,merge,heap,quick};
string sort_name[]={"bubble","select","insert","shell","merge","heap","quick"};
const int sort_num=sizeof(sort_func)/sizeof(FUNC);
const int num_per_line = 10;
int main(int argc, char *argv[])
{
string infile("din.txt"), outfile("dout_");
string help("command [-i infile] [-o outfile] [-n arrNum] [-t sortTimes]");
int num = 0, *arr = NULL,*arr1=NULL;
int N = 1024*1024*1024;
int sort_times=1;
if(0==deal_opt(infile,outfile,N,sort_times,argc,argv)){
if(0==deal_in(arr,num,N,infile)){
arr1=new int[num];
for(int i=sort_num-1;i>=0;i--){
clock_t s = clock();
for(int j=0;j<sort_times;j++){
memmove(arr1,arr,sizeof(int)*num);
(*sort_func[i])(arr1,num);
}
double timeUsed = (double)(clock()-s)/CLOCKS_PER_SEC;
cout<<sort_name[i]<<" timeUsed is "<< timeUsed << "s" << endl;
if(1==deal_out(arr1,num,outfile+sort_name[i])){
cout << "incorrect write outfile" << endl;
cout << help << endl;
}
}
delete [] arr;
delete [] arr1;
}else{
cout << "incorrect read infile" << endl;
cout << help << endl;
}
}else{
cout << "incorrect option" << endl;
cout << help << endl;
}
return 0;
}
int string_to_num(char str[]){
int len = strlen(str), sum=0;
for(int i=0;i<len;i++){
assert(str[i]>='0' && str[i]<='9');
sum = sum*10 + str[i]-'0';
}
return sum;
}
int deal_opt(string& in,string& out,int& n, int& times, int argc,char *argv[]){
for(int i=1;i<argc;i++){
if(!strncmp("-i",argv[i],2) && i<argc-1){
in = argv[i+1];
i++;
}else if(!strncmp("-o",argv[i],2) && i<argc-1){
out = argv[i+1];
i++;
}else if(!strncmp("-n",argv[i],2) && i<argc-1){
n=string_to_num(argv[i+1]);
i++;
}else if(!strncmp("-t",argv[i],2) && i<argc-1){
times = string_to_num(argv[i+1]);
i++;
}else{
return 1;
}
}
return 0;
}
int deal_in(int*& A,int& n,int N,string file){
FILE* fptr=NULL;
A = new int[N];
if((fptr=fopen(file.c_str(),"r"))!=NULL){
int data;
n=0;
while(n<N && (fscanf(fptr,"%d",&data))!=EOF)
A[n++]=data;
fclose(fptr);
return 0;
}else{
return 1;
}
}
int deal_out(int A[],int n,string file){
FILE* fptr=NULL;
if((fptr=fopen(file.c_str(),"w"))!=NULL){
for(int i=0;i<n;i++){
fprintf(fptr,"%d/t",A[i]);
if(i%num_per_line==num_per_line-1)
fprintf(fptr,"/n");
}
fclose(fptr);
return 0;
}else{
return 1;
}
}
inline void swap(int& a,int& b){
int tmp = a;
a = b;
b = tmp;
}
void bubble(int A[],int n){
for(int i=1;i<n;i++)
for(int j=1;j<=n-i;j++)
if(A[j]<A[j-1])
swap(A[j],A[j-1]);
}
void select(int A[],int n){
for(int i=0;i<n-1;i++){
int min=i;
for(int j=i+1;j<n;j++)
if(A[j]<A[min])
min = j;
swap(A[i],A[min]);
}
}
void insert(int A[],int n){
for(int i=1,j;i<n;i++){
int tmp=A[i];
for(j=0;j<i && A[j]<=tmp;j++);
for(int k=i-1;k>=j;k--)
A[k+1]=A[k];
A[j]=tmp;
}
}
void shell(int A[],int n){
int h;
for(h=1;h<n/9;h=3*h+1);
for(;h>0;h/=3){
for(int i=h,j;i<n;i+=h){
int tmp=A[i];
for(j=0;j<i && A[j]<=tmp;j+=h);
for(int k=i-h;k>=j;k-=h)
A[k+h]=A[k];
A[j]=tmp;
}
}
}
void merge1(int A[], int l, int r){
if(l<r){
int mid=(r-l)/2+l;
merge1(A,l,mid);
merge1(A,mid+1,r);
int *B = new int[r-l+1];
int i=0, j=l, k=mid+1;
while(j<=mid && k<=r) B[i++]=A[j]<A[k]?A[j++]:A[k++];
while(j<=mid) B[i++]=A[j++];
while(k<=r) B[i++]=A[k++];
memmove(A+l,B,sizeof(int)*i);
delete [] B;
}
}
void merge(int A[],int n){
merge1(A,0,n-1);
}
void heapify(int A[],int i,int n){
#define LC(i) (2*i+1)
#define RC(i) (2*i+2)
while(i<n/2){
int max = A[i],f=0;
if(max<A[LC(i)] && LC(i)<n) max=A[LC(i)], f=1;
if(max<A[RC(i)] && RC(i)<n) f=2;
if(1==f){
swap(A[i],A[LC(i)]);
i=LC(i);
}else if(2==f){
swap(A[i],A[RC(i)]);
i=RC(i);
}else
break;
}
}
void heap(int A[],int n){
if(n<=1) return;
for(int i=n/2-1;i>=0;i--)
heapify(A,i,n);
swap(A[0],A[n-1]);
for(int i=n-2;i>=1;i--){
heapify(A,0,i+1);
swap(A[0],A[i]);
}
}
struct node{
node(int a,int b):l(a),r(b){}
int l, r;
};
void quick(int A[],int n){
stack<node*> s;
s.push(new node(0,n-1));
while(!s.empty()){
int l=s.top()->l;
int r=s.top()->r;
delete s.top();
s.pop();
if(l<r){
int i=l, j=r, pivot=A[l];
while(i<j){
while(i<=j && A[i]<=pivot)
i++;
while(i<=j && A[j]>=pivot)
j--;
if(i<j) swap(A[i],A[j]);
}
swap(A[l],A[j]);
if(j-1-l>0)
s.push(new node(l,j-1));
if(r-j-1>0)
s.push(new node(j+1,r));
}
}
}
C/C++源码:data.cpp
功能:随机生成一定规模的随机数据
long long cal(char s[]){
long long sum =0;
int len = strlen(s);
for(int i=0;i<len;i++){
assert(s[i]>='0' && s[i]<='9');
sum = sum*10 + (s[i]-'0');
}
return sum;
}
const int N = 1024*1024;
const int NUM_PER_LINE = 10;
int deal_opt(string& out,long long& n,int argc, char *argv[])
{
for(int i=1;i<argc;i++){
if(!strncmp("-o",argv[i],2) && i<argc-1){
out=argv[i+1];
i++;
}else if(!strncmp("-n",argv[i],2) && i<argc-1){
n=cal(argv[i+1]);
i++;
}else
return 1;
}
return 0;
}
int main(int argc, char *argv[])
{
srand(time(NULL));
long long scale = 10000;
string outfile("data.txt");
string help("command [-o outfile] [-n num]");
if(0==deal_opt(outfile,scale,argc,argv)){
FILE *fptr = NULL;
if((fptr=fopen(outfile.c_str(),"w"))!=NULL){
for(long long i=0;i<scale;i++){
fprintf(fptr, "%d/t", rand()%N);
if(i%NUM_PER_LINE==NUM_PER_LINE-1)
fprintf(fptr, "/n");
}
}else{
cout << "incorrect write outfile" << endl;
cout << help << endl;
}
}else{
cout << "incorrect options" << endl;
cout << help << endl;
}
return 0;
}
运行结果:
数据规模10无序数据集,迭代1W次
数据规模100有无序数据集,迭代1024次
数据规模100有序数据集,迭代1024次
数据规模10W无序数据集
数据规模10W有序数据集(注意quickSort性能下降)
数据规模100W无序数据集
1Billion无序数据集(quick,heap,merge,其它O2的方法已经淘汰)
注意在小规模如果数据集全部可以装入内存,不考虑换页影响的话,三种排序时间复杂度都是O(nlgn),其中数据显示快排是时间最快,归并时间与其差不多,堆排慢于其它两种方法,大概是1.5倍关系。但是当10亿数据,内存容量约为4G。快排与堆排需要遍历遍历整个数组,会造成颠簸,而归并的性质决定了它每次处理的数据有很强的局部性,不会很大颠簸,所以归并排比其它两种性能提高数倍。
NTFS(Windows):支持最大分区2TB,最大文件2TB
FAT16(Windows):支持最大分区2GB,最大文件2GB
FAT32(Windows):支持最大分区128GB,最大文件4GB
Ext2
最大文件大小: 1TB
最大文件极限: 仅受文件系统大小限制
最大分区/文件系统大小: 4TB
最大文件名长度: 255 字符
缺省最小/最大块大小: 1024/4096 字节
缺省inode分配: 每4096字节为1
在强制FS检查前的最大装载: 20(可配置)
//REDHAT9默认是ext3的文件系统
Ext3
最大文件大小: 1TB
最大文件极限: 仅受文件系统大小限制
最大分区/文件系统大小: 4TB
最大文件名长度: 255 字符
缺省最小/最大块大小: 1024/4096 字节
缺省inode分配: 每4096字节为1
在强制FS检查前的最大装载: 20(可配置)
ReiserFS
最大文件大小: 1TB
最大文件极限: 32k目录,42亿文件
最大分区/文件系统大小: 4TB
最大文件名长度: 255 字符
JFS
最小文件系统大小 16 MB
最大文件大小: 受体系结构限制
最大文件极限: 受文件系统大小限制
缺省最小/最大块大小: 1024/4096 字节
缺省inode分配: 动态