排序算法讲解学习
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
四、合并排序
算法思想:归并是指将若干个已排序的子文件合并成一个有 的文件。归并排序的实现有两种方法:自底向上和自顶向下。 采用分治法进行的自顶向下的算法形式更为简洁。
具体实现:设归并排序的当前区间是r[low…high],分治法的 三个步骤: (1)分解:将当前区间一分为二,即求分裂点。
第一趟: [55] 22 44 11 33 第二趟: [22 55] 44 11 33 第三趟: [22 44 55] 11 33 第四趟: [11 22 44 55] 33 第五趟: [11 22 33 44 55]
解决问题关键是找插入的位
置。需要写一个函数find(x,y), 来确定第y个插入元素x在已经 有序的序列中的位置。
举例:对下面一组关键字,要求按照从大到小排序
a[1] a[2] a[3] a[4] a[5] a[6] a[7]
1328749 91 2 3 7 4 8
从A[1]到a[7]找最大的数
9 8 1 2 3 4 7 从A[2]到a[7]找最大的数
9 8 7 1 2 3 4 从A[3]到a[7]找最大的数
排序算法
排序就是把一组无序的关键字,通过算法变成一组有序的 关键字。
一、选择排序
算法思想:对于一组关键字{K1,K2,…,Kn},首先从K1,K2, …,Kn中选择最小值,假如它是Ki,则将Ki与K1对换,然后从 K2,K3,…,Kn中选择最小值Ki,再将Ki与K2对换. 如此进行 选择和调换n-2趟,第(n-1)趟,从Kn-1、Kn中选择最小值Ki 将Ki与Kn-1对换,最后剩下的就是该序列中的最大值,一个 由小到大的有序序列就这样形成. 即: 在要排序的一组数 中,选出最小的一个数与第一个位置的数交换,然后在剩下 的数当中再找最小的与第二个位置的数交换,如此循环到 倒数第二个数和最后一个数比较为止。
int find(int x,int y)//该函数就是确定第y个元素x,在有序序列中的位置。
{int k=y;//函数值通过K来返回,K初始化为y,设插入在y位置。
for(int i=1;i<=y;i++)//从第1个元素开始和X比较找到第一个比X小的数
if(a[i]>=x) {k=i;break;}//记下第一个比X小的数的位置,退出循环
9 8 7 4 1 2 3 从A[4]到a[7]找最大的数 9 8 7 4 3 1 2 从A[5]到a[7]找最大的数 9 8 7 4 3 2 1 从A[6]到a[7]找最大的数
9 8 7 4 3ຫໍສະໝຸດ Baidu2 1 排序结束
核心代码
for(i=1;i<n;i++) { for(j=i+1;j<=n;j++) if(a[j]>a[i]) {a[0]=a[i]; a[i]=a[j]; a[j]=a[0];} }
一次比较发生了交换外,以后每一趟都不会发生交换。排序在第一趟冒 泡后就已经有序了,可以结束了。
54312
for(int i=1;i<n;i++) { bool flag=true;//引入了一个标记变量flag,循环中交换过就改变值
for(int j=1;j<=n-i;j++) if(a[j]>a[j+1]) {int tmp=a[j+1];a[j+1]=a[j];a[j]=tmp;flag=false;}// if (flag) break;//flag的值没改变过,说明没发生过交换。 }
举例:对下面一组关键字,要求按照从大到小排序
a[1] a[2] a[3] a[4] a[5] a[6] a[7]
1328749 32 8 7 4 9 1
第一趟
3 8 7 4 9 2 1 第二趟
8 7 4 9 3 2 1 第三趟
87 9 4 3 2 1 89 7 4 3 2 1 98 7 4 3 2 1
该算法缺点就是元素交换 的次数太多。 改进算法:
for(i=1;i<=n;i++) { k=i; for(j=i+1;j<=n;j++) if(a[k]<a[j]) k=j; if(k!=i) {a[0]=a[i]; a[i]=a[k]; a[k]=a[0];} }
二、插入排序
算法思想:设有一组关键字{K1,K2,…,Kn},排序开始就认为 K1是一个有序序列,让K2 插入上述表长为1的有序序列,使之 成为一个表长为2的有序序列,然后让K3插入上述表长为2的 有序序列,使之成为一个表长为3的有序序列,依次类推,最后 让Kn插入上述表长为 n-1的有序序列,得一个表长为n的有序 序列。
return k;//此时的k即为X要插入的位置。
} 程序核心代码:
for(int i=1;i<=n;i++) {
int k;
程序采用了 边读入边插 入的方法。 兰色部分为 后面元素后
移。
cin>>m; k=find(m,i); for (int j=i;j>=k;j--)
a[j+1]=a[j]; a[k]=m; }
三、冒泡排序
算法思想: (1)让j取1至n-1,将r[j]与r[j+1]比较,如果r[j]<r[j+1],则把记录r[j]与 r[j+1]交换位置,否则不进行交换. 最后是r[n-1]与r[n]比较,关键 字较小的记录就换到r[n]的位置上,到此第一趟冒泡结束。最小 关键字的记录就象最轻的气泡冒到顶部一样换到了文件的最后. (2) 让j取1至n-2,重复上述的比较对换操作,最终r[n-1]之中存放 的是剩余n-1个记录(r[n]除外)中关键字最小的记录. (3) 让j取1至2,经过一系列对联对比交换之后,r[3]之中是剩余若 干记录中关键字最小的记录. (4) 让j取1至1,将r[1] 与r[2]对比,把关键字较小的记录交换到r[2] 之中。 至此,经过n-1次冒泡,r[1]到r[n]中的数就成了有序的数。
第四趟 第五趟 第六趟
9 8 7 4 3 2 1 排序结束
核心代码:
for(int i=1;i<n;i++) for(int j=1;j<=n-i;j++)
if(a[j]<a[j+1]) {int tmp=a[j+1];a[j+1]=a[j];a[j]=tmp;}
优化:如果待排序是下面这样的数据。很显然除了第一趟排序在最后