《编程玑珠》中一些章节中有一些算法的实现,书后和网络上有源代码的例子,边看边学同时做一下记录。
如果不缺内存,如何使用一个具有库的语言来实现一种排序算法以表示和排序集合。
利用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.youkuaiyun.com/qiuyang0607/article/details/6789358
rand()与srand()函数:http://blog.sina.com.cn/s/blog_5fe506110100d4ne.html