算法排序.docx

上传人:b****7 文档编号:8865095 上传时间:2023-02-02 格式:DOCX 页数:41 大小:42.50KB
下载 相关 举报
算法排序.docx_第1页
第1页 / 共41页
算法排序.docx_第2页
第2页 / 共41页
算法排序.docx_第3页
第3页 / 共41页
算法排序.docx_第4页
第4页 / 共41页
算法排序.docx_第5页
第5页 / 共41页
点击查看更多>>
下载资源
资源描述

算法排序.docx

《算法排序.docx》由会员分享,可在线阅读,更多相关《算法排序.docx(41页珍藏版)》请在冰豆网上搜索。

算法排序.docx

算法排序

12.3高精度计算

高精度计算要处理好三个问题:

⑴原始数据的输入与储存

  通常的输入方式有四种:

  ①以一个整数或长整数输入,回车结束。

在运算之前先要数字分离。

②以一个数字字符串输入,回车结束。

TP的字符串,系统本身是按数组的形式储存。

如a:

=‘1234’.则相当于:

  a[1]:

=‘1’; a[2]:

=‘2’; a[3]:

=‘3’; a[4]:

=‘4’

在运算之前先要把字符一一转为数字

③以一个一个数字输入,最后有一个特殊的数(如-1),再加回车结束

④以一个一个数字字符输入,最后有一个非数字字符(如$),再加回车结束。

在运算之前先要把字符一一转为数字。

  储存数据一律用数组。

根据不同的需要,数据的储存可分正向与反向两种。

以输入数1234为例:

  ①正向储存:

数位权的大小与储存数组的下标的大小一致

            下标大               下标小

数组各元素 a[4]   a[3]   a[2]   a[1]

  所存的数字   1      2      3      4

             最高位               最低位

②反向储存:

数位权的大小与储存数组的下标的大小相反

            下标小                下标大

数组各元素 a[1]   a[2]   a[3]   a[4]

  所存的数字   1      2      3      4

             最高位               最低位

  加法、减法、乘法的运算是从低位开始的,所以数据储存采取正向储存比较方便。

如加法、减法采取反向储存,那么在运算操作之前要进行对位、移位、补位操作,增加了不少麻烦。

本提要不讲解这方面的内容,如要想了解,可参考中级本的老教材p.180

⑵运算操作:

加法的进位、减法的借位、乘法的进位、除法的商与余数见教材p.220~p.225

⑶运算结果的输出。

输出要注意三点:

  ①数据是正向储存,用递增循环输出;数据是反向储存,用递减循环输出

②TP是先定义,后运算的。

无法根据机器的运算的结果来定义数组的大小,所以一般定义数组大一些,这样就增加在有效数字前有一些无用的0操作。

在输出时这些在有效数字前无用的0不能输出。

一般在输出有效数字前采用:

WHILE a[i]=0 DO i:

=i-1(正向储存)或

WHILE a[i[=0 DO i:

=i+1(反向储存)

③如是用一个字节储存多位数字,输出时要用0来补位。

【例12-10】把输入的数可能有负数也考虑进去的程序,文件名为 P12_10A;

【变量与算法设计】

用两个逻辑变量f与f1。

用f1来控制运算:

当f1为假做加法,当f1为真做减法。

当f为真来控制数前负号的输出。

具体设置如下:

两个数同号f1为假(做加法运算)

两个数都是正数,f为假

两个数都是负数,f为真。

(f为真输出负号,下同)

    两个数异号f1为真(做减法运算)

第一个为负数,第二个为正数。

第一个数的绝对值大于第二个数的绝对值。

f为真

第一个为负数,第二个数正数。

第一个数的绝对值小于第二个数的绝对值。

f为假,

第一个数正数,第二个为负数。

第一个数的绝对值大于第二个数的绝对值。

f为假,

第一个为正数,第二个为负数。

第一个数的绝对值小于第二个数的绝对值。

f为真

【程序清单】

PROGRAM P12_10A;

CONST n=200;

VAR str1,str2,str:

STRING;

    k,l1,l2,i,j,t:

Integer;

    a,b:

ARRAY [1..n] OF Integer;

    fa,fb:

Char;

    f1,f:

Boolean;

BEGIN

  Write(''Input a string str1 :

 '');  Readln(str1);

  Write(''Input a string str2 :

 '');  Readln(str2);

  l1:

=Length(str1); l2:

=Length(str2);         {以上同教材}

  fa:

=str1[1]; fb:

=str2[1]; f1:

=False; f:

=f1; {取符号位,设置f1、f的值}

  IF (fa=''-'') AND (fb=''-'')          {如都是负数,去掉符号位}

    THEN BEGIN                {重新设置f1、f的值}

      f1:

=False; f:

=True; str1:

=Copy(str1,2,l1); l1:

=l1-1;

      str2:

=Copy(str2,2,l2); l2:

=l2-1 END

    ELSE BEGIN

      IF fa=''-'' THEN {如第一个数是负数,去掉其符号位,重新设置f1、f的值}

        BEGIN f1:

=True; f:

=f1; str1:

=Copy(str1,2,l1); l1:

=l1-1 END;

      IF fb=''-'' THEN {如第二个数是负数,去掉其符号位,重新设置f1、f的值}

        BEGIN f1:

=True; f:

=False; str2:

=Copy(str2,2,l2); l2:

=l2-1 END

      END;

  j:

=l1; {如第二个数的绝对值大于第一个数的绝对值就交换,重新设置f的值}

  IF (l2>l1) OR f1 AND (l2=l1) AND (str2>str1) THEN

    BEGIN f:

=NOT(f); j:

=l2; str:

=str1; str1:

=str2; str2:

=str END;

  FOR i:

=l1 DOWNTO 1 DO BEGIN         {字符串分离同时转换成数字,存入a数组}

    Val(str1[i],a[l1+1-i],k);     {不能转换成数字时,输出出错信息}

    IF k>0 THEN BEGIN Writeln(''Str1 data error !

''); Readln; Exit END

  END;

  FOR i:

=l2 DOWNTO 1 DO BEGIN         {字符串分离同时转换成数字,存入b数组}

    Val(str2[i],b[l2+1-i],k);     {不能转换成数字时,输出出错信息}

    IF k>0 THEN BEGIN Writeln(''Str2 data error !

''); Readln; Exit END

  END;

  IF f1

    THEN BEGIN            {f1为真做减法}

      FOR i:

=1 TO j DO BEGIN

        a[i]:

=a[i]-b[i];

        k:

=Ord(a[i]<0);        {减法借位}

        a[i]:

=a[i]+k*10;

        a[i+1]:

=a[i+1]-k

      END;

      WHILE (a[j]=0) AND (j>0) DO j:

=j-1 {有效数字前无用的0不输出}

      END

    ELSE BEGIN            {f1为假做加法}

      FOR i:

=1 TO j DO BEGIN

        k:

=a[i]+b[i];

        a[i]:

=k MOD 10;        {加法进位}

        a[i+1]:

=a[i+1]+k DIV 10

      END;

      IF a[i+1]>0 THEN j:

=j+1     {最后一次进位}

    END;

  Write(''Xiang Jia He :

 '');       {输出}

  IF j=0

    THEN Write(0)

    ELSE BEGIN

      IF f THEN Write(''-'');           {输出符号位}

      FOR i:

=j DOWNTO 1 DO Write(a[i]) {高精度输出}

    END;

  Writeln; Readln

END.

【例12-11】的另一种编法,文件名 P12_11A;

【例12-12】的另一种编法,文件名 P12_12A;此两程序在盘上有兴趣的可查看

12.4排  序

排序的算法较多。

最常见有六种:

选择排序、冒泡排序、插入排序、希尔排序和归并排序一定要掌握,其基本算法要牢记,在以后一些程序中可作为过程使用。

快速排序的算法较复杂,给出了两个程序,要求能看懂。

 

一)选择排序(Paixu1.pas)

PROGRAM PaiXu1; {选择排序}

CONST n=9;

      a:

ARRAY [1..n] OF Integer=(9,8,5,6,2,7,1,4,3);

TYPE ar=ARRAY [1..n] OF Integer;

VAR b:

ar;

    i,j,k,t:

Integer;

PROCEDURE Swap(var a,b:

Integer);        {过程—交换数据}

  BEGIN

    t:

=a; a:

=b; b:

=t

  END;

PROCEDURE Print(a:

ar);                  {过程—输出数据}

  BEGIN

    FOR i:

=1 TO n DO Write(a[i]:

5); Writeln

  END;

BEGIN

  FOR i:

=1 TO n DO b[i]:

=a[i];    {读入数据}

  Print(b);                       {输出无序的原始数据}

  FOR i:

=1 TO n-1 DO BEGIN        {用两重循环排序}

    k:

=i;                         {用k先记下要交换的元素的坐标}

    FOR j:

=i+1 TO n DO            {用i的下一元素至n,逐一与k元素比较}

      IF b[k]>b[j] THEN k:

=j;     {用k记下较小元素的坐标}

    IF i<>k THEN Swap(b[i],b[k])  {把较小元素与i元素交换}

    END;

  Print(b); Readln                {输出有序数据}

END.

注:

以下程序省略程序的说明部分、相应的过程和输入输出。

完整的程序在盘上。

二)冒泡排序(paixu2.pas)

  i:

=n;                              {从数据的最后操作起}

  REPEAT                             {用直到循环,f控制排序趟数}

    i:

=i-1; f:

=True;          {每排一趟,要排序的元素少一个,因最大数已排至最后}

    FOR j:

=1 TO i DO                  {用计数循环进行一趟排序}

      IF b[j+1]

        BEGIN Swap(b[j+1],b[j]); f:

=False END; {如有交换f为假,还要循环}

  UNTIL f;                    {如这趟排序中没有交换, f一直为真,排序结束}

三)插入排序

如有下列未排序的数组A的元素:

 

    49  38  65  97  76  13  27  45

用插入方法按升序排序为:

        13  27  38  45  49  65  76  97

可把数据分成两部分前面的数据有序(开始时只有第1个数据),后面的数据无序(开始时2~n个数据无序),然后把无序的数据插入到有序的数据中去。

无序数据减少,有序数据增多。

把无序数据全部插入为止,

程序分为查找插入的位置、移动数据、插入数据等。

查找搜索的方法有三种:

⑴无序表从头向后搜索,有序表从后向前搜索,一一插入(简称从头插入)

⑵无序表从后向前搜索,有序表从前向后搜索,一一插入(简称从尾插入)

⑶无序表从头向后搜索,有序表折半查找搜索,一一插入(简称折半插入)

1) 从头插入(算法见每句后的注释)(paixu3)

开始数据分成两部分:

第1个数据有序,2~n个数据无序。

    FOR i:

=2 TO n DO BEGIN               {从第二个到n个数据一一插入}

      k:

=a[i];  j:

=i-1;                  {k为要插入的数,j是有序数列的最大下标}

      WHILE (k0) DO        {当k小于此数,且有序数列前面还有数,就}

        BEGIN a[j+1]:

=a[j]; j:

=j-1; END; {将此数向后移,拿前面的数再与k比}

      a[j+1]:

=k        {当k大于等于有序数列的某数就退出当循环,将k插入此数之后}

END;

  2) 从尾插入(paixu3a)

开始数据分成两部分:

第n个数据有序,1~n-1个数据无序

  FOR i:

=n-1 DOWNTO 1 DO BEGIN         {从倒数二个到1数据一一插入}

      k:

=a[i];  j:

=i+1;                  {k为要插入的数,j是有序数列的最小下标}

      WHILE (k>a[j]) AND (j<=n) DO       {当k大于此数,且有序数列后面还有数,就}

        BEGIN a[j-1]:

=a[j]; j:

=j+1; END; {将此数前移,拿后面的数再与k比}

      a[j-1]:

=k        {当k小于等于有序数列的某数就退出当循环,将k插入此数之前}

END;

3)折半插入(paixu3b)

开始数据分成两部分:

第1个数据有序,2~n个数据无序。

用折半查找要插入的位置。

    FOR i:

=2 TO n DO BEGIN

      k:

=a[i]; l:

=1; h:

=i-1;          {k为要插入的数,l和h为折半查找的上下界}

      WHILE l<=h DO BEGIN             {当上界<=下界,就做}

        m:

=(l+h) DIV 2;               {取中界值的下标m}

        IF k

=m-1 ELSE l:

=m+1{如k<中界值,则下界=m-1,否则上界=m+1}

      END;                            {出循环时,上界>下界}

      FOR j:

=i-1 DOWNTO l DO a[j+1]:

=a[j]; {将比k大的数据后移,腾出位置供插入}

      a[l]:

=k                              {将k插入上界位置}

    END;

四)希尔排序

    上面的三种排序算法简单,但当排序的数据较多时运行时间较长。

其原因无论是交换或插入都是按顺序一个不漏来操作。

1959年希尔对上面的排序算法进行了改进,在顺序中用增量来取代一个一个的操作。

因此排序的趟数就为之减少。

常见的希尔排序有如下两种:

    在插入排序的基础上,加上缩小增量的算法的希尔排序

    在冒泡排序的基础上,加上缩小增量的算法的希尔排序

    下面给出的程序,增量采用折半缩小的方法(教材上增量用键盘输入),具体算法见各个程序语句后的注释。

请与插入排序、冒泡排序比较,找出其不同处

1)希尔排序(插入法)(paixu4a)

h:

=n;                           {h取n}

REPEAT                          {用外直到循环去搜索}

      h:

=h DIV 2;                   {每次增量减半}

FOR i:

=h+1 TO n DO BEGIN      {在h+1到n之间去找插入的位置}

        t:

=a[i]; j:

=i-h;            {取要插入的数据t,j为相距一间隔的下标}

        WHILE t

          BEGIN a[j+h]:

=a[j]; j:

=j-h; END;  {再找前一间隔的数来比。

注①}

        a[j+h]:

=t;                  {出当循环,把插入j+h的位置上}

      END;                          {当i>n,一趟排序结束}

UNTIL h=1                       {直到增量为1,整个排序结束}

  注①因为当循环的条件是t

  2)希尔排序(冒泡法)(paixu4b)

    h:

=n;                        {h取n}

    REPEAT                       {用外直到循环去搜索}

      h:

=h DIV 2;                {每次增量减半}

      REPEAT                     {用内直到循环去搜索一趟排序}

        f:

=True;                 {f控制内直到循环}

        FOR j:

=1 TO n-h DO       {在1到n-h之间搜索}

          IF a[j+h]

            BEGIN Swap(a[j+h],a[j]); f:

=False END;  {交换,有交换f为假}

      UNTIL f                    {没有交换一趟排序结束}

    UNTIL h=1                    {增量为1时,整个排序结束}

3)希尔排序,增量采用为1,3,7,15,...(paixu4b)

    m:

=1; d[m]:

=1;

    WHILE d[m]

BEGIN m:

=m+1; d[m]:

=2*d[m-1]+1 END;

    k:

=m;

    REPEAT                          {用外直到循环去搜索}

      k:

=k-1; h:

=d[k];              {增量取d[k]}

      FOR i:

=h+1 TO n DO BEGIN      {i为间隔后的一个数起到最后的n}

        t:

=a[i]; j:

=i-d;            {取要插入的数据t,j为相距一间隔的下标}

        WHILE t

          BEGIN a[j+h]:

=a[j]; j:

=j-h END; {再找前一间隔的数来比,注①}

        a[j+h]:

=t                    {出当循环,把t插入在j+h的位置上}

      END                            {当i>n,一趟排序结束}

    UNTIL h=1                        {增量为1时,整个排序结束}

五)快速排序

快速排序的算法在教材p.229~p.232中已讲解,下面给出回溯算法(PAIXU5)与递归算法(PAIXU5A)的两个程序。

可对比着看,了解如何把递归算法的程序转化为非递归的程序。

这两种算法在以下章节中讲解。

如在此理解有困难可在学习回溯算法与递归算法时再来阅读。

 

1) 回溯算法的快速排序(paixu5)

PROGRAM PaiXu5; {用回溯算法的快速排序}

CONST n=15;

s0:

ARRAY [1..n] OF Byte=(60,38,55,94,93,16,86,73,24,58,22,99,49,15,43);

VAR i,j,k,l,h,c,t:

Byte;              f:

Boolean;

    s,a,b:

ARRAY [1..n] OF Byte;

PROCEDURE Pr;             {过程----输出一趟排序的结果,并输出变量交换的情况}

  BEGIN

    Writeln(''i='':

5,i,''j='':

5,j,''t='':

5,t,''t--->s['':

10,i,'']'');{输出交换分界点}

    FOR k:

=1 TO n DO Write(s[k]:

5); Writeln        {输出一趟排序的结果}

  END;

BEGIN

  FOR i:

=1 TO n DO                {读入数据及输出}

    BEGIN s[i]:

=s0[i]; Write(s[i]:

5) END; Writeln;

  l:

=1; h:

=n; c:

=0;               {l为头指针,h为尾指针,c栈指针}

  REPEAT                          {用直到循环来完成排序}

    f:

=True;                      {用f来控制直到循环}

    WHILE l

      i:

=l; j:

=h; t:

=s[l];{i,j取头尾指针,数据t为比较的依据,分成小于大于两部分}

      WHILE i

        WHILE (it) DO j:

=j-1;  {当i

        IF i=s[j],如再i

          s[i]:

=s[j]; i:

=i+1;                 {s[i]取a[j]值,i向后移}

          WHILE (i

=i+1; {当i

          IF i

=s[i]; j:

=j-1 END {s[j]取a[i]值,j向前移}

        END                                   {一直操作i=j为止}

END;

      s

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 小升初

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1