2016年上班第一天,闲来无事,先写篇博文来结束今天。我们大家都知道java的排序算法很多,接下来我就先看看java最常用的几种排序算法的思想源码附上。(本文所有排序只针对值排序,关于对象排序问题待续.....)
1.插入排序(直接插入排序、二分法插入排序、表插入排序、shell排序)
2.选择排序(直接选择排序、堆排序)
3.交换排序(冒泡排序、快速排序)
4.分配排序(基数排序)
5.归并排序(内排序、外排序)
一、java冒泡排序实现(大家最喜欢也是最简单的排序算法,但是性能不是那么ok 当排序数组很大是性能就很低了)
冒泡排序算法实现思想:
//算法分析:
一次比较相邻的两个数,将大数放在前面、小数放在后面(小数放在前面、大数放在后面)。首先比较第一个和第二 个,满足条件互换位置。然后第二个和第三个比较。直到倒数第二个和最后一个比较。得到一个最大或者最小的数放 在最后完成第一轮比较。一次进行第二轮比较、第三轮直到结束。
//冒泡排序算法:(实现源码)
public static void maopaoSort(int[] arr){
int temp;
for(int i = 0;i < arr.length; i++){
for(int j = 0; j < arr.length-1-i; j++ ){
if(arr[j] < arr[j+1]){
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
二、java交换排序之快速排序
//算法分析:
快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod)。
(1) 分治法的基本思想
分治法的基本思想是:将原问题分解为若干个规模更小但结构与原问题相似的子问题。递归地解这些子问题,然后将这些子问题的解组合为原问题的解。
(2) 实例分解
快速排序是对冒泡排序的一种该进(两种排序都是属于交换排序),通过一趟排序将原有的排序数组分成独立的两个部分。其中一部分的数据比另外一部分的数据都要小。然后再按照此方法对刚划分的两部分进行同样的分割。以此达到整个数组变成有序的序列。
假设需要排序的数组是A[0]......A[N-1],首先任意选取一个数据(通常选择A[0])作为关键数据然后把所有比它小的数都放在前面,所有比它大的数都放在它后面。这整个过程称为一趟快速排序(因此我们可以把一趟快速排序写成一个独立的方法。方便重复调用)
(1)设置两个变量i,j,排序开始的时候i=0,j=N-1.
(2)以第一个数据A[0]作为关键数据,赋值给key,即key=A[i]。
(3)从j(j = j-1 )开始向前搜索,找到第一个小于key的值,让该值与key进行交换。
(4)从i(i = i+1)开始向后搜索,找到第一个大于key的值,让该值与key交换。
(5)重复(3)、(4)不,直到i=j。
列如:需要排序的数组A=[49,38,65,97,76,13,27]初始关键数据为A[0]=49,经过第一趟快速排序后所有比49小的放在了49 的前边,比49大的都放在了49的后边。因此经过第一趟排序后的A=[27, 38, 13, 49, 76, 97, 65]记录关机数据在经过第一轮快速排序后的位置i=3,因此A数组被分为A1=[27, 38, 13]、A0=[49]、A2=[76, 97, 65]三个部分。
package cn.bsxy;
/**
* 快速排序实现源码
* @author smartluobo
*
*/
public class QuickSort {
/**
*
* @a a需要进行排序的数组
* @i i排序的其实位置关键数据的在数组中的位置,第一次调用i = 0
* @j j需要进行排序终止位置。第一次调用是j=a.length-1
* @return 返回经过一趟快速排序后关键数据的位置
*/
public int partition(int[] a, int i, int j){//根据关键数据分割需要排序的数组并返回关键数据在分割后的位置
int key = a[i];//临时变量用于存储关键数据
while(i < j){
while(i < j && a[j] >= key)//找出第一个比key小的数执行j--并将其赋值给a[i]
j--;//执行j = j-1操作
a[i] = a[j];//将a[j]的值赋值给a[i]
while(i < j && a[i] <= key)//找出第一个比key大的数执行i++并将其赋值给a[j]
i++;//执行i = i+1
a[j] = a[i];//把该值赋值给a[j]
}
a[i]=key;//完成一趟快速排序后将选择的关键数据放在分割点上
return i;//返回关键数据在经过一趟快速排序后的位置
}
public void sort(int[] a, int i, int j){
if(i < j){
int n = partition(a ,i ,j);//记录返回的关键数据在经过一趟快速排序后的位置
sort(a,i,n-1);//对左边部分进行递归调用。依次完成分割
sort(a,n+1,j);//对右边部分进行递归调用。依次完成分割
}
}
public static void main(String[] args) {
int[] a = {49,38,65,97,76,13,27};
new QuickSort().sort(a, 0, a.length-1);
for (int i : a) {
System.out.print(i+"\t");
}
}
}
三、性能测试
package cn.bsxy;
import java.util.Random;
/**
*
* @author smartluobo
* 测试java交换排序的冒泡排序和快速排序两种方法的性能
*/
public class SortTest {
/**
* 完成一趟快速排序
* @param a 需要排序的数组
* @param i 起始位置,第一次为0
* @param j 结束位置,一般为数组的长度-1 a.length-1
* @return
*/
public int partition(int[] a,int i,int j){
int key = a[i];
while(i < j){
while(i < j && a[j] <= key)
j--;
a[i] = a[j];
while(i < j && a[i] >= key)
i++;
a[j] = a[i];
}
a[i] = key;
return i;
}
/**
* 快速排序方法实现。递归调用该方法完成数组的排序
* @param a
* @param i
* @param j
*/
public void sort(int[] a, int i, int j){
if(i < j){
int n = partition(a,i,j);
sort(a,i,n-1);
sort(a,n+1,j);
}
}
/**
* 冒泡排序方法实现
* @param a 需要排序的数组
*/
public static void maopaoSort(int[] a){
int temp;
for(int i = 0; i< a.length;i++){
for(int j = 0;j<a.length-i-1;j++){
if(a[j] < a[j+1]){
temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
}
}
/**
* 创建一个长度很长的无序数组
* @return
*/
public static int[] createRandom(){
int[] a = new int[18000];
Random random = new Random();
int b;
for(int i = 0;i < a.length;i++){
b = random.nextInt(100000);
a[i] = b;
}
return a;
}
public static void main(String[] args) {
int[] a = createRandom();
int[] b = a;//将a数组赋值给b是为了保证两个排序方法对完全一样的两个数组进行排序
long maopaoStart = System.currentTimeMillis();
maopaoSort(b);//使用冒泡排序法对生成的数组进行排序
long maopaoEnd = System.currentTimeMillis();
System.out.println("maopaoStart:"+maopaoStart+", maopaoEnd"+maopaoEnd+"快速排序法用 时:"+(maopaoEnd-maopaoStart));
long start = System.currentTimeMillis();
new SortTest().sort(a, 0, a.length-1);//使用快速排序方法对生成的数组排序
long end = System.currentTimeMillis();
System.out.println("start:"+start+", end"+end+"快速排序法用时:"+(end-start));
// int k = 0;
// for (int i : a) {
// k++;
// System.out.print(i+"\t");
// if(k%100 == 0){
// System.out.println();
// }
// }
// 经打印测试冒泡排序和快速排序都能正常排序需要排序的数组
}
}
运行以上代码打印台输出为:
maopaoStart:1456461874561, maopaoEnd:1456461874976 快速排序法用时:415
start:1456461874977, end:1456461875059 快速排序法用时:82
经过多次测试后发现快速排序的速度比冒泡排序快 4~5倍。缺点是快速排序使用递归调用,当数组的长度足够大时,会出现内存溢出的情况.....具体解决方案还望各位大神给出宝贵意见.