问题求解与算法

Download Report

Transcript 问题求解与算法

程序设计语言基础
北京大学信息学院





问题求解与算法
程序设计语言与开发环境
C语言导引
数据结构初步
关于图形界面编程
主要内容
2015/4/13
北京大学
2
问题求解与算法

了解算法的基本概念

掌握描述算法的三种基本结构

学会算法的流程图描述

介绍几种基本算法

难、有意思、数学、编程的基础
主要内容
2015/4/13
北京大学
4

计算机是一个计算工具,它本身不能主动
帮助我们做任何事情,需要我们告诉它如
何进行计算。

程序设计就是要告诉计算机如何进行计算
的。这与我们中学时代的数学解题过程是
一样的,只不过描述的手段有所变化而已。
1 算法的基本概念
2015/4/13
北京大学
5


1984年图灵奖获得者瑞士科学家尼克劳斯·沃斯(Niklaus
Wirth,Pascal语言的发明者和结构化程序设计创始者)1976
年出版了《算法+数据结构 = 程序设计》一书,提出了著名
的公式:“程序 = 数据结构 + 算法” 。

程序:刻画现实世界,解决现实世界中的问题

程序设计语言:实现的工具

算法:问题的解的描述

数据结构:现实世界的数据模型
程序就是在数据的某些特定的表示方式和结构的基
础上对抽象算法的具体表述。
1 算法的基本概念
2015/4/13
北京大学
6

算法的定义


设计程序的目的是为了求解问题,为解决一个问题
所采取的方法和步骤,就称为“算法”
算法是一个由一组严格定义的动作组成的过程,给
定一个初始状态,这个过程能够结束在一个确定终
止状态。

大多数算法都可以用程序实现。

常用算法一般都被实现为算法库,供程序员调用。
1 算法的基本概念
2015/4/13
北京大学
7

算法的基本思想
如何把大象关在冰箱里?

分3步:

第一步:打开冰箱门;

第二步:把大象推进冰箱;

第三步:关上冰箱门;
一个实例:找出一组正整数中的最大的数
1 算法的基本概念
2015/4/13
北京大学
9

逐步求解,定义算法的动作

S1: 设Largest为第一个数

S2: 若第二个数比Largest大,则设Largest为第二个数

S3: 若第三个数比Largest大,则设Largest为第三个数

S4: 若第四个数比Largest大,则设Largest为第四个数

S5: 若第五个数比Largest大,则设Largest为第五个数
1 算法的基本概念
2015/4/13
北京大学
10

算法动作精化






S0: 设Largest为0,第一个数为当前数
S1: 若当前数比Largest大,则设Largest为当前数,并将
下一个数设为当前数
S2: 若当前数比Largest大,则设Largest为当前数,并将
下一个数设为当前数
S3: 若当前数比Largest大,则设Largest为当前数,并将
下一个数设为当前数
S4: 若当前数比Largest大,则设Largest为当前数,并将
下一个数设为当前数
S5: 若当前数比Largest大,则设Largest为当前数
1 算法的基本概念
2015/4/13
北京大学
11

算法规范化
从N个正整数中找出最大数的通用算法

循环结构

S0: 设Largest为0,当前位置p为0

S1: 若当前数比Largest大,则设Largest为当前数

S2: 若p比N小,则p增加1,并返回S1;否则返回Largest
1 算法的基本概念
2015/4/13
北京大学
12
算法的基本性质

通用性:即适用于某一类问题中的所有个体,而不只是用
来解决一个具体的问题。

有效性:即应有明确的步骤一步一步地引导计算的进行。

确定性:即每个步骤都是机械的、有明确定义的动作,不
需要计算者临时动脑筋。

有限性:对满足算法要求的输入数据,算法应在有限多步
内结束,并给出明确的计算结果。

离散性:算法的输入数据及输出数据都应是离散的符号。
1 算法的基本概念
2015/4/13
北京大学
13
算法的基本要求




正确
易维护(可读,易修改)
方便使用
高效




速度快 运行时间少,时间复杂度低
占用内存少,空间复杂度低
算法的效率可以测试,用大量输入数据测量运行的时间和占用
的内存,通过比较判别和选择效率高的算法。
更重要的是可以在编程前进行分析和估计(算法分析),即理
论的计算,给出事前的判断。
1 算法的基本概念
2015/4/13
北京大学
14

不了解施加于数据上的算法就无法决定如
何构造数据;反之,算法的结构和选择却
常常在很大程度上依赖于作为基础的数据
结构。简而言之,程序的构成(算法)
与数据结构是两个不可分割地联系在一
起的问题。
1 算法的基本概念
2015/4/13
北京大学
15


计算机科学家已经证明,只使用如下三种结构,
就可以描述任何算法,且算法结构优良

顺序结构(Sequence)

分支结构(Decision)

循环结构(Repetition)
每一种基本结构分别只有一个入口和一个出口
2 描述算法的三种基本结构
2015/4/13
北京大学
16

顺序结构:动作(语句)序列,
顺序执行,每个动作只执行一次,
各动作对执行结果产生的影响是
独立的
动作1
动作2
动作3





动作1
动作2
动作3
…
动作n
…
动作n
2.1 顺序结构
2015/4/13
北京大学
17

现实生活中的示例






按部就班
先来后到
循序渐进
接连不断








起床
刷牙
吃早饭
上课
吃中饭
午休
上课
吃晚饭
晚自习
洗漱
睡觉
2.1 顺序结构
2015/4/13
北京大学
18

分支结构:根据条件判
断执行什么动作(序列),
最多只有一个动作(序列)
是
被执行

如果 条件成立 则


动作(或动作序列)1
动作(序列)1
动作(序列)2
否则


条件成立?
否
动作(或动作序列) 2
分支结束
2.2 分支结构
2015/4/13
北京大学
19
现实生活中的示例



选择
二选一
条条道路通罗马

如果分数达到一本线


如果分数达到二本线


如果明天天晴


小明就去郊游
否则


就在家里看书
录取到三本大学
如果分数达到专科线


录取到二本大学
如果分数达到三本线


录取到一本大学
录取到专科学校
否则

落榜
2.2 分支结构
2015/4/13
北京大学
20

一个生活中的笑话



早上,妻子对正要上班出门的程序员丈夫说
:“晚上回来时买两个烧饼;如果看到卖西
瓜的,买一个。”
转眼到了下午下班,丈夫回到家把一个烧饼
放到桌上,妻子怒问:“为什么就买一个烧
饼?!”
丈夫答曰:“因为我看到了卖西瓜的…….”
2.2 分支结构
2015/4/13
北京大学
21

循环结构:重复执行
条件成立?
一系列动作
否
是

当 条件成立 做





动作1
动作1
动作2
…
动作n
…
动作n
循环结束处
2.3 循环结构
2015/4/13
北京大学
22
现实生活中的示例



周而复始
转圈
轮回

(第几周)如果小于20周

如果是周一到周五


否则


上课
休息
放寒假
2.3 循环结构
2015/4/13
北京大学
23
开始
一个循环结构示例:
求1~1000的平方和
S←0
j←1
S←S + j*j
j←j+1
j>1000
Yes
打印S
结束
No
三种基本控制结构可相互
组合和嵌套使用,形成更
为复杂的控制,完成各种
复杂的工作。

算法是让人来理解的,因此需要有效的
算法表示机制

自然语言表示法

伪代码表达法

流程图表示法
3 用流程图表示算法
2015/4/13
北京大学
25

流程图显示了程序的流程判断结构。通
常包含如下符号:

开始和结束

流程线

输入和输出

处理(动作)

条件判断
开始/结束
输入/输出
流程线
处理(动作)
条件判断
3 用流程图表示算法
2015/4/13
北京大学
26

判断
Yes
x>0
y=x
No
y = -x
3 用流程图表示算法
2015/4/13
北京大学
27

循环
k=0
k<10
No
Yes
动作
k=k+1
动作
3 用流程图表示算法
2015/4/13
北京大学
28
口诀:轻轻提, 慢慢移, 先开窗, 再喝
汤。
理解算法结构

顺序很重要:
将包子从蒸笼中轻轻提起,and then
2.
将包子慢慢移动到面前的小碟子中,and
then
3.
在包子的正上方咬开一个小口,and then
4.
通过小口吸食包子里的汤(当心别烫着),
and then
5.
将包子送入口中。
完成!
1.
吃一只蟹黄汤包的“算法”
假如我们认为在步骤4和5执行前要确保前面的结果是正
确的,可以在相应的地方设个“监视哨” –
“guard”。
理解算法结构
理解算法结构
假如规定吃8只:
开始
注意:
计数器的初始值
设一个计数器,
并将其值设定为0。
吃一只汤包
计数器值加1,并
判断其是否为8
否
是
结束
策略一:控制数量
是否已饱?
是
否
策略二:吃饱为止
开始
否
要吃汤包的
人不到5岁吗?
选用策略2
是
选用策略1
结束
有人知道饱不饱,但有人不知道!
开始
是
要吃汤包的
人不到5岁吗?
否
要吃汤包的人
不到60岁吗?
否
参数设为2
是
参数设为4
参数设为8
选用策略1(带参数)
结束
分类定量控制

判断闰年


能被4整除且不能被100整除;
能被400整除
3 用流程图表示算法
2015/4/13
北京大学
37
用C语言实现算法

判断闰年


能被4整除且不能被100整除;
能被400整除
3 流程图表示算法
2015/4/13
北京大学
38


问题:给定年月日,判断该日是这年的
第几天。
求解



按月累加天数
区分大、小月
区分闰年、平年
4.1基本算法 – 日期判断
2015/4/13
北京大学
39
开始
输入:year, month, day
初始化:total=0, i=1
N
Y
i < month?
Y
i是大月?
Y
total = total + 31
N
N
i是小月?
total = total + 30
year是闰年?
total = total + 29
i = i+1
total = total + day
输出:total
结束
total = total + 28
int year, month, day, total, i;
scanf(“%d%d%d”, &year, &month, &day);
total = 0;
for( i=1; i<month; i++)
{
if ( i ==1 || i==3 || i==5 || i==7 || i==8 || i==10 || i==12)
{
total = total +31;
}
if ( i ==4 || i==6 || i==9 || i==11)
{
total = total +30;
}
if ( i ==2)
{
if( (year%4==0&&year%100!=0) || year%400==0 )
total = total +29;
else total = total +28;
}
}
total = total + day;
4.1基本算法 – 日期判断(C语言实现)
2015/4/13
北京大学
41
开始

求一个数的平方根: x = a

迭代公式
x1 = 1
xn+1 = (xn + a/xn)/2
输入数a
初始化:x2=1
x1 = x2
迭代计算,直到 xn+1 – xn 的绝对
值小于误差要求,例如小于
0.00001,即保留小数点后5位。
x2 = (x1 + a/x1)/2
x2-x1的绝对值
小于0.00001?
N
Y
输出x2
结束
4.1基本算法 - 求平方根
2015/4/13
北京大学
42
4.1基本算法 - 求平方根(C语言实现)
2015/4/13
北京大学
43

问题:判定一个数是否为素数

求解

除2之外,偶数都不是素数

对于一个奇数P,看它是否能被某个大于1,小于P的
奇数整除,如果存在,则P不是素数,否则P就是素数
4.1基本算法 – 素数判定 与
歌德巴赫猜想
2015/4/13
北京大学
44
开始
输入:p
初始化:isPrime = ture, i = 3
p能否被2整除?
Y
N
P等于2吗?
Y
half = p
N
isPrime = false
Y
i < half ?
Y
p能否被i整除?
isPrime = false
输出isPrime
结束
N
half = p/2
half = sqrt(p)
N
i = i+2
int isPrimeNumber(int p)
{
int i, half, isPrime=1;
if ( p % 2 == 0 ) {
if ( p == 2 ) {
return isPrime;
}
isPrime = 0;
return isPrime;
}
half = p; // half = p / 2;
for( i = 3; i <= half; i = i+2 ) {
if( p % i == 0 ) {
isPrime = 0;
break;
}
}
return isPrime;
}
4.1基本算法 – 素数判定 与
歌德巴赫猜想
2015/4/13
北京大学
46

歌德巴赫猜想:任何大于6的偶数都能分成两个奇
素数之和

问题分析

对一个偶数N,把它分解成两个奇数的和

分别验证这两个数是否为素数,如果都是,则N满足歌
德巴赫猜想
4.1基本算法 – 素数判定 与
歌德巴赫猜想
2015/4/13
北京大学
47
开始
输入:n
初始化:i = 3
half = n/2
N
i <= half ?
Y
Y
i和n-i是否都为素数 ?
输出:n为素数i和
n-i 之和
N
i = i+2
结束
4.1基本算法 – 素数判定 与
歌德巴赫猜想

判断一个偶数是否满足歌德巴赫猜想
void GoldbachConjecture(int n)
{
int half = n/2;
int i;
int isPrime1, isPrime2;
// 求出半数n/2待用
// 循环变量
// 临时变量
for( i = 3; i <= half; i = i + 2 )
{
isPrime1 = isPrimeNumber(i);
isPrime2 = isPrimeNumber(n-i);
if( isPrime1 && isPrime2 )
{
printf("%d = %d + %d\n", n, i, n-i);
break;
}
}
}
4.1基本算法 – 素数判定 与
歌德巴赫猜想
2015/4/13
北京大学
49

排序(Sort)是指对一些数据的重新组织,使得
数据由大到小(降序)或者由小到大(升序)存
储。排序是很一种基本的要求。我们所感兴趣的
是如何寻找到一个好(计算速度快或占用内存少)
的办法来进行排序。

选择排序

冒泡排序
4.2基本算法 – 排序
2015/4/13
北京大学
50

选择排序,Selection sort


选身高,第一第二。。。==从余下的选最高
数据列表被分为两个子列表:已排序和未排序。
找到未排序列表中值最小(或最大)的元素,
并把它和未排序列表中的第一个元素进行交换。
4.2排序——选择排序
2015/4/13
北京大学
51
4.2 选择排序——示例(续)
2015/4/13
北京大学
52
4.2 选择排序——示例
2015/4/13
北京大学
53
开始
初始化:wall=0
/*先假设A[i]是最小的*/
N
是否还有
未排序元素?
Y
找到未排序列表
中的最小元素
与未排序列表中
第一个元素交换
wall = wall+1
结束
4.2 选择排序——算法、程序
2015/4/13
北京大学
54

冒泡排序,Bubble sort

数据列表被分为两个子列表:已排序和未排序。
未排序列表中最小(或最大)的元素通过冒泡的
形式(从后往前冒泡)从未排序列表中交换到已
排序列表中。
4.2 排序——冒泡排序
2015/4/13
北京大学
55
比较
比较并交换
冒
泡
的
过
程
4.2 冒泡排序——示例
2015/4/13
北京大学
56
4.2 冒泡排序——示例(续)
2015/4/13
北京大学
57
4.2 冒泡排序——示例(续)
2015/4/13
北京大学
58
开始
初始化:wall=0
N
还有未排序的数?
N
Y
还有未冒泡的数?
Y
Y
比较相邻数
N
交换相邻数
结束
4.2 冒泡排序——算法、程序
2015/4/13
北京大学
59

演示:排序舞
4.2基本算法 – 排序
2015/4/13
北京大学
60

各种排序方法简介:就地排序算法(不增加新的存储空间)
1、插入排序法(Insert Sort)
将一个数插入到序列中的合适位置。
2、选择排序法(Selection Sort)
每次把最小(大)的元素交换到最前面。
3、冒泡排序法(Bubble Sort
比较并交换相邻的元素,直到所有元素都被放到合适的位置。
4、堆排序(Heap Sort)
一种效率非常高,但原理较复杂的排序方法。
5、快速排序算法(Quick Sort)
一种通常情况下效率非常高,但原理较复杂的排序
4.2基本算法 – 排序
2015/4/13
北京大学
61


搜索(Search)是利用给出的关键值,在一个数据集合或
数据序列中找出与关键值匹配的一个或一组数据的过程。
顺序查找:最简单的查找算法。


从数据序列的第一个数据开始,逐个与关键值比较,直到找到一个
或所有的匹配数据为止(也可能找不到)。顺序查找不要求待查找
的数据序列已经排好序。但当待查找数据序列中数据比较多时,顺
序查找的效率将十分低。
二分查找:二分查找可以提高查找效率,但要求待查找的
数据序列已经排好序。

以序列中间数据为界将待查找的数据序列分成两个子序列,比较匹
配关键值与中间数据的大小,再确定去哪个子序列中继续查找。这
样逐步缩小范围,直到找到所需数据。
4.3基本算法 – 搜索
2015/4/13
北京大学
62

二分法搜索,
Binary search
A
1
3
6 12 24 32 35 41 43 45 51 53 56 75 88 91
0
7
15
45>41
(0+15)/2
(0+16)/2
找一个数在给定已 A
排序列表中的位置。
例如在A中查找45
A
的位置。
1
3
6 12 24 32 35 41 43 45 51 53 56 75 88 91
8
11
45<53
15
(8+15)/2
1
3
6 12 24 32 35 41 43 45 51 53 56 75 88 91
8
9 10
(8+10)/2
45=45
4.3基本算法 – 二分法搜索
2015/4/13
北京大学
63

迭代(iterative)与递归(recursive)
n=1
n>1
n=1
n>1
4.4 基本算法 – 迭代与递归
2015/4/13
北京大学
64
一个关于递归的故事
一个没有去过北京的人问:天安门是什么样
子?去过北京的人答道:天安门有个城楼,
城楼上有个国徽,国徽里有个天安门,天安
门有个城楼,城楼上有个国徽,国徽里有个
天安门, ……
4.4 基本算法 – 迭代与递归
2015/4/13
北京大学
65


算法的概念
描述算法的三种基本结构


算法的流程图表示与算法的程序实现


顺序结构、分支结构、循环结构
闰年判断
基本算法介绍




迭代计算:求平方根
排序:选择排序、冒泡排序
二分查找
迭代与递归
小结
2015/4/13
北京大学
66
书面作业

用程序流程图描述以下算法:
1.
输入正整数n,输出n!
2.
输入大于0的整数n,输出裴波那契数列 的第n个数值
裴波那契数列的定义为:
F(0)=0; F(1)=1;F(n)=F(n-1)+F(n-2)

交作业的方式为将答案写在word文件中,作为邮件的附件发给本
班辅导老师。

2周内交(11.10号前交,普通班助教)
2015/4/13
北京大学
67