第一章 开篇

来源:互联网 发布:ftp被动模式端口范围 编辑:程序博客网 时间:2024/05/17 05:15

    《编程玑珠》中一些章节中有一些算法的实现,书后和网络上有源代码的例子,边看边学同时做一下记录。

如果不缺内存,如何使用一个具有库的语言来实现一种排序算法以表示和排序集合。

利用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 10000000int 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 10000000int 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 200000int 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


原创粉丝点击