plc编程常用算法

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

常用算法
基本概念:
1. 算法:就是解决问题方法的精确描述。

并不是所有问题都有算法,有些问题经研究
可行,则相应有算法;而有些问题不能说明可行,则表示没有相应算法。

算法具有以下性质:是一有穷动作的序列;
动作序列仅有一个初始动作;序列中每个动作的后继动作是确定
的;序列的终止表示问题得到解答或问题没有解答
2. 算法的分类:数值的和非数值的
数值的算法是以数学方式表示的问题求数值解的方法,女口:代数方程计算、矩阵计算、线性方程组求解、函数方程求解等;
非数值的算法是求非数值解的方法,如排序查找、模式匹配、排列模拟、表格处理、文字处理等。

3. 算法设计:主要是针对各类具体问题设计良好的算法及研究设计算法的规律和方
法。

4. 常用的算法设计方法:
数值算法:迭代法、递归法、插值法等;非数值算法:分治法、贪婪法、回溯法等。

5. 算法分析:是对设计出的每一个具体的算法,利用数学工具,讨论
各种复杂度。

算法的复杂度分时间复杂度和空间复杂度。

常用数值计算算法
1. 迭代法
迭代法适用于方程(或方程组)求解,是使用间接方法求方程近似根的一种常用算法。

(参见清华版《PASCAL程序设计P89练习4.23》
设方程f(x)=0 ,该方法将方程表示为等价形式:x=g(x),或一般地
将f(x)拆成两个函数f l、f2,即卩f(x)= f i(x)-f2(x) =0,因而有f i(x)=f2(x)。

其中f i(x)是这样一个函数,对于任意数C,容易求出f i(x)=c的精确度很高的实根。

迭代法求解算法如下:
(1) .首先选一个x的近似根X0,从X0出发,代入右面函数,并解
方程f1 (x)=f 2(x0)得到下一个近似根X1;
(2) .将上次近似根X1代入右面函数,并解方程f1(x)=f 2(x1),得到
又一个近似根X2
(3) .重复⑵的计算,得到一系列近似根X0,X1,X2,…,X i,X i+1 ,…,x n,…;
4. 插值法
也称为内插法。

在实际问题中出现的函数 f(x),往往只知道它在某 区间中若干点的函数值, 这时作出适当的特定函数, 使得在这些点上取 已知值,并且在这区间内其它各点上就用这特定函数所取的值作为函数
f(x)的近似值,这方法称为“插值法”。

如果这特定函数是多项式,就称 之为“插值
多项式”或“内插多项式” 。

(常见用于高等代数中的计算 ) 三 .
常用非数值计算算法
若方程有根,这数列收敛于方程的根,若满足 X n X n i
,则
认为X n 是方程的近似根。

例1:迭代计算n!、Fibonacci(斐波那契)数列 程序设计》P59-62例4.3,4.4)
(详见清华版《PASCAL 例2:计算sin(x) x 3
x
3! 5
x
5!
7
x 7!
直到最后一项的绝对
值小于10-7时停止计算, 程序设计》P72例4.11) 练习:清华版《PASCAL
由键盘输入。

(详见清华版《PASCAL
程序设计习题与选解》 P18习题4.23,4.38
2.递推法
递推法实际上是需要抽象为一种递推关系求解,
此方法通常表现为
两种方式: 方式一是从简单推到一般;
3.递归法
在数学中几个熟知的递归定义:
(1). n!
1
当n 0

(2).树结构:a)O 是树(空树);b)若t1和t2是树,则 是树。

O / \ t1 t2
例3:递归计算n!;(详见清华版《PASCAL 程序设计》P108例5.8) 例4 :第二届初中组一、6
第二届初中组一、7
提示:利用 y=((((A N X+A N -1 )X+A N -2)X+A N -3)+ ……+A 1)X+A 0 第七届初中组三、1
练习:计算 Fibonacci(斐波那契)数列
Fib。

Fib 1 Fib n
1
Fib n 1 Fib n 2 当n
1 时
方式二是将一个复杂问题逐步推到一个已知解的简单问题。

这两 种方式反映了两种不同的递推方向,前者往往用于计算级数,后者与 “回归”配合成为一种特殊的算法一一递归法。

1. 穷举搜索法
穷举所有可能情形,并从中找出符合要求的解。

最直观的是联系循环的算法。

例5:百钱买百鸡问题;第一届初中组3( 也可用累加法)
第七届初中组四、2 输出1-100 内的素数;验证哥德巴赫猜想(详见
清华版《PASCAL 程序设计》P82-86 例4.16,4.17)
例6 :找出n个自然数(1,2,3, ............ ,n)中r个数的组合
当n=5,r=3 时,约定前一个数应大于后一个数,
有: 543 542 541 532 531 521 432 431 421 321
可简单地用三重循环进行搜索,算法如下:
for i:=5 downto 1 do
for j:=5 downto 1 do
for k:=5 downto 1 do
if ((i<>j) and (i<>k) and (j<>k) and (i>j) and (j>k))
then writeln(i,j,k);
或者
for i:=5 downto 3 do
for j:=i-1 downto 3-1 do
for k:=j-1 downto 1 do
if ((i<>j) and (i<>k) and (j<>k) and (i>j) and (j>k))
then writeln(i,j,k);
2. 递归法
例如:在例6中,可首先固定第一位数(如5),其后是在另4个数中再“组合” 2个数。

这就将“ 5个数中3个数的组合”推到了“ 4 个数中2个数的组合”上去了。

第一位数可以是n^r(如5宀3), n个数中
r 个数组合递推为n-1 个数中r-1 个数的组合,这是一个递归的算法: procedure comb(n,r:integer);
var i,temp:integer;
begin
for i:=n downto r do
if ((i<>n) and (k<>r)
then begin temp:=1
while temp<=(k-r)*3 do {k 为过程外定义的} begin
write( ‘‘); temp:=temp+1
end;
end;
write(i);
if (I>1) then comb(i-1,r-1) { 递推到下一情形}
else writeln;
end;
例7:求m 与n 的最大公约数;汉诺塔游戏(Tower of Hanoi) ( 详见清华版《PASCAL 程序设计》P109-P112 例5.9,5.10)
例8:第六届初中组二、2 第五届高中组二、第五届初中组五
3. 回溯法
一种选优搜索法,按选优条件向前搜索,以达到目标。

但当搜索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足条件的某个状态的点称为“回溯点” 。

例如:在例6中将自然数排列在数组A 中:
A[1]A[2]A[3]
543
542
321
排数时从A[1] T A[2]t A[3] ,后一个至少比前一个数小1,并且应
满足「i+A[r i]>r这个关系。

若n+A[r i]< r就要回溯,该关系就是回溯条件。

为直观起见,当输出一组组合数后,若最后一位为1,也应作一
次回溯(若不回,便由上述回溯条件处理)。

算法如下:
procedure comb2(n,r,a[m]:integer);
var j,ri:integer;
begin
ri=1;a[1]=n;
repeat
if (ri<>r) { 没有搜索到底}
then if (ri+a[ri]>r) { 是否回溯}
then begin
a[ri+1]:=a[ri]+1;ri:=ri+1
end;
else begin
ri:=ri-1; a[ri]:=a[ri]-1 { 回溯}
end;
else begin
for j:=1 to r do write(a[j]);
writel n;
if (a[r]=1) {是否回溯}
then begi n
ri:=ri-1; a[ri]:=a[ri]-1 {回溯}
en d;
else a[ri]:=a[ri]-1 en d;
un til (a[1]<>r-1)
en d;
例9:八皇后问题(详见清华版《PASCAL程序设计》P165)
练习:清华版《PASCAL程序设计》P172习题7.19跳马问题和7.20 迷宫问题、四色问题
例10:第三届初中组二、3
4. 贪婪法
一种可以快速得到满意解(但不一定是最优解)的方法。

方法的“贪
婪”性反映在对当前情况,总是作最大限度的选择。

即满足条件的均
选入,然后分别展开,最后选得一个问题解。

这方法不考虑回溯,也不考虑某次选择并不符合最优条件,但最终能得到最优结果的选择。

例11:用贪婪法求解“货郎担问题”。

所谓货郎担问题是指,给定一个无向图,并已知各边的权,在这样的图中,要找一个闭合
回路,使回路经过图中的每一个点,而且回路各边的权
e 之和为最小,如右图所示。


a,b,c,d,e,f 这6 个点,坐标分别为(0,0)、(4,3)、
(1,7)、(15,7)、(15,4)、(18,0),这是最优解。

(算法程序略)求解步骤一般如下:
(1).计算各点间距离(邻接矩阵);
(2).距离关系表排序;
(3).贪婪法选择边,入选的边应符合如下两条件:每个端点不能联系两条以上的边;不会使入选的边形成回路,除非入选正好是边数等
于端点数。

为此引入端点关系表
(4).如果由⑶得不到解,应调整距离关系表中距离相同的边的次序,再试;
(5).若有解,则按端点关系表给出回路的轨迹。

例12:旅行路线选择。

设有n个城市(或景点),今从某市出发遍历各城市,使之旅费最少(即找出一条旅费最少的路径)。

例13 :背包问题。

从n件不同价值、不同重量的物品中选取一部
分,在不超过规定重量的原则下,使该部分价值最大。

例 14 :第三届初中组一、 8; 第七届高中组四、 2
5. 分治法
是应用十分广泛的一种算法设计方法, 其基本思想是把一个规模为 n 的问题
分成若干个规模较小的问题,使得从这些较小问题的解易于 构造出整个问题的解。

例 15 :找一个集合的极大元和极小元。

集合 S 含有 n 个元素,其 中
n=2k (k > 1)。

算法思路如下:
procedure MAXIM(S); begin
1. if ||S||=2 {集合 S 的元素个数为 2} then begin
2. 设 S={a,b};
3.
return (MAX(a,b),MIN(a,b)) end
else begin
4. 把S 分为两个子集S i 和S 2,各有一半元素;
5. (max1,min1) — MAXMIN(S i );
6. (max2,min2) — MAXMIN(S 2);
7. return (MAX(max1,max2),MIN(min1,min2)) end
end;
注意到,需要在集合 S 的元素间进行比较的步骤只是步骤 3(在此 比较两个元素 )及步骤 7(在此把 max1 与 max2 及 min1 与 min2 进行比 较),设T(n)是用
MAXMIN 在一个具有n 个元素的集合中找极大元和 极小元时,需要在 S 的元素
间进行比较的次数。

显然, T(2)=1 ,如果 n>2,则T(n)是在大小为n/2的集合上两次调用 MAXMIN(第5、6步 所需的比较次数加上第 7 步的两次比较所得的总次数, 即
元素间进行比较的次数来说,这种算法是最优的。

例16:设有n 个选手的循环比赛(n=2m ),要求每名选手要与其他 n-1 名选手都赛一次。

每名选手每天比赛一次,循环赛共进行 n-1 天, 要求每天没有选手轮空。

例如
m=3,见下表,用分治法将(2m *2m )矩阵
AB
分成四块,每块是(2m-1*2 m-1)的矩阵,它应是对称的(
),再对A
BA
T(n)
1 当 n
2 2T(n/2)
2 当n 2
经递推 T(n)=3n/2-2 ,对于在集合 S 的
与B 均是(2m-1*2m-1)的矩阵分成四块,直至(2*2)的矩阵定出每个元素 的值,再按对称关系构造出比赛表。

算法程序略。

选 手
、送 第一 天
第二

第三 天
第四 天
第五 天
第六 天
第七 天
1
2 3 4 5 6 7 8 2 1
4 3 6
5 8 7 3 4 1 2 7 8 5
6 4 3 2 1 8
7 6 5 5 6 7
8 1 2 3 4 6 5 8 7 2 1 4 3 7
8 5 6 3 4 1 2 8
7
6
5
4
3
2
1
四•排序
1.插入排序
设待排序的记录为
(R I ,R 2,…,R n ),插入排序的基本思想是把记录
R i (2< i < n)插入到一列已排好序的记录
R I ,R 2,…,R i-i (1w i < n)中,使
得长度为I 的一系列记录也是排好序的。

(1) .直接插入排序
若记录R I ,R 2,…,R i-i 已按关键码有 序,即对应的关键码有
K G K 2«Y
K i-i ,将K 与K i-i ,K i-2,…,K I 依次比较, 一旦K i 大于或等于某个 K j ( K j w
i-1
)时,把 R j+1, R j+2,…,R i-1 后移一一 个位
置,并将R j 插在第j+1个位置上。

在直接插入排序中,若待排序的记录已有序,总共比较
C = n-1
次。

直接插入排序可用顺序存储和链接存储。

囲乳2链接存储的直接捕人排序
例17:清华版《PASCAL 程序设计》P171习题7.8 (2)
.二分法插入排序
在直接插入算法中,确定 R i (i=2,…,n )插入位置的方法是将它
次;若记录是完全反序的, 则比较C = 2 + 3+…+ n =
-a
图4.1直接樋人推序
key wxt
head
till
' -------------- v" -------------- '
已援瓷赞码有萍
与前面i-1个记录依次比较,由于前i-1个记录已按关键码有序,
可以用二分法较快地找到R i的插入点。

首先取m 1 i 1
2
比较R m与R i的关键码。

若R i的关键码小于R m的关键码,则在
[R1,R2,…,R m-l]范围内再用二分法,否则在[Rm+1,…,R n]范围内再用二分
法。

如此反复,直至最后找到R i的插入位置。

当n较大时,二分法插入排序比较次数比直接插入排序的最多比较次数丄」少得多,但比直接插入排序的最少比较次数
2
(n-1)大。

二分法插入排序只能采用顺序存储。

2. 选择排序
又称为直接选择排序。

在待排序的n个记录中先选出关键码最大的记录,将它送到第n个位置上,然后再从其余n-1个记录中选出关键
码最大的记录送到第n-1个位置上,…,直至选择了n-1个记录。

选择排序比较次数共有 C = (n-1)+…+2=n(n-1)/2 (详见清华版
《PASCAL程序设计》P145-147)
3. 冒泡排序
这种排序方法从表的一端开始,依次比较相邻两个记录的关键码
R[i].key 和R[I = 1].key,若R[i].key > R[l+1].key,则交换R[i]和R[i+1]。

假设从表的左端开始,当i从0到n-2对表扫描一趟后,具有最大关
键码的记录将被移到最右边的位置上。

作n-1趟扫描将完成对n个记录的排序,但完成n个记录的排序不一定都要进行n-1趟扫描,如果在某趟扫描中没有发生交换,则排序工作已完成,此后的扫描便不必进行。

如果待排序的诸记录在排序前已按关键码排好序,贝U用冒泡排序算法只需一趟扫描便完成排序,比较次数为C= n-1。

如果待排序的记录完全反序,即已由大至小排序,则比较次数C= n(n-1)/2 (详见清华版《PASCAL程序设计》P148-150)
4. 希尔排序
在直接插入排序和冒泡排序中,只比较相邻的记录,一次比较至多
将记录移动一个位置。

希尔排序是对此两种排序的推广。

算法先将记录按某个增量d分成若干组,每组中记录的下标相差d。

对每组中的
记录用某种方法(前两种)进行排序,然后再用一个较小的增量对记录进行分组,在每组中再进行排序,…,当增量减至1时,整个记录
被分成一组,排序完成。

例如:设待排序的记录的关键码为:
94 32 40 90 99 80 46 21 69 28 64 73 85 54
取增量序列为:5, 3, 1,当增量d=5时,整个记录被分成五组:
擁纽中的元累分别为匕
第一组194*90*64
第二组戲・46占3
翳三组r40t2US5
第四组;90,仙,54
第五组*9,48 各组摆呼后”结集为:
若d=3血牛记录被分就三组倍组排序后的结果孙_
T—}—r I—I—I nn f~1 t I
4: 26 21 54 12 抽M 須73 85 90 肌畀94
再取增量为1,排序结果为:21 28 32 40 46 54 64 69 73 80 85 90 94 99
5. 快速排序
选取表中某个记录的关键码K作为基准,将表划分成左、右两个子表:左子表中各记录的关键码都小于等于K,右子表中各记录的关键码都大于等于K,然后用同样的方法递归地处理这两个子表。

比较次数C(1)=0,C(2)=2+C(1)=2,C(3)=3+C(2)=5,…,
C( n)=n+C( n-1)=( n+2)( n-1)/2
170 +
&03
061
512 908
0«7 Z75
653 4Z6
B12
765

i 170
503 1 X.
061 512 908
0B7
275 esa
426
612
J
703
j
j
503
170 IM 061
512 908
OS 7
275
6&3 426 «12 ?65 703
170
商 061
T *
r
0B7 j
512

503 «12 765 703
[170
061
375 C$7
][S08 512 653 426
S03 612 765 70S]
ffi A-3快議排序的划井过稈
上图说明了 13个记录的表进行第 1次划分的过程。

取表的中间一 个记录的关键码275作为基准,划分时用两个指针变量
i 和j 扫描表,
变量i 从表头向右扫描,直至遇到一个关键码大于或等于基准的记录; 变量j 从表尾向左扫描,直至遇到一个关键码小于或等于基准的记录; 接着交换R i 和R j 。

指针i 和j 继续向两端前进,进行比较、交换。

当 i 和j 交叉(即i 处于j 的右边)时,表中各记录都与基准比较过,表 被分成左、右两部分,左边各记录的关键码小于或等于右边各记录的 关键码。

6. 堆排序
是对选择排序的改进。

为了避免在选择排序中出现的每趟选择最大 关键码的记录时的某些重复的比较,可以采用树形选择方法。

设待排
记录的关键码)都大于或等于它的子女结点的值,因此堆的根在树中 具有最大的关键码。

这样得到的序列将是非递减的。

7. 归并排序
是把两个或两个以上已排好序的表组合在一起, 产生一个新的排好
序的表。

方法如下:
(1).若两个表有一个为空,则无须归并
序的n 个记录的关键码为 K i ,K 2,… K n-1
:K n ,然后用同样的方法比较每 对中的
较小者,直至找出最小的关 键码。

另一种改进的堆排序方法是, 将待排
序的n 个记录(R 1,R 2,…,R n ) 看成是有n 个结点的一棵完全二 叉树,树中结点满足下列条件:

何一个非叶结点的值(这个结点上
,K n ,先两两比较 K 1:K 2, K 3:K 4,…
闺氛7含有12牛元當的堆
A A 严"
IB 27 68 3€ JO
(2) .若两个表都非空,则比较 p 和q (两个表的头指针)所指结点
的关键码,将较小者插入第三个表中,并前进相应的指针。

重复这一
步;
(3) . 若有一个表先到达表尾,则把另一个表的剩余部分插入到第
三个表中。

例 18:第五届初中组五
8. 各种排序方法的比较
直接插入排序在记录数目较少且是基本有序时是最佳的; 选择排序是比较次数不依赖记录的初始排列,且记录移动较少; 冒泡排序的性能较差; 希尔排序是对插入排序和冒泡排序的推广, 在记录移动时可能消 去多个反
序,算法时间可能较短; 快速排序是目前所有排序中平均性能最好的方
法, 但在最坏情况 下年耗时间最多; 堆排序在 n 较大时非常有效; 归并排序可以看成是插入排序的扩充。

例 19:第六届初中组 1、 10
9. 其它排序方法
例 20:第七届初中组四、 1
五 . 查找
查找又称为检索, 它往往是程序中最耗费时间的操作, 使用何种存储 结构和查找算法对程序的性能有本质的差别, 因此, 在讨论各种查找算法 时都应指明所用的存储结构。

{定义记录类型} {值为关键字的域} { 记录的其它域 }
END; sqlist=ARRAY[0..n] OF element;
1. 顺序查找 又称为线性查找, 对给定的关键码值 K ,从表的一端开始, 依次检 查表中每个记录的关键码,直至找到所需灌到达表的另一端。

FUNCTION seqsrch(r:sqlist;K:keytype):integer;
Begin r[0].key:=K; i:=n; while r[I].key<>K do i:=i-1 return(i)
end;
TYPE element=RECORD
key: keytype
recs: rectype
{K为给定值,函数seqsrch值为关键码等于K的记录在表r中的序号,值为零时表明查找不成功}
(参考清华版《PASCAL程序设计习题与选解》P35习题7.23)
2. 二分查找
又称为折半查找。

当表中记录按关键码有序时(有序表),可以采用二分查找法。

先确定待查记录的范围(区间),然后逐步缩小范围直
到找到或找不到该记录为止。

用两个指针low和hig分别指示待查元
素所在范围的下界和上界,并用指针mid指示中间元素
low hig
mid 。

在开始进行查找时,low和hig的初值分别指向
2
第1个和第n个元素。

FUNCTION bin srch(r:sqlist;K:keytype):i nteger;
Begin
low:=1; hig:=n;
while low<=hig do {判别区间大小}
begin
mid: =(low+hig ) div 2;
case
k>r[mid].key: low:=mid+1;
k=r[mid].key: return(mid); {查找成功}
k<r[mid].key: hig:=mid-1
end; return(O)
en d;
(参考清华版《PASCAL程序设计习题与选解》P35习题7.24)例21:第七届初中组一、19;第六届初中组一、14
3. 分块查找
又称为索引顺序查找,是顺序查找的改进方法。

是把表分成若干块,
每块中记录的存储顺序是任意的,但块与块之间必须按关键码有序,
即第一块中任一记录的关键码都小于第二块中各记录的关键码,如此类推。

这种查找方法要求除表本身外,尚需建
立一个索引表,索引表中的一项对应
于表的一块,它含有这一块中的最大
关键码的指向块内第一个记录位置的
指针,索引表中各项按关键码有序。

分块查找的过程分两步进行:先查找
索引表(可以用上述两种方法)确定
要找的记录在哪一块;然后再在相应
的块中查找。

4.14并块杳掳的减段累引。

相关文档
最新文档