第 1 章 引论

1.1 本书讨论的内容

举例:

  • 选择问题:求一组数的第 k 个最大者。
  • 字谜游戏:在一个字母组成的矩阵中找出单词。

在许多问题当中:一个重要的观念是:写出一个可以正确工作的程序并不够。

我们将在本书中看到对于大量的输入,如何估计程序的运行时间,尤其是在尚未具体编码的情况下比较两个程序的运行时间。

1.2 数学知识复习

1.2.1 指数

1.2.2 对数

1.2.3 级数

1.2.4 模运算

1.2.5 证明方法

归纳法证明、反证法证明

1.3 递归简论

递归的四条基本法则:

1. 基准情形。

2. 不断推进。

3. 设计法则。

4. 合成效益法则。

总结

这一章为本书其余部分建立一个舞台。对于面临大量输入的算法,他所花费的时间是一个判别其好坏的重要的标准。

(当然正确性是最重要的。)速度是相对的。对于一个问题在一台机器上是快速的算法有可能对另一问题或在不同的

机器上就变成了慢的。我们将在下一章讲述这些问题,并将用这里讨论的数学概念建立一个正式的模型。


练习

1.1 编写一个程序解决选择问题。令 k = N / 2。画出表格显示你的程序对于 N 为不同值的运行时间。

1 M 10 M 100 M 1 G
Time 7 ms 586 ms 5.793 s 58.697 s
#include 
#include 
#include 

#ifndef N
#define N  100000000
#endif // !N

void RandomFillArray(int* array, size_t len);
void PrintArray(int* array, size_t len);
int GetMaxNArray(int* array, size_t len, size_t n);

int main()
{
	const size_t k = N / 2;

	int* arr = (int*)malloc(N * sizeof(int)); // 获取内存
	RandomFillArray(arr, N); // 以随机数填充数组

	if (N < 1000) 
		PrintArray(arr, N);

	clock_t start = clock(); // 开始计时
	int re = GetMaxNArray(arr, N, k); // 获取第 k 大元素
	clock_t finish = clock(); // 停止计时

	if (N < 1000) 
		PrintArray(arr, N);

	printf("\nThe max %lld element is [ %d ]\n", k, re); // 输出结果
	double total_time = (double)((long long)finish - start) / CLOCKS_PER_SEC; // 计算用时
	printf("Use time: %f seconds \n", total_time); // 输出用时

	free(arr); // 释放内存
}

void RandomFillArray(int* array, size_t len)
{
	srand((unsigned int)(time(NULL)));
	for (size_t n = 0; n < len; ++n) 
		*(array + n) = rand() % 1000;	
}

void PrintArray(int* array, size_t len)
{
	printf("\n");
	for (size_t n = 0; n < len; ++n) {
		if (n > 0 && n % 20 == 0) 
			printf("\n");
		printf("%3d, ", *(array + n));
	}
	printf("\n");
}

int compare_ints(const void* a, const void* b)
{
	int arg1 = *(const int*)a;
	int arg2 = *(const int*)b;

	if (arg1 < arg2) return -1;
	if (arg1 > arg2) return 1;
	return 0;

}

int GetMaxNArray(int* array, size_t len, size_t n)
{
	qsort(array, len, sizeof(array[0]), compare_ints);
	return *(array + (len - n));
}

1.2 编写一个程序求解字谜游戏问题。

暂略。

1.3 只使用处理 I/O 的 PrintDigit 函数,编写一个过程以输出任意实数(可以是负的)。

#include 
#include 
#include  // for abs()
#include    // for pow()

#define PrintDigit(ch) (putchar((ch) + '0'))

void PrintOut(uint64_t number);
void PrintRealNumber(double number, uint8_t precision);

int main()
{
	PrintRealNumber(-12345678.6789, 5);
}

// Print nonnegative number
void PrintOut(uint64_t number)
{
	if (number >= 10)
		PrintOut(number / 10);
	PrintDigit(number % 10);
}

void PrintRealNumber(double number, uint8_t precision)
{
	if (number < 0)
		putchar('-');
	uint32_t pow_num = (uint32_t)pow(10, precision);
	uint64_t integer = llabs((long long int)(number * pow_num));
	uint64_t integer_part = integer / pow_num;
	uint64_t float_part = integer % pow_num;

	PrintOut(integer_part);
	putchar('.');
	PrintOut(float_part);
}

1.4 C 提供形如

             #include filename

的语句,它读入文件 filename 并将其插入到 include 语句处。include 语句可以嵌套;换句话说,文件 filename 本身还可以包含 include 语句,但是显然一个文件在任何链接中都不能包含它自己。编写一个程序,使它读入被 include 语句修饰的一个文件并且输出这个文件。

暂略。

1.5 证明下列公式:

  a.  log X < X 对所有的 X > 0 成立。

你可能感兴趣的:(算法与数据结构)