1 / 33

P 基础算法

P 基础算法. 阿默. 应该了解的基础知识. Pascal 基础:变量类型、表达式、常用系统函数 分支结构: if 、 case 循环结构:三种循环 for 、 while 、 repeat 数组、字符串 自定义函数、过程. 一、循环. 三种循环 while 语句 while 语句用于“当满足某一条件时进行循环”的情况。 while 语句的语法格式: while 布尔表达式  do    语句(复合); < 表达式为真就进入循环体,最实用灵活 >

cael
Télécharger la présentation

P 基础算法

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. P基础算法 阿默

  2. 应该了解的基础知识 • Pascal基础:变量类型、表达式、常用系统函数 • 分支结构:if 、case • 循环结构:三种循环for、while、repeat • 数组、字符串 • 自定义函数、过程

  3. 一、循环 • 三种循环 • while 语句while语句用于“当满足某一条件时进行循环”的情况。while语句的语法格式:while 布尔表达式 do   语句(复合); • <表达式为真就进入循环体,最实用灵活> • repeat语句repeat 语句用于“重复执行循环体,一直到指定的条件为真时结束”。语法格式为:repeat   语句1;……    语句n;until 布尔表达式; • <直到型、至少执行一次循环体,表达式为真退出循环> • for 语句用来描述已知重复次数的循环结构。for 语句有两种形式:(1) for 控制变量:=初值 to 终值 do 语句;(2) for 控制变量:=初值 downto 终值 do 语句; • <使用简单,但是变量必须是可数的>

  4. 循环应用 • 求1+2+。。+100 • 求 N! • 判断素数 • 打印花式图形 • ………… • ……

  5. 二、数组 • 为什么要使用数组 ? • 例1 输入50个学生的某门课程的成绩,打印出低于平均分的同学号数与成绩。 • 分析:在解决这个问题时,虽然可以通过读入一个数就累加一个数的办法来求学生的总分,进而求出平均分。但因为只有读入最后一个学生的分数以后才能求得平均分,且要打印出低于平均分的同学,故必须把50个学生的成绩都保留下来, 然后逐个和平均分比较,把高于平均分的成绩打印出来。如果,用简单变量a1,a2,…,a50存放这些数据,可想而知程序要很长且繁。

  6. 数组定义 var a,b,c:array[1..100] of integer; d:array[1..10,0..1] of real;

  7. 例1题解 Program ex; var tot,ave:real; a:array[1..50] of real; i:integer; begin tot:=0; {tot表示总分} for i:=1 to 50 do {循环读入每一个学生的成绩,并累加它到总分} begin read(a[i]); tot:=tot+a[i]; end; ave:=tot/50;{计算平均分} for i:=1 to 50 do if a[i]<ave then writeln(‘No.’,i,’ ‘,a[i]:5:2);{如果第i个同学成绩小于平均分,则将输出 } end.

  8. 算法 • 什么是算法? 算法是在有限步骤内求解某一问题所使用的一组定义明确的规则。通俗点说,就是计算机解题的过程。

  9. 算法的优化 • 一个问题可能有多种算法,当然在这些算法中也有优劣。 例:求1+2+..+100 一种算法:直接累加 另一种:高斯用很短的时间计算出了小学老师布置的任务:对自然数从1到100的求和。他所使用的方法是:对50对构造成和101的数列求和(1+100,2+99,3+98……),同时得到结果:5050。

  10. 算法的优化 • 同一种算法中,我们也可以考虑到问题的各种条件来对算法进行一定的优化。 • 例:100元一张 换成若干张10元、5元、2元、1元的零钱,要求每次都换成40张小钞票,每种至少1张。

  11. 程序1(为了便于了解程序工作效率,加入了一些统计变量)程序1(为了便于了解程序工作效率,加入了一些统计变量) var i,j,k,l,s:integer; c:longint; {用于统计最内部循环体执行的次数} begin s:=0;c:=0; for i:=1 to 40 do {10元的张数} for j:=1 to 40 do {5元的张数} for k:=1 to 40 do {2元的张数} for l:=1 to 40 do {1元的张数} begin c:=c+1; {统计循环执行次数} if (i+j+k+l=40) and (i*10+j*5+k*2+l=100) then begin {张数一共是40,并且总和是100元} {write('[',i,' ',j,' ',k,' ',l,']');} s:=s+1; {统计可行的方法} end; end; writeln(s);{显示换零方法总数} writeln(c);{显示内部执行总数} end. 程序运行结果: 34 2560000

  12. 程序2 • 当我们确定了i,j,k后,就直接可以确定l的值了l就是(40-i-j-k),而不需要再次进行循环。四重循环变成三重循环 var i,j,k,s:integer; c:longint; begin s:=0;c:=0; for i:=1 to 40 do for j:=1 to 40 do for k:=1 to 40 do begin c:=c+1; if (i+j+k<40) and (i*10+j*5+k*2+(40-i-j-k)=100) then begin {上述i,j,k之和一定要小于40 ,否则1元的张数就没有意义} {write(‘[’, i,' ',j,' ',k,' ',l,']');} s:=s+1; end; end; writeln(s); writeln(c); end. 程序运行结果: 34 64000

  13. 程序3 再来考虑一些边界值的量的问题,10元的最多取多少张?换100元最多10张,但是每种至少一张,所以最多取到7张。5元的也可以确定下来了,当然,2元的最多可取到37张。 var i,j,k,l,s:integer; c:longint; begin s:=0;c:=0; for i:=1 to 7 do {限定i,j,k的边界值} for j:=1 to 17 do for k:=1 to 37 do begin c:=c+1; if (i+j+k<40) and (i*10+j*5+k*2+(40-i-j-k)=100) then begin {write('[',i,' ',j,' ',k,' ',l,']');} s:=s+1; end; end; writeln(s); writeln(c); end. 程序运行结果: 34 4403

  14. 程序4还有可能继续优化么?举个例子:当i=3时,很显然j的取值最多只能到(100-3×10) div 5-2 张 var i,j,k,l,s:integer; c:longint; begin s:=0;c:=0; for i:=1 to 7 do for j:=1 to (100-i*10) div 5 - 2 do for k:=1 to (100-i*10-j*5) div 2 - 1 do begin c:=c+1; if (i+j+k<40) and (i*10+j*5+k*2+(40-i-j-k)=100) then begin {write('[',i,' ',j,' ',k,' ',l,']');} s:=s+1; end; end; writeln(s); writeln(c); end. 程序运行结果: 34 1190

  15. 程序运行结果: 34 2560000 程序运行结果: 34 64000 程序运行结果: 34 4403 程序运行结果: 34 1190

  16. 基础算法 • 判断一个数是否为素数 素数定义:除了1和本身之外,没有其它的约数。 思路:给出任意数N 分别用(1,N)之间的整除去除N,如果N被任意一个整除就说明N不是素数,否则就是素数 • 一级算法 flag=true; {假设N是素数,设立一个布尔型标志flag为true } for i:=2 to N-1 do if N mod i=0 then {如果N被i整除} flag:=false; {N的标志量置为false,表明N不是素数} writeln(flag); {输出标志量flag} 试除法!

  17. 算法优化 • 一级算法 flag=true; {假设N是素数,设立一个布尔型标志flag为true } for i:=2 to N-1 do if N mod i=0 then {如果N被i整除} begin flag:=false; {N的标志量置为false,表明N不是素数} break; end; writeln(flag); {输出标志量flag} 算法中,无论何种情况,哪怕N是偶数,循环体必须运行N-2次。 一次优化,利用break语句,一旦求余为0,则立即退出循环。 此时最差的情况下循环体才运行N-2次。

  18. 算法优化 • 二次优化 i的终值到sqrt(N)即可 flag=true; for i:=2 to trunc(sqrt(N)) do if N mod i=0 then begin flag:=false; break; end; writeln(flag); 此时最差的情况循环体循环trunc(sqrt(N))次。 能继续优化么?能,不过要以牺牲空间为代价

  19. 判断素数算法 var n:longint; begin readln(n); writeln(n,'-->',isprime(n)) ; end. • 将其设计成一个函数模块 program prime; function isprime(x:longint):boolean; var i:longint; flag:boolean; begin flag:=true; for i:=2 to round(sqrt(x)) do if x mod i=0 then begin flag:=false; break; end; isprime:=flag; end; 蓝色的自定义函数块,下次直接copy就可以用! 应用范围如: 1、找出<N的所有素数 2、证歌德巴赫猜想 ......

  20. 求素数——筛法 • 用筛法求出100以内的全部素数,并按每行五个数显示。 解:⑴ 把2到100的自然数放入a[2]到a[100]中(所放入的数与下标号相同); ⑵ 在数组元素中,以下标为序,按顺序找到未曾找过的最小素数minp,和它的位置p(即下标号); ⑶ 从p+1开始,把凡是能被minp整除的各元素值从a数组中划去(筛掉),也就是给该元素值置 0; ⑷ 让p=p+1,重复执行第②、③步骤,直到minp>Trunc(sqrt(N)) 为止; ⑸ 打印输出a数组中留下来、未被筛掉的各元素值,并按每行五个数显示。 用筛法求素数的过程示意如下(图中用下划线作删去标志) : ① 2 3 4 5 6 7 8 9 10 11 12 13 14 15…98 99 100 {置数} ② 2 3 4 5 6 7 8 9 10 11 12 13 14 15…98 99 100 {筛去被2整除的数 } ③ 2 3 4 5 6 7 8910 11 12 13 1415…9899100 {筛去被3整除的数 } 2 3 4 5 6 7 8910 11 12 13 1415…9899100 {筛去被5整除的数 } …………

  21. Pascal程序: Program Exam53;{下标表示数据} const N=100; type xx=1 .. N; {自定义子界类型xx(类型名)} Var a: array[xx] of boolean; i,j: integer; Begin Fillchar(a,sizeof(a),true); a[1] := False; for i:=2 to Trunc(sqrt(N)) do if a[i] then for j := 2 to N div I do a[i*j]:= False; t:=0; for i:=2 to N do if a[i] then Begin write(a[ i ]:5); inc(t); if t mod 5=0 then writeln end; readln End.

  22. 练习:请用试除法设计一个求2~100之间所有素数的程序练习:请用试除法设计一个求2~100之间所有素数的程序

  23. 基础算法:求最大公约数,最小公倍数 • 求a,b最大公约数:用辗转相除法: ① r ←a mod b ②如果 a mod b=0 转 ④ 否则转③ ③a←b,b←r ,r ←a mod b ,转② ④输出b

  24. 最大公约数 var a,b,r:integer; begin readln(a,b); r:=a mod b; while r <>0 do begin a:=b; b:=r; r:=a mod b; end; writeln(b); end. 请换种算法设计求最大公约数的程序

  25. 分解质因数 • var  n,k:longint;beginreadln(n);k:=2;write(n,‘=’);while n<>k do   begin    if n mod k=0 then       begin        write(k,‘*’);{输出 k* 格式,}        n:=n div k; {n的新值为n去掉其中一个因子k}      end    else      inc(k);{如果n不能被k整除,就把K往上递增。}  end;  writeln(k);{此处一个k为最后一个因子k,因为n=k 时,不满足条件,直接推出while循环,所以无法输出循环内k'*',所以在此处要输出最后一个因子}end.

  26. 排序算法——选择排序 选择排序 【示例算法描述】:初始关键字 [49 38 65 97 76 13 27 49]第一趟排序后 13 [38 65 97 76 49 27 49]第二趟排序后 13 27 [65 97 76 49 38 49]第三趟排序后 13 27 38 [97 76 49 65 49]第四趟排序后 13 27 38 49 [49 97 65 76]第五趟排序后 13 27 38 49 49 [97 65 76]第六趟排序后 13 27 38 49 49 65 [97 76]第七趟排序后 13 27 38 49 49 76 [97 76]最后排序结果 13 27 38 49 49 76 76 97

  27. var a:array[1..10] of integer; i,j,t,m:integer; begin randomize; for i:=1 to 10 do begin a[i]:=random(100);write(a[i],' ');end; writeln; for i:=1 to 9 do begin m:=i; for j :=i+1 to 10 do begin if a[m]>=a[j] then m:=j; end ; t:=a[i]; a[i]:=a[m]; a[m]:=t; end; for i:=1 to 10 do write(a[i],' '); writeln; end.

  28. 冒泡排序 • 冒泡排序的基本概念是:依次比较相邻的两个数,将大数放在前面,小数放在后面。 • 即首先比较第1个和第2个数,将大数放前,小数放后。然后比较第2个数和第3个数,将大数放前,小数放后,如此继续,直至比较最后两个数,将大数放前,小数放后,此时第一趟结束,在最后的数必是所有数中的最小数。重复以上过程,仍从第一对数开始比较(因为可能由于第2个数和第3个数的交换,使得第1个数不再大于第2个数),将大数放前,小数放后,一直比较到最小数前的一对相邻数,将大数放前,小数放后,第二趟结束,在倒数第二个数中得到一个新的最小数。如此下去,直至最终完成排序。

  29. var i,j,t:integer; a:array[1..10] of integer; begin randomize; for i:=1 to 10 do begin a[i]:=random(100);write(a[i],' '); end;writeln; for i:=1 to 9 do for j:=1 to 10-i do if a[j]>a[j+1] then begin t:=a[j]; a[j]:=a[j+1]; a[j+1]:=t; end; for i:=1 to 10 do write(a[i],' ') ; writeln; end.

  30. 顺序查找 • 在对线性表的操作中,经常需要查找某一个元素在线性表中的位置。此问题的输入是待查元素x和线性表L,输出为x在L中的位置或者x不在L中的信息。 L 76 x

  31. const MAXN=9; L:array[1..MAXN] of integer=(2,15,3,49,76,28,99,21,17); var i,x:integer; begin readln(x); i:=1; while i<=MAXN do {进行顺序查找} begin if x=L[i] then break; {如果找到就跳出循环} inc(i); end; if i>MAXN then {根据i的位置,来判断是否找到} writeln('Not found!') else writeln('x is L[',i,']'); end.

  32. min max mid min max mid min max 顺序查找 • 顺序查找法,对于有n个元素的线性表在最坏情况下需要n次比较。 • 下面我们考虑一种简单的情况。假设该线性表已经排好序了,我们是否有改进查找效率的可能呢? L mid x 71

  33. Const MAXN=9; L:array[1..MAXN] of integer=(2,3,17,29,36,38,59,71,97); var i,x,min,max,mid:integer; found:boolean; begin readln(x); min:=1;max:=MAXN;mid:=(min+max) div 2; while min<=max do begin if x=L[mid] then {如果找到,跳出循环} begin found:=true; break; end; if x>L[mid] then {如果x处于位置mid的右半边,那么把min提到mid+1的位置} min:=mid+1 else {如果x处于位置mid的左半边,那么把max提到mid-1的位置} max:=mid-1; mid:=(min +max) div 2;{计算中间mid位置} end; if found then writeln('x is L[',mid,']') else writeln('Not found!'); end.

More Related