1、題目: ios
如何在1MB的空間裏面對一千萬個整數進行排序?而且每一個數都小於1千萬。實際上這個須要1.25MB的內存空間(這裏所說的空間是考慮用位圖表示法時,每一位表明一個數,則1千萬/(1024*1024*8) 約爲1.25MB )。面試
1MB總共有838,8608個可用位。因此估計也能夠在1MB左右的空間裏面進行排序了。數組
分析: 數據結構
1)基於磁盤的歸併排序(耗時間)ide
2)每一個號碼採用32位整數存儲的話,1MB大約能夠存儲250 000 個號碼,須要讀取文件40趟才能把所有整數排序。(耗時間)spa
3)位圖法,採用一個1千萬位的字符串表示每一個數,好比{0,2,3}表示爲 1 0 1 1 0 0 0 0 。(說明:左邊第一位表示 0 第二位表示1 第三位表示 2 。若是有則表示爲1,不然爲0)遍歷每個整數,有則標記爲1,不然標記爲0。而後按順序輸出每一個整數。這種方法實際須要1.25MB內存,若是能夠方便弄到內存的話能夠採用此種方法。.net
2、代碼實現 3d
/*C++中的bitset實現位圖*/ #include <iostream> #include<bitset> using namespace std; #define MAXNUMBER 10000000 //利用bitset完成在必定範圍內的正整數排序,並標準輸出 int IntRangeSort(int pdata[],int n) { //static bitset<MAXNUMBER> intset; //或者new一個 bitset<MAXNUMBER> * intset = new bitset<MAXNUMBER>; //用位圖記錄數據 for(int i = 0;i < n;i++) (*intset)[pdata[i]]=1; //intset[pdata[i]]= 1; //輸出有序數據 for(int i = 0;i < MAXNUMBER;i++) //if(intset[i] == 1) if((*intset)[i] == 1) cout<<i<<" "; cout<<endl; return 0; } void main() { int pdata[10]; for(int i = 0;i < 10;i++) { pdata[i] = rand()%10000000; cout<<pdata[i]<<" "; } cout<<endl; IntRangeSort(pdata,10); system("pause"); }
注:利用bitset時設置大於1M的棧大小時,vs會報錯誤(vs默認分配的棧大小約爲1M),解決辦法是聲明爲static(至關於將這些數據放於全局數據區) 或者 new一個bitset(至關於在棧上分配內存)。code
/*用數組實現位圖*/ #include <stdio.h> #include<stdlib.h> #define MAXNUMBER 10000000 #define MASK 0x1F #define SHIFT 5 int sets[1+MAXNUMBER/32]; void set(int i){sets[i>>SHIFT] |= (1<<(i & MASK));} void clr(int i){sets[i>>SHIFT] &= ~(1<<(i & MASK)); } int test(int i){return sets[i>>SHIFT] & (1<<(i & MASK));} void main() { int i = 0; while(scanf("%d",&i)) set(i); for(i = 0;i < MAXNUMBER;i++) if(test(i)) printf("%d\n",i); system("pause"); }
注:位操做解釋請看:http://zjianjia.blog.163.com/blog/static/17408947520137249535631/blog
3、課後習題
習題1-1:
#include <stdio.h> #include<stdlib.h> #define MAXNUMBER 10000000 int cmp(const void *a,const void *b) { return (*(int*)a) - (*(int*)b); } void main() { static int data[MAXNUMBER]; int n,i; while(scanf("%d",&n) != EOF) { for(i = 0;i < n;i++) scanf("%d",&data[i]); qsort(data,n,sizeof(int),cmp); for(i = 0;i < n;i++) printf("%d ",data[i]); printf("\n"); } system("pause"); }
習題1-4:使用兩趟排序
習題1-6:
#include <stdio.h> #include<stdlib.h> #define MAXNUMBER 10000000 #define BIN 8 #define MASK 0x07 #define SHIFT 3 #define TEST 0x0F #define POS ((i & MASK)<<2) int sets[1+MAXNUMBER/BIN]; void set(int i){sets[i>>SHIFT] += 1<<POS;} void clr(int i){sets[i>>SHIFT] &= ~(TEST<<POS); } int test(int i){return (sets[i>>SHIFT] & TEST << POS) >> POS;} void main() { int i = 0,j = 0; while(scanf("%d",&i) != EOF) set(i); for(i = 0;i < MAXNUMBER;i++) for(j=test(i);j>0;j--) { printf("%d ",i); printf("\n"); } system("pause"); }
4、總結
1 正確的問題:分析問題的輸入、輸出、約束。有時在分析問題的約束時能夠將一個極其複雜的問題簡化爲一個簡單的問題。
2 位圖數據結構:描述了一個有限定義域內的集合。
這兒是一些面試題中位圖的應用【位圖數據結構應用】
參考:
http://blog.csdn.net/tianshuai1111/article/details/7555563 感謝該做者的分享