java排序方法
2015-08-30 00:36
701 查看
此节介绍排序方法
1,冒泡排序
2,选择排序
3,插入排序
4,希尔排序
5,快速排序
6,归并排序
一,冒泡排序
算法描叙:
设待排序记录序列中的记录个数为n
一般地,第i趟起泡排序从1到n-i+1
依次比较相邻两个记录的关键字,如果发生逆序,则交换之。
其结果是这n-i+1个记录中,关键字最大的记录被交换到第n-i+1的位置上,最多作n-1趟。
二,选择排序
算法描叙:
首先通过n-1次比较,从n个数中找出最小的, 将它与第一个数交换——第一趟选择排序,结果最小的数被安置在第一个元素位置上。
再通过n-2次比较,从剩余的n-1个数中找出关键字次小的记录,将它与第二个数交换——第二趟选择排序。
重复上述过程,共经过n-1趟排序后,排序结束。
三,插入排序
算法描叙
记录存放在数组R[0….n-1]中,排序过程的某一中间时刻,R被划分成两个子区间R[0…i-1]和R[i….n-1],其中:前一个子区间是已排好序的有序区;后一个子区间则是当前未排序的部分。
基本操作:
将当前无序区的第1个记录R[i]插入到有序区R[0….i-1]中适当的位置,使R[0…i]变为新的有序区
操作细节:
当插入第i(i≥1)个对象时, 前面的r[0], r[1], …, r[i-1]已经排好序。
四,希尔排序
算法描叙:
先取定一个小于n的整数gap1作为第一个增量,把整个序列分成gap1组。所有距离为gap1的倍数的元素放在同一组中,在各组内分别进行排序(分组内采用直接插入排序或其它基本方式的排序)。
然后取第二个增量gap2<gap1,重复上述的分组和排序。
依此类推,直至增量gap=1,即所有元素放在同一组中进行排序为止。
算法分析:
开始时 gap 的值较大, 子序列中的元素较少, 排序速度较快。
随着排序进展, gap 值逐渐变小, 子序列中元素个数逐渐变多,由于前面大多数元素已基本有序, 所以排序速度仍然很快。
分组后n值减小,n²更小,而T(n)=O(n²),所以T(n)从总体上看是减小了。
Gap的取法有多种。 shell 提出取 gap = n/2 ,gap = gap/2 ,…,直到gap = 1。gap若是奇,则gap=gap+1
五,快速排序
算法描叙:
任取待排序记录序列中的某个记录(例如取第一个记录)作为基准(枢),按照该记录的关键字大小,将整个记录序列划分为左右两个子序列
左侧子序列中所有记录的关键字都小于或等于基准记录的关键字
右侧子序列中所有记录的关键字都大于基准记录的关键字
基准记录则排在这两个子序列中间(这也是该记录最终应安放的位置)。
然后分别对这两个子序列重复施行上述方法,直到所有的记录都排在相应位置上为止。
基准记录也称为枢轴(或支点)记录。取序列第一个记录为枢轴记录,其关键字为Pivotkey。指针low指向序列第一个记录位置,指针high指向序列最后一个记录位置。
算法分析:
快速排序是一个递归过程,快速排序的趟数取决于递归树的高度。
如果每次划分对一个记录定位后, 该记录的左侧子序列与右侧子序列的长度相同, 则下一步将是对两个长度减半的子序列进行排序, 这是最理想的情况。
六,归并排序
算法描叙:
设初始序列含有n个记录,则可看成n个有序的子序列,每个子序列长度为1。
两两合并,得到 n/2 个长度为2或1的有序子序列。
再两两合并,……如此重复,直至得到一个长度为n的有序序列为止。
ppt 文档 链接:http://pan.baidu.com/s/1c0vzh9u 密码:23yt
1,冒泡排序
2,选择排序
3,插入排序
4,希尔排序
5,快速排序
6,归并排序
一,冒泡排序
算法描叙:
设待排序记录序列中的记录个数为n
一般地,第i趟起泡排序从1到n-i+1
依次比较相邻两个记录的关键字,如果发生逆序,则交换之。
其结果是这n-i+1个记录中,关键字最大的记录被交换到第n-i+1的位置上,最多作n-1趟。
二,选择排序
算法描叙:
首先通过n-1次比较,从n个数中找出最小的, 将它与第一个数交换——第一趟选择排序,结果最小的数被安置在第一个元素位置上。
再通过n-2次比较,从剩余的n-1个数中找出关键字次小的记录,将它与第二个数交换——第二趟选择排序。
重复上述过程,共经过n-1趟排序后,排序结束。
三,插入排序
算法描叙
记录存放在数组R[0….n-1]中,排序过程的某一中间时刻,R被划分成两个子区间R[0…i-1]和R[i….n-1],其中:前一个子区间是已排好序的有序区;后一个子区间则是当前未排序的部分。
基本操作:
将当前无序区的第1个记录R[i]插入到有序区R[0….i-1]中适当的位置,使R[0…i]变为新的有序区
操作细节:
当插入第i(i≥1)个对象时, 前面的r[0], r[1], …, r[i-1]已经排好序。
四,希尔排序
算法描叙:
先取定一个小于n的整数gap1作为第一个增量,把整个序列分成gap1组。所有距离为gap1的倍数的元素放在同一组中,在各组内分别进行排序(分组内采用直接插入排序或其它基本方式的排序)。
然后取第二个增量gap2<gap1,重复上述的分组和排序。
依此类推,直至增量gap=1,即所有元素放在同一组中进行排序为止。
算法分析:
开始时 gap 的值较大, 子序列中的元素较少, 排序速度较快。
随着排序进展, gap 值逐渐变小, 子序列中元素个数逐渐变多,由于前面大多数元素已基本有序, 所以排序速度仍然很快。
分组后n值减小,n²更小,而T(n)=O(n²),所以T(n)从总体上看是减小了。
Gap的取法有多种。 shell 提出取 gap = n/2 ,gap = gap/2 ,…,直到gap = 1。gap若是奇,则gap=gap+1
五,快速排序
算法描叙:
任取待排序记录序列中的某个记录(例如取第一个记录)作为基准(枢),按照该记录的关键字大小,将整个记录序列划分为左右两个子序列
左侧子序列中所有记录的关键字都小于或等于基准记录的关键字
右侧子序列中所有记录的关键字都大于基准记录的关键字
基准记录则排在这两个子序列中间(这也是该记录最终应安放的位置)。
然后分别对这两个子序列重复施行上述方法,直到所有的记录都排在相应位置上为止。
基准记录也称为枢轴(或支点)记录。取序列第一个记录为枢轴记录,其关键字为Pivotkey。指针low指向序列第一个记录位置,指针high指向序列最后一个记录位置。
算法分析:
快速排序是一个递归过程,快速排序的趟数取决于递归树的高度。
如果每次划分对一个记录定位后, 该记录的左侧子序列与右侧子序列的长度相同, 则下一步将是对两个长度减半的子序列进行排序, 这是最理想的情况。
六,归并排序
算法描叙:
设初始序列含有n个记录,则可看成n个有序的子序列,每个子序列长度为1。
两两合并,得到 n/2 个长度为2或1的有序子序列。
再两两合并,……如此重复,直至得到一个长度为n的有序序列为止。
package cn.hncu.sortMethods; public class SortMethods { /*输出数组中的元素*/ private static void print(int[] a) { for(int num: a){ System.out.print(num+"\t"); } System.out.println(); } private static void swap(int[] a, int i, int j) { int temp; temp =a[i]; a[i] = a[j]; a[j] = temp; } public static void main(String[] args) { int a[] = {0,21,25,49,25,16,15,8,-2,0,-9,67,34,5,12,40}; //1-1冒泡排序 bubbleSort(a); //1-2优化的冒泡排序 //bubbleSort2(a); //2选择排序 //selectSort(a); //3-1直接插入排序 //insertSort(a); //3-2用二分优化插入排序 //binaryInsertSort(a); //4 希尔排序 //shellSort(a); //5 快速排序 //quickSort(a,0,a.length-1); //6 归并排序 //mergeSort(a,0,a.length-1); print(a); } private static void mergeSort(int[] a, int left, int right) { if(left<right){//至少有2个元素 int mid = (left+right)/2; //二分,取中点 //把序列拆分成两个子序列:[left,mid] 和 [mid+1,right] //同时还要对分解后的子序列分别进行递归“归并排序” mergeSort(a,left,mid); mergeSort(a,mid+1,right); //把前面两个已经排好序的子序列进行归并 int b[] = new int[a.length]; merge(a,b,left,mid,right); copyArray(a,b,left,right); } } private static void copyArray(int[] a, int[] b, int left, int right) { for(int i=left;i<=right;i++){ a[i] = b[i]; } } //把两个已经排好序的子序列(a[left,mid]和a[mid+1,right]) 合并成一个 ( b[left,right] ) private static void merge(int[] a, int[] b, int left, int mid, int right) { int p = left; int r=mid+1; int k=left; while( p<=mid && r<=right ){ if(a[p]<=a[r]){ b[k++] = a[p++]; }else{ b[k++] = a[r++]; } } //此时,肯定有一个子序列中的元素全部移到b[]数组,因此,只要把还未移完的子序列当中的所有剩余元素直接对拷到数组b[]当中即可 if(p>mid){//左子序列已经完成。因此剩下的是右序列,对拷右序列当中的剩余元素即可 for(int i=r;i<=right;i++){ b[k++]=a[i]; } }else{//对拷左子序列中的剩余元素 for(int i=p;i<=mid;i++){ b[k++]=a[i]; } } } private static void quickSort(int[] a, int p, int r) { if(p<r){ //把数组划分成两个子数组和一个元素(枢轴): //用枢轴a[q]把整数数组划分成 ==> a[p,q-1] , a[q] , a[q+1,r] int q = partition(a,p,r); //a[q] quickSort(a,p,q-1);//排左边的子数组a[p,q-1] quickSort(a,q+1,r);//排右边的子数组a[q+1,r] } } private static int partition(int[] a, int p, int r) { //优化:采用随机选择策略确定枢轴----随机选取数组当中的一个元素,和第一个元素进行交换。之后,以第一个元素作为枢轴进行划分 int rand = (int)(Math.random()*(r-p));//rand为区间内的随机序号(第几个)//p=10000, r=15000 swap(a,p,p+rand); int i=p;//第一个元素定为枢轴 int j=r+1; int x=a[p]; while(true){ while(a[++i]<x && i<r);//定位指针i,找比x大的元素 <--为的是找要交换到右边的"非法"元素 while(a[--j]>x);//定位指针j <--为的是找要交换到左边的"非法"元素 if(i>=j){ break; } swap(a,i,j); } swap(a,p,j);//枢轴a[p]要换到中间位置 return j; } //4 希尔排序 private static void shellSort(int[] a) { //进行分组,初始步长设为数组长度的一半即n/2,然后依次减半,直到最后取1 for(int gap=(a.length+1)/2;gap>0;){ //组内排序 for(int i=0;i<a.length-gap;i++){//定位到每一个元素 for(int j=i;j<a.length-gap;j+=gap){ if(a[j]>a[j+gap]){ swap(a,j,j+gap); } } } //for循环的修正 if(gap>1){ gap = (gap+1)/2; }else if(gap==1){ break; } } } //3-2用二分优化插入排序 private static void binaryInsertSort(int a[]){ for(int i=0;i<a.length-1;i++){ int temp=a[i+1]; int low=0; int high=i; int mid; //在low与 high之间的区域内进行二分查找,以确定新元素的插入位置 while(low<=high){ mid = (high+low)/2; if(a[mid]>temp){//若待插入的数小于中间元素a[mid],则目标落于左半区 high = mid-1; }else{//若待插入的数大于等于中间元素a[mid],则目标落于右半区 low= mid+1; } } //搜索的最后一个小区间的high位置即是查找目标,因此新元素的插入位置即是high+1 //把原来从high到i范围内的元素依次往后移一个位置 for(int j=i;j>high;j--){ a[j+1] = a[j]; } a[high+1] = temp; } } //3-1直接插入排序 private static void insertSort(int[] a) { for(int i=0;i<a.length-1;i++){ int temp=a[i+1]; int j=i; //插入第i个数 //从后往前搜,发现a[j]>temp时,则把a[j]后移到j+1的位置,继续往前搜。 while(a[j]>temp){ a[j+1]=a[j]; j--; if(j<0){ break; } } //否则即a[j]<=temp时,直接把待插入的数放到a[j+1]处 a[j+1]=temp; } } //2选择排序 private static void selectSort(int[] a) { for(int i=0;i<a.length-1;i++){ int j,k; for(j=i+1,k=i;j<a.length;j++){ if(a[j]<a[k]){ k=j; } } if(k!=i){ swap(a,i,k); } } } /*1-1冒泡排序*/ private static void bubbleSort(int[] a) { //冒n-1次,每一次排一个数,最后一个不用排 for(int i=0;i<a.length-1;i++){ //第i趟,从1~n-i-1,两两相邻的数进行判断,若逆顺则交换 for(int j=0;j<a.length-i-1;j++){ if(a[j]>a[j+1]){//升序 swap(a, j, j+1); } } } } /*1-2冒泡排序优化*/ private static void bubbleSort2(int[] a) { boolean flag=false;//表示整个序列还没排好 //冒n-1次,每一次排一个数,最后一个不用排 for(int i=0;i<a.length-1;i++){ flag = true;//假设整个序列已经完成排序 for(int j=0;j<a.length-i-1;j++){ if(a[j]>a[j+1]){ swap(a, j, j+1); //如果有交换,说明前面的假设不成立 flag = false; } } if(flag){//如果前面的假设成立即整个序列已经排好序,则函数返回 return; } } } }
ppt 文档 链接:http://pan.baidu.com/s/1c0vzh9u 密码:23yt
相关文章推荐
- javaWeb解决中文乱码问题终极办法字符流转换
- java_基础篇_01(补)
- javaWeb利用Filter解决中文乱码问题
- Java-instanceof总结
- Java-instanceof总结
- Java-instanceof总结
- shirt----spring security的另外一个选贤
- Java学习之旅_基础篇_05
- Java集合之TreeSet
- Java集合之TreeSet
- Java-TreeSet源码分析及示例
- JAVA POST GET
- Java集合之HashSet
- Java集合之HashSet
- Java-HashSet源码分析及示例
- java实现快速排序
- java基础概念
- java面向对象总结
- Spring基础
- 当web中应用spring框架启动后,获得spring初始化的bean和ServletContext