位图排序
使用位图对[0..N-1]中不同的整数进行排序
/* bitmap sort -- Sort distinct integers in the range [0..N-1] */ #include <stdio.h> #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)); } int main() { int i; for (i = 0; i < N; i++) clr(i); /* Replace above 2 lines with below 3 for word-parallel init int top = 1 + N/BITSPERWORD; for (i = 0; i < top; i++) a[i] = 0; */ while (scanf("%d", &i) != EOF) set(i); for (i = 0; i < N; i++) if (test(i)) printf("%d\n", i); return 0; }
/* sortedrand.cpp -- output m sorted random ints in U[0,n) */ #include <iostream> #include <set> #include <algorithm> using namespace std; int bigrand() { return RAND_MAX*rand() + rand(); } int randint(int l, int u) { return l + bigrand() % (u-l+1); } void genknuth(int m, int n) { for (int i = 0; i < n; i++) /* select m of remaining n-i */ if ((bigrand() % (n-i)) < m) { cout << i << "\n"; m--; } } void gensets(int m, int n) { set<int> S; set<int>::iterator i; while (S.size() < m) { int t = bigrand() % n; S.insert(t); } for (i = S.begin(); i != S.end(); ++i) cout << *i << "\n"; } void genshuf(int m, int n) { int i, j; int *x = new int[n]; for (i = 0; i < n; i++) x[i] = i; for (i = 0; i < m; i++) { j = randint(i, n-1); int t = x[i]; x[i] = x[j]; x[j] = t; } sort(x, x+m); for (i = 0; i < m; i++) cout << x[i] << "\n"; } void genfloyd(int m, int n) { set<int> S; set<int>::iterator i; for (int j = n-m; j < n; j++) { int t = bigrand() % (j+1); if (S.find(t) == S.end()) S.insert(t); // t not in S else S.insert(j); // t in S } for (i = S.begin(); i != S.end(); ++i) cout << *i << "\n"; } int main(int argc, char *argv[]) { int m = atoi(argv[1]); int n = atoi(argv[2]); genknuth(m, n); return 0; }
使用后缀数组,字符串保存在c中,后缀数组为a,C代码:
/* longdup.c -- Print longest string duplicated 1 times */ #include <stdlib.h> #include <string.h> #include <stdio.h> int pstrcmp(const void *p, const void *q) { return strcmp(*(char **)p, *(char **)q); } int comlen(char *p, char *q) { int i = 0; while (*p && (*p++ == *q++)) i++; return i; } #define MAXN 5000000 char c[MAXN], *a[MAXN]; int main() { int i, ch, temlen, n = 0, maxi, maxlen = -1; while ((ch = getchar()) != EOF) { a[n] = &c[n]; c[n++] = ch; } c[n] = 0; qsort(a, n, sizeof(char *), pstrcmp); for (i = 0; i < n-1; i++) { temlen = comlen(a[i], a[i+1]); if (temlen > maxlen) { maxlen = temlen; maxi = i; } } printf("%.*s\n", maxlen, a[maxi]); return 0; }
二分查找可以解决排序数组的查找问题:只要数组中包含T(即要查找的值),那么通过不断缩小包含T的范围,最终就可以找到它。一开始,范围覆盖整个数组。将数组的中间项与T进行比较,可以排除一半元素,范围缩小一半。就这样反复比较,反复缩小范围,最终就会在数组中找到T,或者确定原以为T所在的范围实际为空。对于包含N个元素的表,整个查找过程大约要经过log(2)N次比较。
//copyright@2011 July //随时欢迎读者找bug,email:[email protected]。 //首先要把握下面几个要点: //right=n-1 => while(left <= right) => right=middle-1; //right=n => while(left < right) => right=middle; //middle的计算不能写在while循环外,否则无法得到更新。 int binary_search(int array[],int n,int value) { int left = 0; int right = n-1; //如果这里是int right = n 的话,那么下面有两处地方需要修改,以保证一一对应: //1、下面循环的条件则是while(left < right) //2、循环内当array[middle]>value 的时候,right = mid while (left <= right) //循环条件,适时而变 { int middle = left + ((right-left)>>1);//防止溢出,移位也更高效。每次循环都需要更新。 if (array[middle] > value) { right = middle-1; //right赋值,适时而变 } else if(array[middle] < value) { left = middle+1; } else return middle; //可能会有读者认为刚开始时就要判断相等,但毕竟数组中不相等的情况更多 //如果每次循环都判断一下是否相等,将耗费时间 } return -1; }