《編程珠璣》中的一些代碼

位圖排序

使用位圖對[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;
}


從0...n-1中隨機選擇m個數
/* 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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章