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)设置两个变量I、J,排序开始的时候I:=1,J:=N;
2)以第一个数组元素作为关键数据,赋值给X,即X:=A[1];
3)从J开始向前搜索,即由后开始向前搜索(J:=J-1),找到第一个大于X的值,两者交换;
4)从I开始向后搜索,即由前开始向后搜索(I:=I+1),找到第一个小于X的值,两者交换;
5)、重复第3、4步,直到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]
明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了N个1到1000之间的随机整数(N≤100),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从小到大排序,按照排好的顺序去找同学做调查。请你协助明明完成“去重”与“排序”的工作。
[输入格式 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.
Pascal 排序算法的更多相关文章
- 十大经典排序算法(java实现、配图解,附源码)
前言: 本文章主要是讲解我个人在学习Java开发环境的排序算法时做的一些准备,以及个人的心得体会,汇集成本篇文章,作为自己对排序算法理解的总结与笔记. 内容主要是关于十大经典排序算法的简介.原理.动静 ...
- JavaScript实现常用的排序算法
▓▓▓▓▓▓ 大致介绍 由于最近要考试复习,所以学习js的时间少了 -_-||,考试完还会继续的努力学习,这次用原生的JavaScript实现以前学习的常用的排序算法,有冒泡排序.快速排序.直接插入排 ...
- 排序算法----基数排序(RadixSort(L))单链表智能版本
转载http://blog.csdn.net/Shayabean_/article/details/44885917博客 先说说基数排序的思想: 基数排序是非比较型的排序算法,其原理是将整数按位数切割 ...
- 常见排序算法(附java代码)
常见排序算法与java实现 一.选择排序(SelectSort) 基本原理:对于给定的一组记录,经过第一轮比较后得到最小的记录,然后将该记录与第一个记录的位置进行交换:接着对不包括第一个记录以外的其他 ...
- 几大排序算法的Java实现
很多的面试题都问到了排序算法,中间的算法和思想比较重要,这边我选择了5种常用排序算法并用Java进行了实现.自己写一个模板已防以后面试用到.大家可以看过算法之后,自己去实现一下. 1.冒泡排序:大数向 ...
- 排序算法----基数排序(RadixSort(L,max))单链表版本
转载http://blog.csdn.net/Shayabean_/article/details/44885917博客 先说说基数排序的思想: 基数排序是非比较型的排序算法,其原理是将整数按位数切割 ...
- 排序算法汇总(C/C++实现)
前言: 本人自接触算法近2年以来,在不断学习中越多地发觉各种算法中的美妙.之所以在这方面过多的投入,主要还是基于自身对高级程序设计的热爱,对数学的沉迷.回想一下,先后也曾参加过ACM大大小小的 ...
- 用Java来写常见的排序算法
随着校招的临近 算法是校招中很重要的一个部分 总结了常见几种排序算法,各种算法的时间复杂度和空间复杂度大家也需要多了解下 package com.huwei.sort; /** * 各种排序算法 * ...
- 模板化的七种排序算法,适用于T* vector<T>以及list<T>
最近在写一些数据结构以及算法相关的代码,比如常用排序算法以及具有启发能力的智能算法.为了能够让写下的代码下次还能够被复用,直接将代码编写成类模板成员函数的方式,之所以没有将这种方式改成更方便的函数模板 ...
随机推荐
- mysql的下载
怎样从Mysql官网下载mysql.tar.gz版本的安装包 原创 2016年10月20日 21:06:41 10854 今天学习在Linux上部署项目,用到了Mysql,因此想要下载适用 ...
- python cv2 恢复手机图片
找到可以恢复的手机图片 矩阵相乘 mat() {} 量化表 8*8 矩阵 与 2 4 2 2 16 16 16后面都是16的8*8矩阵相乘 计算变化的位是否可恢复 单独一张jpg的计 ...
- ES6 Sybol属性
Symbol: 概念:ES6中的添加了一种原始数据类型symbol(已有的原始数据类型:String, Number, boolean, null, undefined, 对象) 特点: 1.Symb ...
- Shell case in语句详解
和其它编程语言类似,Shell 也支持两种分支结构(选择结构),分别是 if else 语句和 case in 语句.在<Shell if else>一节中我们讲解了 if else 语句 ...
- Python加密模块
RSA加密 # 生成公钥私钥对象 import rsa pub_key_obj, priv_key_obj = rsa.newkeys(1024) ''' 这里的1024是二进制位数, 也就是说他加密 ...
- Kotlin Doc
{ https://www.runoob.com/kotlin/kotlin-eclipse-setup.html }
- python中os模块获取路径的几种方式
一.代码 import os BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) p ...
- VS卸载不干净,再次安装盘符不能更改问题(转载)
下载文件,直接用. 链接:https://pan.baidu.com/s/1K1cbJUq_JC9DN2MoE6Z3RA 密码:cuad
- 在linux中的rpm -ivh 是干什么的呢?
在linux中的rpm -ivh 是干什么的呢? RMP 是 LINUX 下的一种软件的可执行程序,你只要安装它就可以了.这种软件安装包通常是一个RPM包(Redhat Linux Packet ...
- JTable更新内容的方法
JTable更新内容的方法 DefaultTableModel dtm=new DefaultTableModel(data,head);//定义表格模型 jt.setModel(dtm);或jt=n ...