浙大陈越老师主编《数据结构》(第2版)学习笔记
什么是数据结构?让我们在解决问题的过程中,得到对数据结构的理解。
目录
1、数据组织方式
例1.1 如果你是书店的主人,该如何摆放你的书,才能让读者很方便地找到《数据结构》这本书?
问题分析:
1、如何插入书本
2、如何查找书本
方法1:随便放
插入书本方便:哪有空插哪儿
查找书本困难:翻遍书架的每本书,才能确定地说找不到书
方法2:按照书名的拼音字母顺序摆放
插入书本痛苦:如果新书书名以A开头,得把后面所有书往后挪,才能给新书挪出位置
查找书本相对方便
方法3:书架划分区域,分类摆放;每个分类的书,按照书名拼音字母顺序摆放
与方法2相比,插入和查找,工作量都减少很多
问题1:书架划分区域时要为新书预留空间,可能造成空间浪费
问题2:类别分得越细,某一类内部查找、插入工作量越小,但查找某一类所在位置又成了麻烦
所以:解决问题的方法的效率和 数据的组织方式 有关
2、空间利用效率
例1.2 写程序实现一个函数printN,传入参数正整数N,打印从1到N的正整数
方法1:循环语句实现:
void printN_1(int n)
{
/* 打印从1到N的全部正整数(循环) */
int i;
for(i = 1; i <= n; i++)
{
printf("%d\n", i);
}
return;
}
方法2:递归实现
void printN_2(int n)
{
/* 打印从1到N的全部正整数(递归) */
if (n > 0) /* 注意:递归调用需要一个终止条件 */
{
printN_2(n - 1);
printf("%d\n", n);
}
return;
}
调用printN:
int main()
{
int N = 0;
printf("Please input a number: \n");
scanf_s("%d", &N);
printf("number is %d \n", N);
printN_1(N);
return 0;
}
测试输入N为100、1000、10000、100000的情况
当N为100000时
递归方式的printN拒绝工作了:
而循环方式printN仍然正常工作:
所以:解决问题的方法的效率还跟 空间利用效率 有关
3、算法巧妙程度
例1.3 写程序计算给定多项式在给定点x处的值
方法1:循环累计求和
/* 循环累计求和 */
double polynomial_1(unsigned int n, double a[], double x)
{
unsigned int i;
double result = 0;
for(i = 0; i <= n; i++)
{
result += (a[i] * pow(x, i));
// printf("index[%d] a[%.2f] result %.2f \n", i, a[i], result);
}
return result;
}
方法2:南宋数学家秦九韶提出的算法(不断提取公因式x来减少乘法运算次数)
以n=3为例来分析:
/* 秦九昭:不断提取公因式x
* f(X) = a0 + a1 * X + a2 * X^2 + a3 * X^3
* = a0 + X * (a1 + X * (a2 + X * a3))
*/
double polynomial_2(unsigned int n, double a[], double x)
{
double result;
unsigned int i;
result = a[n];
for(i = n; i > 0; i--)
{
result = a[i -1] + (x * result);
}
return result;
}
用于计算运行时间的程序:
typedef double (*polynomial_func)(unsigned int n, double a[], double x);
void run_func(polynomial_func func, unsigned int n, double a[], double x, unsigned int exec_count)
{
clock_t start;
clock_t stop;
unsigned int i;
double duration;
double result;
start = clock();
for(i = 0; i < exec_count; i++)
{
result = func(n, a, x);
}
stop = clock();
/* 计算运行时间,CLK_TCK是机器时钟每秒所走的时钟打点数 */
duration = ((double)(stop - start))/CLK_TCK;
printf("exec count[%d], duration is %.2f(s) \n", exec_count, duration);
printf("result is %.2f \n", result);
return;
}
调用:
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <stdlib.h>
int main()
{
double x = 0;
int n = 3;
int exec_count = 100;
double* a = NULL;
int i;
printf("please input x :\n");
scanf("%lf", &x);
printf("please input n :\n");
scanf("%d", &n);
printf("please input exec count :\n");
scanf("%d", &exec_count);
if(n < 0 || exec_count <= 0)
{
printf("ERROR: invalid param: n[%d] exec count[%d] \n",
n, exec_count);
return -1;
}
printf("x[%.2f] n[%d] exec coun[%d] \n", x, n, exec_count);
a = (double*)calloc(1, (n + 1) * sizeof(double));
if(NULL == a)
{
printf("ERROR: malloc for a failed! \n");
return -1;
}
for(i = 0; i <= n; i++)
{
a[i]= i;
}
printf("\n polynomial_1: \n");
run_func(polynomial_1, n, a, x, exec_count);
printf("\n polynomial_2: \n");
run_func(polynomial_2, n, a, x, exec_count);
free(a);
return 0;
}
运行结果:
所以:解决问题的方法的效率也跟 算法巧妙程度 有关