《编程玑珠》中一些章节中有一些算法的实现,书后和网络上有源代码的例子,边看边学同时做一下记录。
如果不缺内存,如何使用一个具有库的语言来实现一种排序算法以表示和排序集合。
利用C语言中的qsort函数实现程序。
“
qsort函数是ANSI C标准中提供的,其声明在stdlib.h文件中,是根据二分法写的,其时间复杂度为n*log(n),其结构为:
void qsort(void *base, size_t nelem, size_t width, int (* comp)(const void *, const void *));
其中:
*base 为要排序的数组
nelem 为要排序的数组的长度
width 为数组元素的大小(一字节为单位)
默认的顺序是从小到大
(* comp)(const void *p1,const void *p2) 为判断大小函数的指针,这个函数需要自己定义,如果p1>p2,函数返回-1;a<b,函数返回1;a==b函数返回0。
”
//Sort input set of integers using qsort #include <stdio.h> #include <stdlib.h> int a[10000]; /* int intcmp(int *x, int *y) { return (*x-*y); } */ int intcmp(const void *x, const void *y) { return *(int *)x-*(int *)y; } int main() { int i, n=0; while(scanf("%d",&a[n])!=EOF) n++; qsort(a, n, sizeof(int), intcmp); for(i=0;i<n;i++) printf("%d ",a[i]); return 0; }
使用C++中的标准模板库中的set容器实现:
// Sort input set of integers using STL set // set容器中每个元素的值必须惟一,而且系统会根据该值自动将数据排序 #include <iostream> #include <vector> //#include <iterator> using namespace std; int main() { int i; set<int> S; set<int>::iterator iset; while(cin>>i) S.insert(i); for(iset=S.begin();iset!=S.end();++iset) printf("%d ",*iset); /* while(*iset>0) { printf("%d ",*iset); ++iset; } */ return 0; }
使用位逻辑运算(例如与、或、移位)来实现位向量并编写程序实现位图排序,程序可以实现用10000000个bit位排序最多10000000个不同的正整数,其中每个正整数都小于10000000
使用一个数组存储数据,其中数组每一位模拟块32bit位的内存空间(1MB大概是8000000bit位),使用位运算将代表数据的某一位设置为0或1,其实是一个输入数据到位图的转换程序。注意其中的位运算符的结合性都是自左向右。程序设置了3个函数,分别完成置1,清0和检测的功能。
// Bitmap sort // Sort distinct integers in the range [0...N-1] #include <stdio.h> #define BITSPERWORD 32 #define N 10000000 int a[1+N/BITSPERWORD]; //void set(int i){a[i/BITSPERWORD]|=((i%BITSPERWORD)<<1);} void set(int i){a[i/BITSPERWORD]|=(1<<(i%BITSPERWORD));} //void clr(int i){a[i/BITSPERWORD]&=~((i%BITSPERWORD)<<1);} void clr(int i){a[i/BITSPERWORD]&=~(1<<(i%BITSPERWORD));} //int test(int i){return a[i/BITSPERWORD]&((i%BITSPERWORD)<<1);} int test(int i){return a[i/BITSPERWORD]&(1<<(i%BITSPERWORD));} int main() { int i; for(i=0;i<N;i++) clr(i); while(scanf("%d",&i)!=EOF) set(i); for(i=0;i<N;i++) if(test(i)) printf("%d ",i); return 0; }
程序是包括0在内的,所以题目的准确描述是10000000个不同的非负整数,每个非负整数都小于10000000。上面的程序是按照移位的思路写下来的,但源程序有另外两个宏变量:SHIFT,MASK。功能是一样的,上面的程序给的函数形参是按照十进制处理的,在多加宏变量的情况下是按照二进制处理的(不太好理解)。主函数相同。
#define BITSPERWORD 32 #define SHIFT 5 #define MASK 0x1F #define N 10000000 int a[1 + N/BITSPERWORD]; void set(int i) { a[i>>SHIFT] |= (1<<(i & MASK)); } void clr(int i) { a[i>>SHIFT] &= ~(1<<(i & MASK)); } int test(int i){ return a[i>>SHIFT] & (1<<(i & MASK)); }
如何生成位于0至n-1之间的k个不同的随机顺序的随机整数?尽量使你的程序简短且高效。
思路是初始化一个有序的n元数组,利用函数生成一个从0到n-1的随机数,从0开始循环k次,每次将当前数组下标值数据与该随机数标注的数组下标值数据交换,从而生成k个不同的随机数。生成随机数的函数用到stdlib库中的rand()。
// get k distinct numbers in the range [0...n-1] #include <stdio.h> #include <time.h> #include <stdlib.h> //for rand(),srand(),atoi() #define MAXN 200000 int x[MAXN]; // generate a random integer between a and b (including a and b) int randint(int a, int b) { //return a+(RANDMAX*rand()+rand())%(b+1-a); return a+(RAND_MAX*rand()+rand())%(b+1-a); } int main(int argc, char *argv[]) { int i,k,n,p,t; k=atoi(argv[1]); n=atoi(argv[2]); //srand(time(NULL)); srand((unsigned) time(NULL)); // for(i=0;i<n;i++) x[i]=i; for(i=0;i<k;i++) { t=randint(i,n-1); p=x[i]; x[i]=x[t]; x[t]=p; } for(i=0;i<k;i++) printf("%d\n",x[i]); return 0; }
参考资料:
C语言qsort部分:http://hi.baidu.com/zfsuan/blog/item/07a6ab1e45f6fcd8a6866952.html
位运算符的结合性:http://blog.csdn.net/qiuyang0607/article/details/6789358
rand()与srand()函数:http://blog.sina.com.cn/s/blog_5fe506110100d4ne.html