排序算法讲解(二)
来源:互联网 发布:非诚勿扰程序员死亡 编辑:程序博客网 时间:2024/06/07 22:55
三、快速排序
快速排序是目前在实际工作当中使用频率最高、效率也最好的一种排序算法。它的主要思想是:有待排序数组S={d1,d2,d3,……,dn},从中挑选一个元素dx最为一个基准,将剩余的元素中小于或者等于dx的元素全都移到dx的前面,将大于dx的元素全部移到dx的后面。这样S课分为两个子集S1和S2,其中S1中的元素全部小于等于dx,S2中的元素全部大于dx。此时一趟排序完成。再遵循以上的思路,用递归的方法,对S1和S2也进行相同的操作。当所有的子序列都只含有一个或者零个元素的时候,说明排序已经完成。
在具体的代码实现过程中。快速排序的每一次递归执行都有两个主要的操作:数据交换和返回基准数dx的追中位置。
举一个具体的例子,假设有待排序数组S = {2,9,3,7,10,1,5,4,6,8},我们设置变量p和r表示数组的首尾元素小标。选取最后一个元素8作为第一次排序的基准数,记为S(r)。剩下的就是将S(p),S(p+1),S(p+2)……S(r-1)进行划分。首先,我们设置变量i = p-1,即第一个元素的前方位置。设置变量j = p,反复执行如下步骤:
(1)j+1,如果S(j)<=S(r),交换S(i+1)和S(j)的位置,然后 i++,j++;若S(j)>S(r),则保持两个元素原位置不变,i值不变,j++。
(2)等到j = r-1的时候,停止步骤(1)。
(3)当上述步骤停止之后,交换S(r)与S(j+1)的值,基准值S(r)就放在了应在的位置上。这样,S(r)之前的元素全部小于等于S(r),S(r)之后的元素全部大于S(r)。
代码:其中,i,j,p,r等字母的含义如上所述。
#include<iostream>using namespace std;void Swap(int* a,int* b){ int temp; temp = *a; *a = *b; *b = temp;}int Partition(int a[],int p,int r){ int pos; int temp = a[r]; int i = p-1; for(int j=p;j<r;j++) { if(a[j]<=temp) { i++; Swap(&a[i],&a[j]); } } Swap(&a[i+1],&a[r]); return i+1;}void quickSort(int a[],int p,int r){ int pos = 0; if(p<r) { pos = Partition(a,p,r); quickSort(a,p,pos-1); quickSort(a,pos+1,r); }}
四、归并排序
归并是指将两个或者多个有序序列合并成为一个有序的序列。如果是将两个有序序列归并成为一个有序序列,那么称之为二路归并。同理,如果是三个并成一个,为三路归并;4个归并成一个,为四路归并……。这里只介绍最简单的二路归并。
归并算法的关键操作是:合并两个已排序的自数据集。其过程可以描述为:我们选取两个数组A和B,声明另外一个数组C长度是A和B的长度之和。我们要做的就是把A和B归并为一个有序数组C。首先,设置3个指针AStr,BStr,CStr分别指向数组A,B,C。AStr和BStr用于比较A和B数组当中的数组的大小。CStr永远指向C数组中需要插入的元素的位置。初始状态下,AStr和BStr分别指向数组A和B的第一个元素,然后比较这两个元素的大小,将较小的元素插入到C数组中的CStr指针所指向的位置。接着,将刚挪到C数组的元素所在的数组的指针往后移……以此类推,直到某一个数组所有的元素都被处理了。此时,将另一个数组的剩余元素复制到C数组的末尾即可。
代码:
#include<iostream>using namespace std;///首先是两个数组的合并操作.void Merge(int a[],int b[],int c[],int lenA,int lenB)///将数组a,b合并为c数组,a数组长度为lenA{ ///b数组长度为lenB int aStr = 0,bStr = 0,cStr = 0; ///相当于指向a,b,c三个数组的指针。 while(cStr<(lenA+lenB)) { if(a[aStr]<b[bStr]) ///判断两个数组各自指针所指向的元素的大小,将较小的放进c中 { c[cStr] = a[aStr]; aStr ++; cStr ++; } else { c[cStr] = b[bStr]; bStr ++; cStr ++; } if(aStr==lenA) ///若其中一个数组的元素已经处理完,将另一个数组当中剩余 { ///的元素一次放入c中 while(bStr<lenB) { c[cStr] = b[bStr]; bStr ++; cStr ++; } } else if(bStr==lenB) { while(aStr<lenA) { c[cStr] = a[aStr]; aStr ++; cStr ++; } } }}///归并算法的实现。void mergeSort(int a[],int n){ if(n>1) { ///首先是将a数组进行拆分 int i = n/2; int j = n-n/2; int b[n/2]; int c[n-n/2]; for(int k=0;k<i;k++) { b[k] = a[k]; } for(int k=0;k<j;k++) { c[k] = a[k+i]; } mergeSort(b,i); mergeSort(c,j); Merge(b,c,a,i,j); }}
- 排序算法讲解(二)
- 几种排序算法的讲解(二)
- 排序算法讲解(一)
- 排序算法讲解(三)
- 排序算法(二)
- 排序算法(二)
- 排序算法(二)
- 排序算法 (二)
- 排序算法(二)
- 排序算法讲解
- 排序算法小记(二)
- 排序算法总结(二)
- 排序算法总结(二)
- 排序算法总结(二)
- 算法(二)冒泡排序
- 八大排序算法(二)
- 排序算法总结(二)
- 排序算法分析(二)
- Android用户界面UI总结
- php反射代码
- 基本的线程机制
- [笔记]java应用程序窗口关闭的六种方式
- 获取图片的宽高
- 排序算法讲解(二)
- bfs和bfs
- HDOJ-5363 Key Set
- Flip Game
- windows程序设计学习笔记--多任务和多线程
- c++ 析构函数定义与实现
- C语言实现输入字符串计算单词个数
- CodeForces 699DFix a Tree
- 基于注解的Spring多数据源配置和使用