Pascal 排序算法

Pascal 排序

排序

排序就是将杂乱无章的数据元素,通过一定的方法按关键字顺序排列的过程。排序问题是一个十分重要的问题,并且排序的方法有很多种:

例子:输入20个数,将它们按照从高到低的次序排列以后输出。

方法一:选择排序

选择排序的基本思想:首先从要进行排序的数中选择最大的一个数,将它放在第一个位置,然后从剩下的数中选择最大的放在第二个位置,如此继续,直到最后剩下的两个数中选出较大的数放在倒数第二个位置,剩下的一个数放在最后完成排序。

具体操作:对需要排序的数据序列进行n-1遍的处理,第1遍处理是将L[2..n]中每一个元素与L[1]比较,最大者与L[1]交换位置,第2遍处理是将L[3..n]中每一个元素与L[2]比较,最大者与L[2]交换位置,......,第i遍处理是将L[i+1..n]中每一个元素与L[i]比较,最大者与L[i]交换位置。

算法:1、输入20个数到数组a中;

2、用外循环确定每一个数,需要循环19次;(For i:=1 to 19 do)

3、用内循环实现确定数与后面所有数的比较和交换;For j:=i+1 to 20 do

4、输出结果。                                     If a[i]<a[j]

为了理解,我们以6个数为例来进行说明:

a[1]     a[2]     a[3]     a[4]     a[5]     a[6]

4        5        7        1        2        3

5        4        7        1        2        3

7        4        5        1        2        3

7        4        5        1        2        3

7        4        5        1        2        3

7        4        5        1        2        3  第一趟结束

7        5        4        1        2        3

7        5        4        1        2        3

7        5        4        1        2        3

7        5        4        1        2        3  第二趟结束

7        5        4        1        2        3

7        5        4        1        2        3

7        5        4        1        2        3  第三趟结束

7        5        4        1        2        3

7        5        4        1        2        3  第四趟结束

7        5        4        1        2        3  第五趟结束

参考程序如下:

Program example(input,output);

Var

a:array[1..20] of integer;

temp: integer;

i,j:integer;

Begin

For i:=1 to 20 do  {读入20个元素}

read(a[i]);

For i:=1 to 19 do  {从第一个到倒数第二个依次确定每个数 }

For j:=i+1 to 20 do  {确定的数与它后面所有的数进行比较}

If a[i]<a[j]

Then  Begin

temp:= a[i];

a[i]:= a[j];

a[j]:=temp

End;

For i:=1 to 20 do   {输出排序后的结果}

Begin

write(a[i]:5);

If i mod 5=0    {控制每行输出5个数据}

Then writeln

End;

End.

上面的程序每次交换两个元素需要执行3个语句,过多的交换必定要花费许多时间,我们做一下改进,就是在内循环中先找出最大值元素的下标,在内循环结束时才考虑是否要交换。改进的选择程序如下:

Program example(input,output);

Var

a:array[1..20] of integer;

temp: integer;

i,j,k:integer;     {添加了一个中间存放下标的变量k}

Begin

For i:=1 to 20 do  {读入20个元素}

read(a[i]);

For i:=1 to 19 do  {从第一个到倒数第二个依次确定每个数 }

Begin

k:=i;

For j:=i+1 to 20 do  {比较之后仅将下标交换给变量k}

If a[i]<a[j]

Then k:=j;

If i<>k

Then  Begin

temp:= a[i];

a[i]:= a[k];

a[k]:=temp

End;

End;

For i:=1 to 20 do   {输出排序后的结果}

write(a[i]);

End.

例子:输入20个数,将它们按照从高到低的次序排列以后输出。

方法二:冒泡排序

冒泡排序的基本思想:依次比较相邻的两个数,将较大的数放在前面,较小的数放在后面。即首先比较第1个数和第2个数,将大的放在前面小的放在后面,然后比较第2个数和第3个数,仍将大的放在前面小的放在后面,如此继续,直到比较最后两个数,大的放在前面小的放在后面,此时第一趟结束,在最后的数必定是最小的数。重复以上步骤,只是最后不用比较最后两个数,这一趟比第一趟少了一步,依次继续下去,直到最后一趟,只比较第一对数,大的放在前面小的放在后面,从而完成排序。

由于在排序过程中总是大数往前放,小数往后放,相当于气泡往上升,所以叫冒泡排序。

算法:

1、输入20个数到数组a中;

2、用外循环实现将最小的数置后,需要循环19次;(For i:=1 to 19 do)

3、用内循环实现相邻两位数的置换; For j:=1 to 20-i do

4、输出结果。                        If a[j]<a[j+1]

为了理解,我们以6个数为例来进行说明:

a[1]     a[2]     a[3]     a[4]     a[5]     a[6]

4        5        7        1        2        3

5        4        7        1        2        3

5        7        4        1        2        3

5        7        4        1        2        3

5        7        4        2        1        3

5        7        4        2        3        1  第一趟结束

7        5        4        2        3        1

7        5        4        2        3        1

7        5        4        2        3        1

7        5        4        3        2        1  第二趟结束

7        5        4        3        2        1

7        5        4        3        2        1

7        5        4        3        2        1  第三趟结束

7        5        4        3        2        1

7        5        4        3        2        1  第四趟结束

7        5        4        3        2        1  第五趟结束

参考程序如下:

Program example(input,output);

Var

a:array[1..20] of integer;

temp: integer;

i,j:integer;

Begin

For i:=1 to 20 do  {读入20个元素}

read(a[i]);

For i:=1 to 19 do  {从最后一个到第二个依次确定每个数 }

For j:=1 to 20-i do  {实现相邻两位数的置换}

If a[j]<a[j+1]

Then Begin

temp:= a[j];

a[j]:= a[j+1];

a[j+1]:=temp

End;

For i:=1 to 20 do   {输出排序后的结果}

Begin

write(a[i]:4);

If i mod 5=0

Then writeln

End;

End. 

上面的这三种程序的比较次数都是190次,因为

19+18+17+…+1=((19+1)/2)*19=190次

在上面冒泡排序的例子中,我们可以看到,在比较完第二趟之后,数组已经排好序,但计算机并不知道,它还要继续进行第三、第四、第五趟。我们可以做一下改进,如果在某一趟的比较中没有发现任何数据交换,则知道已排好序,可以不用再进行比较了,因此第三趟还需要进行,第四趟、第五趟比较则是不必要的。

最完美的是这样一种情况,如果读入的数是排好序的,则只需要进行一趟比较(19次)就可以了,而不用进行19趟(190次)比较了。

为了标志在比较的过程中是否发生了数据交换,我们可以定义一个布尔型的变量flag,以此来判断是否有数据交换。循环中先把flag置为true,如果有数据交换,在交换之后将flag置为false,最后判断如果flag仍为true,则说明已经排好顺序,循环退出,输出结果。由于不确定到底循环多少次,我们可以使用repeat语句。

改进的选择程序如下:

Program example(input,output);

Var

a:array[1..20] of integer;

temp: integer;

i,j:integer;

flag:boolean;   {添加了一个标志变量flag}

Begin

For i:=1 to 20 do  {读入20个元素}

read(a[i]);

i:=1;

Repeat  {不确定需要循环多少次,所以用Repeat语句}

Flag:=true;

For j:=1 to 20-i do  {实现相邻两位数的置换}

If a[j]<a[j+1]

Then Begin

temp:= a[j];

a[j]:= a[j+1];

a[j+1]:=temp

flag:=false

End;

i:=i+1;

Until flag;

For i:=1 to 20 do   {输出排序后的结果}

write(a[i]);

End;

End.

例子:输入20个数,将它们按照从高到低的次序排列以后输出。

方法三:插入排序

插入排序的基本思想:从第2个数开始取出,从其前一个元素向前依次和它比较,如果遇到比它小的,就将小的数据向后移动一个位置,从而插入到它前面已经排好序的数列中去。如此继续,每次将一个待排序的数据元素,插入到前面已经排好序的数列中的适当位置,使数列依然有序;直到待排序数据元素全部插入完为止。

比如:

a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9]

5    7    3    4    6    1    9    8    2   取出第2个数

7    5    3    4    6    1    9    8    2   取出第3个数

7    5    3    4    6    1    9    8    2   取出第4个数

7    5    4    3    6    1    9    8    2   取出第5个数

7    6    5    4    3    1    9    8    2   取出第6个数

7    6    5    4    3    1    9    8    2   取出第7个数

9    7    6    5    4    3    1    8    2   取出第8个数

9    8    7    6    5    4    3    1    2   取出第9个数

9    8    7    6    5    4    3    2    1

参考程序如下:

Program example(input,output);

Var

a:array[1..20] of integer;

t: integer;  {定义一个用于放置取出元素的变量}

i,j:integer;

Begin

For i:=1 to 20 do  {读入20个元素}

read(a[i]);

For i:=2 to 20 do  {从第二个数开始取出 }

Begin

t:=a[i];

j:=i-1;

while (j>0) and (a[j]<t) do  {依次将它前面比它小的数向后移动一个位置}

    begin            问题:条件可不可以写成(a[j]<t) and (j>0),为什么?

a[j+1]:=a[j];

      j:=j-1;

    end;

a[j+1]:=t; {遇到不比它小的数之后,将取出的数据放置在此数之后}

end;

For i:=1 to 20 do   {输出排序后的结果}

write(a[i]:5);

End.

以上三种方法比较简单,属于简单排序。下面介绍一种比较复杂的高级排序方法:

例子:输入20个数,将它们按照从高到低的次序排列以后输出。

方法四:快速排序算法

快速排序是对冒泡排序的一种改进。

它的基本思想是:通过一趟排序将要排序的数据分割成独立的左右两部分,其中一部分的所有数据都比另外一部分的所有数据要小,而另一部分的所有数据都比前一部分的所有数据要大,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,直到每一个待处理的序列的长度为1, 处理结束。

   具体操作:假设要排序的数组是A[1]……A[N],首先任意选取一个数据(通常选用第一个数据)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。

比如:              A[1]   A[2]   A[3]   A[4]   A[5]   A[6]   A[7]              

                    49    38     65     27     76     13     97

一趟快速排序之后    97    76     65     49     13     27     38

一趟快速排序的算法是:

  1)设置两个变量IJ,排序开始的时候I:=1J:=N;

  2)以第一个数组元素作为关键数据,赋值给X,即X:=A[1];

  3)从J开始向前搜索,即由后开始向前搜索(J:=J-1),找到第一个大于X的值,两者交换;

  4)从I开始向后搜索,即由前开始向后搜索(I:=I+1),找到第一个小于X的值,两者交换;

  5)、重复第34步,直到I=J;

  例如:待排序的数组A的值分别是:(初始关键数据X:=49

A[1]   A[2]   A[3]   A[4]   A[5]   A[6]   A[7]              

  49    38     65     27     76     13     97 从后搜,交换前I=1; J=7;交换后I=2 ;J=7

  97    38     65     27     76     13     49 从前搜,交换前I=2; J=7;交换后I=2 ;J=6     

  97    49     65     27     76     13     38 从后搜,交换前I=2; J=6;交换后I=3 ;J=5

  97    76     65     13     49     27     38 从前搜,交换前I=3; J=5;交换后I=4 ;J=5

  97    76     65     49     13     27     38 从后搜,当I=4 ;J=4 结束

     经过一趟快速排序之后的结果是:97   76   65   49   13   27   38,即所有大于49的数全部在49的前面,所有小于49的数全部在49的后面。     

一趟快速排序的程序段:

x:=a[i];

repeat

        while (a[j]<x) and (j>i) do {从后往前搜索比x大的数}

j:=j-1;

        if j>i then  {找到比x大的数后和前面的数进行交换}

begin

w:=a[i];

a[i]:=a[j];

a[j]:=w;

i:=i+1; {交换之后i的值应该增加,定位到后一个}

end;

        while (a[i]>x) and (i<j) do {从前往后搜索比x小的数}

i:=i+1;

        if i<j then

begin

w:=a[j];

a[j]:=a[i];

a[i]:=w;

j:=j-1; {交换之后j的值应该减少,定位到前一个}

end

      until i=j;

整个快速排序过程的实现:

利用分治思想(即大化小的策略)可进一步对分开的两组数据再次分别进行快速排序,照此继续,直到分组对象只有一个数据为止。

我们可以将一趟快速排序写成过程,快速排序就是递归调用此过程。

在上面的例子中,以49为中点分割这个数据序列,然后分别对前面一部分和后面一部分进行类似的快速排序,从而完成全部数据序列的快速排序,最后把此数据序列变成一个有序的序列,根据这种思想对于上述数组A的快速排序的全过程如图所示

初始状态                    {49    38    65    97    76    13    27}   

进行一次快速排序之后划分为   {97    76    65}   49    {13   27    38}

分别对前后两部分进行快速排序 97     {76   65}   49    {38   27}    13

                             结束   {76}  {65}        {38}   {27 }  结束

                                    结束  结束       结束  结束

完整的过程:

procedure quicksort(var a:array; s,e:integer);

var i,j,x,w:integer;

    begin

i:=s;

j:=e;

x:=a[i];

repeat

        while (a[j]<x) and (j>i) do {从后往前搜索比x大的数}

j:=j-1;

        if j>i then  {找到比x大的数后和前面的数进行交换}

begin

w:=a[i];

a[i]:=a[j];

a[j]:=w;

i:=i+1; {交换之后i的值应该增加,定位到后一个}

end;

        while (a[i]>x) and (i<j) do {从前往后搜索比x小的数}

i:=i+1;

        if i<j then

begin

w:=a[j];

a[j]:=a[i];

a[i]:=w;

j:=j-1; {交换之后j的值应该减少,定位到前一个}

end

until i=j;

i:=i+1;

j:=j-1;

      if s<j then quicksort(a,s,j);

      if i<e then quicksort(a,i,e);

  end;

完整的参考程序如下:

program kuaisu(input,output);

const

n=20;

  type

    arr=array[1..n] of integer;

var

    s:arr;

    m:integer;

procedure quicksort(var a:arr; s,e:integer);

var

i,j:integer;

x,w:integer;

    begin

i:=s;

j:=e;

x:=a[i];

repeat

        while (a[j]<x) and (j>i) do {从后往前搜索比x大的数}

j:=j-1;

        if j>i then  {找到比x大的数后和前面的数进行交换}

begin

w:=a[i];

a[i]:=a[j];

a[j]:=w;

i:=i+1; {交换之后i的值应该增加,定位到后一个}

end;

        while (a[i]>x) and (i<j) do {从前往后搜索比x小的数}

i:=i+1;

        if i<j then

begin

w:=a[j];

a[j]:=a[i];

a[i]:=w;

j:=j-1; {交换之后j的值应该减少,定位到前一个}

end

until i=j;

i:=i+1;

j:=j-1;

      if s<j then quicksort(a,s,j);

if i<e then quicksort(a,i,e);

end; {过程结束}

Begin

Writeln(‘input 20 integer num:‘);

For m:=1 to n do

read(s[m]);

m:=1;

quicksort(s,m,n);

For m:=1 to n do

write(s[m]:4)

End.

练习:明明的随机数 全国青少年信息学奥林匹克分区联赛 (NOIp2006) 普及组第一题

[描述 Description]

   明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了N11000之间的随机整数(N100),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从小到大排序,按照排好的顺序去找同学做调查。请你协助明明完成“去重”与“排序”的工作。

[输入格式 Input Format]

   输入有2行,第1行为1个正整数,表示所生成的随机数的个数:N

2行有N个用空格隔开的正整数,为所产生的随机数。

[输出格式 Output Format]

   输出也是2行,第1行为1个正整数M,表示不相同的随机数的个数。第2行为M个用空格隔开的正整数,为从小到大排好序的不相同的随机数。

[样例输入 Sample Input]

10

20 40 32 67 40 20 89 300 400 15

[样例输出 Sample Output]

8

15 20 32 40 67 89 300 400

[时间限制 Time Limitation]

全部点1s

参考程序:

program mm;

  var

    a,b:array[1..100] of integer;

    i,n,j,k:integer;

  begin

    read(n);

    for i:=1 to n do   {读入所有数据放在数组a}

      read(a[i]);

    for i:=1 to n-1 do  {所有数据用冒泡法排序}

      for j:=1 to n-i do

         if a[j]>a[j+1]

           then begin

                  t:=a[j];

                  a[j]:=a[j+1];

                  a[j+1]:=t;

                end;

    k:=1;

    b[1]:=a[1];      {数组a中的第一个元素赋值给数组b的第一个元素}

    for i:=2 to n do

      if a[i]<>a[i-1]  {当本元素与前一个不相等时才赋给数组b}

        then begin

              k:=k+1;

              b[k]:=a[i];

             end;

    writeln(k);      {输出不同元素的个数}

    for i:=1 to k do

      write(b[i],‘ ‘);

  end.

时间: 2024-08-12 07:59:58

Pascal 排序算法的相关文章

经典排序算法 - 冒泡排序Bubble sort

 原文出自于 http://www.cnblogs.com/kkun/archive/2011/11/23/bubble_sort.html 经典排序算法 - 冒泡排序Bubble sort 原理是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换, 这样一趟过去后,最大或最小的数字被交换到了最后一位, 然后再从头开始进行两两比较交换,直到倒数第二位时结束,其余类似看例子 例子为从小到大排序, 原始待排序数组| 6 | 2 | 4 | 1 | 5 | 9 | 第一趟排序(外循环) 第

排序算法比较及其应用

一.将各种数据排序 只要实现了Comparable接口的数据类型就可以被排序. 但要使算法能够灵活地用不同字段进行排序,则是后续需要考虑的问题. 1.指针排序 在Java中,指针操作是隐式的,排序算法操作的总是数据引用,而不是数据本身. 2.键不可变 如果在排序后,用例还可以改变键值,那么数组很可能就不是有序的了.类似,优先队列也会乱套. Java中,可以用不可变数据类型作为键来避免这个问题,如String,Integer,Double和File都是不可变的. 3.廉价交换 使用引用的另一个好处

选择排序 —— 排序算法系列

假设我们有如下一个数组: 使用选择排序算法对这个数组进行排序,步骤如下: 第 1 次 在下标0到6之间找到最小的数字,我们可以发现最小的数字是15,它在下标为4的位置上: 把下标4上面的数字跟下标0上面的数字互换,得到排序如下图的数组: 第 2 次 在下标1到6之间找到最小的数字,我们可以发现最小的数字是33,它在下标为5的位置上: 把下标5上面的数字跟下标1上面的数字互换,得到排序如下图的数组: 第 3 次 在下标2到6之间找到最小的数字,我们可以发现最小的数字是48,它在下标为5的位置上:

排序算法Java版,以及各自的复杂度,以及由堆排序产生的top K问题

常用的排序算法包括: 冒泡排序:每次在无序队列里将相邻两个数依次进行比较,将小数调换到前面, 逐次比较,直至将最大的数移到最后.最将剩下的N-1个数继续比较,将次大数移至倒数第二.依此规律,直至比较结束.时间复杂度:O(n^2) 选择排序:每次在无序队列中"选择"出最大值,放到有序队列的最后,并从无序队列中去除该值(具体实现略有区别).时间复杂度:O(n^2) 直接插入排序:始终定义第一个元素为有序的,将元素逐个插入到有序排列之中,其特点是要不断的 移动数据,空出一个适当的位置,把待插

排序算法总结

各种排序算法总结  排序算法  插入排序 冒泡排序  选择排序  归并排序  快速排序 堆排序  计数排序  基数排序  桶排序  思想  构建有序序列 两两交换 每次找一个最小值 分治法思想 分治法思想 最小堆.最大堆 数字本身的属性  对数据选择多种基数  函数的映射关系.Hash  数据结构  数组  数组  数组  数组 不定   数组 数组 数组  数组  最差时间复杂度 O(n^2)   O(n^2)   O(n^2)   O(n*lgn)  O(n^2).改进O(n*lgn)  O

七大常见排序算法总结

文档版本 开发工具 测试平台 工程名字 日期 作者 备注 V1.0 2016.04.06 lutianfei none V1.1 2016.07.16 lutianfei 增加了归并排序说明 V2.0 2016.07.19 lutianfei 完善了排序算法的总结 排序另一种分法 外排序:需要在内外存之间多次交换数据才能进行 内排序: 插入类排序 直接插入排序 希尔排序 选择类排序 简单选择排序 堆排序 交换类排序 冒泡排序 快速排序 归并类排序 归并排序 排序方法 平均情况 最好情况 最坏情况

数据结构——各排序算法的比较

1.从时间复杂度比较  从平均时间复杂度来考虑,直接插入排序.冒泡排序.直接选择排序是三种简单的排序方法,时间复杂度都为O(n2),而快速排序.堆排序.二路归并排序的时间复杂度都为O(nlog2n),希尔排序的复杂度介于这两者之间.若从最好的时间复杂度考虑,则直接插入排序和冒泡排序的时间复杂度最好,为O(n),其它的最好情形同平均情形相同.若从最坏的时间复杂度考虑,则快速排序的为O(n2),直接插入排序.冒泡排序.希尔排序同平均情形相同,但系数大约增加一倍,所以运行速度将降低一半,最坏情形对直接

八种排序算法

最近一段时间自己在研究各种排序算法,于是自己写了一个八种排序算法的集合: /************************************************************************* > Copyright (c)2014 stay hungry,stay foolish !!! > File Name: sort.cpp > Author: kanty > Mail: [email protected] > Created Time:

排序算法 之 快速排序

快速排序是基于分治思想的一种排序算法,就像该方法的名字一样,速度比较快,所以叫做快速排序:它的平均时间复杂度为O(N*logN),最坏时间复杂度为O(n2),由于快速排序在序列元素数量多的时候速度比较快,所以很多语言内置的排序方法也是用快速排序实现的.快速排序也有很多优化的版本,比如在排序时基数的选择等等-下面就说一下一般的快速排序的实现. 基本思想: 快速排序的基本思想就是,先从待排序的序列中任选一个元素作为基数,然后将序列中的其他小于基数的元素放在基数的左边,大于或等于基数的元素放在基数的右