数据结构与算法C++-引论

在这里插入图片描述

数据模型

数值问题:数学方程
对于数值计算问题的解决方法,主要是用数学方程建立数学模型,例如

  • 天气预报的数学模型为二阶椭圆偏微分方程
  • 预测人口增长的数学模型为常微分方程

非数值问题:表、树、图等数据结构

数据结构从逻辑上分为四类:

  1. 集合:数据元素之间没有关系
  2. 线性结构:数据元素之间是一对一的线性关系
  3. 树结构:数据元素之间是一对多的层次关系
  4. 图结构:数据元素之间是多对多的任意关系

线性关系:线性结构
非线性关系:树结构和图结构


什么是数据结构呢?
什么是数据?什么是数据元素?
什么是结构?关系指的是什么?

数据(Data)

-

数据:所有能输入到计算机中并能被程序识别和处理的符号集合。
数据包含:
数值数据:整数、实数等
非数值数据:图形、图象、声音、文字等
数据元素(Data Element):是组成数据的基本单位,是数据集合的个体,在计算机中通常作为一个整体进行考虑和处理
数据项:构成数据元素的最小单位
在这里插入图片描述

-

  • 数据对象(Data Object):数据对象是性质相同的数据元素的集合,是数据的一个子集。
  • 数据结构(Data Structure):是指相互之间存在一种或多种特定关系的数据元素 集合,是带有结构的数据元素的集合,它指的是数据元素之间的相互关系,即数据的组织形式。
    数据的逻辑结构:数据元素之间逻辑关系的整体,如:树结构、 图结构、 集合结构。
    在这里插入图片描述

数据的存储(物理)结构:数据及其逻辑结构(数据元素、逻辑关系)在计算机(内存)中的表示

  1. 顺序存储结构:用一组连续的存储单元依次存储数据元素,数据元素之间的逻辑关系由元素的存储位置表示
  2. 链接存储结构:用一组任意的存储单元存储数据元素,数据元素之间的逻辑关系用指针来表示

数据的逻辑结构用户视图,面向问题->数据本身的构成方式
数据的存储结构实现视图,面向计算机->数据在内存的存储表示
在这里插入图片描述

-

数据类型(Data Type):数据类型是一组性质相同的值集合以及定义在这个值集合上的一组操作的总称。
原子类型:其值不可分解。如C语言中的标准类型(整型、实型、字符型)。
结构类型:其值是由若干成分按某种结构组成的,因此是可以分解的,并且它的成分可以是非结构的,也可以是结构的。

-

抽象数据类型(Abstract Data Type):指基于一类逻辑结构的数据类型以及定义在这个类型之上的一组操作。如:整数类型
抽象数据类型不考虑数据项,把具体的数据类型抽象掉了
抽象数据类型只考虑数据的逻辑结构和基本操作
ADT有两个重要特征:

  1. 数据抽象:用ADT描述程序处理的实体时,强调的是其本质的特征、其所能完成的功能以及它和外部用户的接口(即外界使用它的方法)。
  2. 数据封装:将实体的外部特性和其内部实现细节分离,并且对外部用户隐藏其内部实现细节。
    在这里插入图片描述

实现的三种方法:

  1. 传统的面向过程的程序设计
  2. “包”、“模型”的设计方法
  3. 面向对象的程序设计(Object Oriented Programming,简称00P)
    在这里插入图片描述

在这里插入图片描述
算法 + 数据结构 = 程序
Algorithm + Data Structures = Programs

算法

算法的要求

(1)有穷性:总是在执行有穷步之后结束,且每一步都在有穷时间内完成
(2)确定性:每一条指令必须有确切的含义,相同的输入得到相同的输出
(3)可行性:操作步骤可以通过已经实现的基本操作执行有限次来实现

好算法应有的特性

(1)正确性:算法能满足具体问题的需求,即对于任何合法的输入,算法都会得出正确的结果。
(2)健壮性:算法对非法输入的抵抗能力,即对于错误的输入,算法应能识别并做出处理,而不是产生错误动作或陷入瘫痪。
(3)可理解性:算法容易理解和实现。
(4)抽象分级:用合适的抽象分级来组织表达算法的思想,启发式规则7±2。
(5)高效性:具有较短的执行时间并占用较少的辅助空间。

算法的选择

1.【算法一自然语言描述】

设两个自然数为m和n,欧几里德算法如下:
步骤1:将m除以n得到余数r;
步骤2:若r等于0,则为最大公约数,算法结束;否则执行步骤3;
步骤3:将n的值放在m中,将r的值放在n中,重新执行步骤1:
优点:容易理解;
缺点:冗长、二义性
使用方法:粗线条描述算法思想;注意事项:避免写成自然段

2. 【算法一流程图描述】

设两个自然数为m和n,算法为
在这里插入图片描述

优点:流程直观
缺点:缺少严密性、灵活性
使用方法:描述简单算法
注意事项:注意抽象层次

3.【算法一程序语言描述】

设两个自然数为m和n,算法为
在这里插入图片描述

优点:能由计算机执行
缺点:抽象性差,对语言要求高
使用方法:算法需要验证
注意事项:将算法写成子函数

4. 伪代码

:介于自然语言和程序设计语言之间的方法,它采用某一程序设计语言的基本语法,操作指令可以结合自然语言来设计。
【算法一
伪代码描述】设两个自然数为m和n,算法为

输入:两个自然数m和n
输出:m和n的最大公约数
	1. r=m%n;
	2. 循环直到r等于0
		2.1 m=n;
		2.2 n=r;
		2.3 r=m%n;
	3. 输出n;

int CommonFactor(int m,int n)
{
	int r = m % n;
	while (r != 0){
		m = n, n = r;
		r = m % n;
	}
return n;
}
//只描述子函数;省略主函数和头函数

优点:表达能力强,抽象性强,容易理解,容易实现
使用方法:7±2
米勒原则:人类的短期记忆能力一般限于一次记忆5~9个对象

和算法执行时间相关的因素:

(1)算法选用的策略
(2)问题的规模
(3)编写程序的语言
(4)编译程序产生的机器代码的质量
(5)计算机执行指令的速度

通常有两种衡量算法效率的方法:

事后统计法(定量分析):将算法实现,测算其时间和空间开销
缺点:1.必须执行程序。2.其它因素掩盖算法本质
事前分析(定性分析):对算法所消耗资源(时间、空间)的一种估算方法

算法执行时间

定义:一个算法的执行时间大致上等于其所有语句执行时间的总和(基本语句的执行次数),对于语句的执行时间是指该条语句的执行次数和执行一次所需时间的乘积。
语句频度:是指该语句在一个算法中重复执行的次数。
在这里插入图片描述
for语句执行n+1次,for里的语句执行n次

算法的时间复杂度

即算法的时间量度
记做:T(n)=0(f(n))
例如:

(1)X=x+1;时间复杂度为0(1),称为常量阶;
(2)for(i=1;1<=n;i++)X=X+1;时间复杂度为0(n),称为线性阶;
(3)for(i=1;i<=n;i++)
	for(j=1;j<=n;j+)X=X+1;时间复杂度为0(n),称为平方阶。

在这里插入图片描述
在这里插入图片描述

算法的空间复杂度

作为算法所需存储空间的量度,记做:S(n)=0(f(n))
算法的存储量包括:
1.输入数据所占空间
2.程序本身所占空间
3.辅助变量所占空间

时间复杂度及应用
问题:编写程序实现用一元人民币换成一分、两分、五分的硬币共50枚。
分析:假设一分、两分、五分的硬币各为X,y,Z枚。则有:x+y+z=50,×+2y+5z=100
方法1.三重循环

#include <stdio.h>
main(){
	int i,j,k;
	for(i=0:i<=50:i++)
		for(j=0:j<=50:j+)
			for(k=0:k<=50:k++){
				if(i+j+k=50&&i+2j+5k=100)
				printf("%d,%d,%dn",i,j,k);
			};
}
# 循环次数为51 * 51 * 51       0()

方法2.两重循环

#include <stdio.h>
main(){
	int i,j,k;
	for(i=0;i<=50;i++)
		for(j-=0;j<=50;j++)
		{
			k=50-i-j;
			if(i+2*j+5*k==100)
			printf("d,%d,%d n",ij,k);
		}
}
# 循环次数为51*51     0()

方法3.两重循环

#include <stdio.h>
main(){
	int i,j,k;
	for(k=0;k<=20;k++)
		for(j==0;j<=50,j++)
		{
			i=50-j-k;
			if+2*j+5*k==100)
			printf("%d,%d,%dn",i,j,k);
		}
}
# 循环次数为21*51 0()

方法4.单重循环
x+y+Z=50
x+2y+5z=100
->y+4*Z=50

#include <stdio.h>
main()
{
	int i,j,k;
	for(k=0;k<13;k++)
	{
		j=50-4*k;
		i=50-j-k;
		printf("d,%d,%d n",i,j,k);
	}
}
# 循环次数为13  0(1)

本章重点

学会计算执行次数和时间复杂度

  • 计算下方程序的时间复杂度
for(i=1;i<=n;++i)
	for(j=1;j<=i-1;++j)
		++x;

执行次数为
(n∑ i=1) (i-1∑ j=1) 1
=(n∑ i=1) (i-1)
=n(n-1)/2

(i-1∑ j=1) 1=(1+1)(i-1-1+1)/2=i-1 首项加末项*项数/2

o(n²)


void fun (int n)
{
	int i,j,x=0;
	for(i=1;i<n;++i)
		for(j=i+1;j<=n;++j)
			++x;
}

执行次数为
((n-1)∑ i=1)(n∑ j=i+1) 1
=((n-1)∑ i=1) (n-i)
=n(n-1)/2

(n∑ j=i+1) 1 =(1+1)(n-i-1+1)/2=n-i

o(n²)


注:若k是O(n),则O(kn)=O(n^2)
要考虑第二层循环对第一层循环变量的影响

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值