数据结构笔记第一章

6 篇文章 0 订阅

第一章

第一节

1.1.1 例1:在书架上摆放图书

方法1:随便放
操作1:新书怎么插入?
哪里有空放哪里,一步到位!
操作2:怎么找到某本指定的书?
…累死

方法2:按照书名的拼音字母顺序排放
操作1:新书怎么插入?
新进一本(阿Q正传)…
操作2:怎么找到某本指定的书?
二分查找!

例1说明:

解决问题方法的效率,跟数据的组织方式有关

1.1.2 例2:写程序实现一个函数PrintN,使得传入一个正整数为N的参数后,能顺序打印从1到N的全部参数

循环实现

void PrintN(int N){
	int i;
	for(int i = 1; i < N; i++){
		printf("%d\n", i);
	}
	return;
}

递归实现

void PrintN(int N){
	if(N){
		printN(N - 1){
			printf("%d\n", N);
		}
	}
	return;
}

当输入为10000时 在Visual Studio 2019中输出的结果是:
循环实现的程序正常运行
递归实现的程序发生错误

在这里插入图片描述

例2说明:

解决问题方法的效率,跟空间利用率有关

1.1.3 例3:写程序计算给定多项式在给定点 x \mathcal{x} x处的值

f ( x ) = a 0 + a 1 x + a 2 x + . . . + a n − 1 x n − 1 + a n x n f(x)=a_0+a_1x+a_2x+...+a_n-1x^{n-1}+a_nx^n f(x)=a0+a1x+a2x+...+an1xn1+anxn

方法1:

double f(int n, double a[], double x) {
	int i;
	double p = a[];
	for (i = 1; i <= n; i++) {
		p += a[i] * pow(x, 1);
	}

	return p;
}

不建议使用上述方法

方法2:
f ( x ) = a 0 + x ( a 1 + x ( . . . ( a n − 1 + x ( a n ) ) . . . ) ) f(x)=a_0+x(a_1+x(...(a_n-1+x(a_n))...)) f(x)=a0+x(a1+x(...(an1+x(an))...))

double f(int n, double a[], double x) {
	int i;
	double p = a[n];
	for (i = n; i > 0; i--) {
		p = a[i - 1] + x * p;
	}

	return p;
}

方法2的代码运行比方法1快许多
clock():捕捉从程序开始运行到clock()被调用时所耗费的时间,这个时间单外是clock tick,即“时钟打点”。
常数CLK_TCK:机器时钟每秒所走的时钟打点数。

#include "stdio.h"
#include "time.h"

clock_t start, stop;
/* clock_t 是 clock() 函数返回的数据类型*/
double duration;
/*记录被测函数运行时间,以秒为单位*/
int main() {
	start = clock();
	MyFunction();
	stop = clock();
	duration = ((double)(stop - start)) / CLK_TCK;
	/*其他不再测试范围内的处理写在后面,例如输出duration的值*/
	return 0;
}

测试:
写程序计算给定多项式
∑ i = 0 9 i ⋅ x i \sum_{i=0}^{9}i \cdot x^i i=09ixi
在给定点 x = 1.1 \mathcal{x}=1.1 x=1.1处的值 f ( 1.1 ) f(1.1) f(1.1)

#include "stdio.h"
#include "time.h"
#include "math.h"

clock_t start, stop;
/* clock_t 是 clock() 函数返回的数据类型*/
double duration;
/*记录被测函数运行时间,以秒为单位*/
#define MAXN 10
double f1(int n, double a[], double x);
double f2(int n, double a[], double x);

int main() {
	int i;
	double a[MAXN];/*存储多项式的系数*/
	for (i = 0; i < MAXN; i++) {
		a[i] = (double)i;
	}

	start = clock();
	f1(MAXN - 1, a, 1.1);
	stop = clock();
	duration = ((double)(stop - start)) / CLK_TCK;
	printf("ticks1 = %f\n", (double)(stop - start));
	printf("duration1=%6.2e\n", duration);

	start = clock();
	f2(MAXN - 1, a, 1.1);
	stop = clock();
	duration = ((double)(stop - start) / CLK_TCK);
	printf("ticks2 = %f\n", (double)(stop-start));
	printf("duration2 = %6.2e\n", duration);

	return 0;
}

结果:
ticks1和ticks2都为0,duration1和duration2也都为0
原因是这两个程序都运行太快,运行时间都不到一个tick
解决:
让被测函数重复运行充分多次,使得测出的总的时钟打点间隔充分长,最后计算被测函数平均每次的运行时间即可

#include "stdio.h"
#include "time.h"
#include "math.h"


#define MAXK 1e7/*被测函数最大调用次数*/

clock_t start, stop;
/* clock_t 是 clock() 函数返回的数据类型*/
double duration;
/*记录被测函数运行时间,以秒为单位*/


#define MAXN 10
double f1(int n, double a[], double x);
double f2(int n, double a[], double x);

int main() {
	int i;
	double a[MAXN];/*存储多项式的系数*/
	for (i = 0; i < MAXN; i++) {
		a[i] = (double)i;
	}

	start = clock();
	for (i = 0; i < MAXK; i++) {
		f1(MAXN - 1, a, 1.1);
	}
	stop = clock();
	duration = ((double)(stop - start)) / CLK_TCK / MAXK; //计算函数单次运行时间
	printf("ticks1 = %f\n", (double)(stop - start));
	printf("duration1=%6.2e\n", duration);

	start = clock();
	for (i = 0; i < MAXK; i++) {
		f2(MAXN - 1, a, 1.1);
	}
	stop = clock();
	duration = ((double)(stop - start) / CLK_TCK) / MAXK; //计算函数单次运行时间
	printf("ticks2 = %f\n", (double)(stop-start));
	printf("duration2 = %6.2e\n", duration);

	return 0;
}

例3说明:

解决问题方法的效率,跟算法的巧妙程序有关

1.1.4抽象数据类型

所以到底什么是数据结构?
数据对象在计算机中的组织方式
*逻辑结构
*物理存储结构
数据对象必定与一系列加在其上的操作相关联
完成这些操作所用的方法就是算法

抽象数据类型(Abstract Data Type)
数据类型
*数据对象集
*集合相关联的操作集

抽象:描述数据类型的方法不依赖于具体实现
*与存放数据的机器无关
*与数据存储的物理结构无关
*与实现操作的算法和编程语言均无关
只描述数据对象集和相关操作集“是什么”,并不涉及“如何做到”的问题

例4:“矩阵”的抽象数据类型定义
类型名称:矩阵(Matrix)
数据对象集:一个 M × N \mathcal{M \times N} M×N的矩阵 A M × N = ( a i j ) ( i = 1 , . . . , M ; j = 1 , . . . , N ) A_{M \times N} = (a_{ij})(i=1, ..., M; j=1, ..., N) AM×N=(aij)(i=1,...,M;j=1,...,N) M × N \mathcal{M \times N} M×N个三元组 < a , j , j > \mathcal{<a, j, j>} <a,j,j>构成,其中 a \mathcal{a} a是矩阵元素的值, i \mathcal{i} i是元素所在的行号, j \mathcal{j} j是元素所在的列号。
操作集合:对于任意矩阵 A , B , C ∈ M a t r i x \mathcal{A, B, C} \in Matrix A,B,CMatrix,以及整数 i , j , M , N \mathcal{i, j, M, N} i,j,M,N
*Matrix Create(int M, int N);返回一个 M × N \mathcal{M \times N} M×N的空矩阵;
*int GetMaxRow(Matrix A);返回矩阵A的总行数
*int GetMatCol(Matrix B);返回矩阵A的总列数
*ElemenType GetEntry(Matrix A, int i, int j);返回矩阵A的第i行,第j列的元素
*Matrix Add(Matrix A, Matrix B);如果A和B的行、列数一致,则返回矩阵C=A+B,否则返回错误标志
*Matrix Multiply(Matrix A, Matrix B);如果A的列数等于B的列数,则返回矩阵C=AB,否则返回错误标志
*…

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值