java 交换排序之(冒泡排序、快速排序)

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倍。缺点是快速排序使用递归调用,当数组的长度足够大时,会出现内存溢出的情况.....具体解决方案还望各位大神给出宝贵意见.

 
时间: 2024-12-18 10:12:28

java 交换排序之(冒泡排序、快速排序)的相关文章

[Java]排序算法&gt;交换排序&gt;【冒泡排序】(O(N*N)/稳定/N较小/有序/顺序+链式)

1 冒泡排序 1.1 算法思想 交换排序的基本思想:两两比较待排序记录的关键字,一旦发现2个记录不满足次序要求时,则:进行交换,直到整个序列全部满足要求为止. 1.2 算法特征 属于[交换排序] 冒泡排序 快速排序 适用于[稳定性]:稳定 适用于[规模N]:较小 适用于[有序性]:有序 适用于[存储结构]:顺序存储 or 链式存储(二者均可) 相关口诀:[插冒归堆]好有序,[插冒]记录个数小,[插冒二选]时N方 1.3 算法实现 import java.util.Arrays; public c

交换排序(冒泡排序、快速排序)——Java

交换排序 (1)冒泡排序 1.基本思想:在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒.即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换. 2.实例 3.java实现 public static void main(String[] args) { int []nums={57,68,59,52}; bubblesort1(nums); } /** * 它重复地遍历过要排序的数列,一次比较两个元素

常用排序算法实现[交换排序之冒泡排序、快速排序]

相关知识 1. 稳定排序和非稳定排序: 稳定排序算法会依照相等的关键(换言之就是值)维持纪录的相对次序. 如果排序算法是稳定的,就是当有两个有相等关键的纪录R和S,且在原本的列表中R出现在S之前,在排序过的列表中R也将会是在S之前. 2. 内排序和外排序 在排序过程中,所有需要排序的数都在内存,并在内存中调整它们的存储顺序,称为内排序: 在排序过程中,只有部分数被调入内存,并借助内存调整数在外存中的存放顺序排序方法称为外排序. 3.算法分类 排序算法从理论上分为如下几类: (1) 交换排序法:

排序算法四:交换排序之冒泡排序

排序算法四:交换排序之冒泡排序 声明:引用请注明出处http://blog.csdn.net/lg1259156776/ 引言 在我的博文<"主宰世界"的10种算法短评>中给出的首个算法就是高效的排序算法.本文将对排序算法做一个全面的梳理,从最简单的"冒泡"到高效的堆排序等. 系列博文的前三篇讲述了插入排序的三种不同类型,本文讲述第二大类的排序算法:交换排序,包括冒泡排序和快速排序. 排序相关的的基本概念 排序:将一组杂乱无章的数据按一定的规律顺次排列起

数据结构例程——交换排序之冒泡排序

本文是[数据结构基础系列(9):排序]中第4课时[交换排序之冒泡排序]的例程. 冒泡排序 #include <stdio.h> #define MaxSize 20 typedef int KeyType; //定义关键字类型 typedef char InfoType[10]; typedef struct //记录类型 { KeyType key; //关键字项 InfoType data; //其他数据项,类型为InfoType } RecType; //排序的记录类型定义 void B

交换排序算法---冒泡排序与快速排序

本文介绍两种交换排序方法:冒泡排序.快速排序 冒泡排序 冒泡排序基本思想 每次遍历完序列都把最大(小)的元素放在最前面,然后再对剩下的序列重复前面的一个过程,每次遍历完之后待排序序列就少一个元素,当待排序序列减小为只有一个元素的时候排序就结束了.因此,复杂度在最坏的情况下是O(N ^2). 冒泡排序实现过程 将被排序的记录数组R[1..n]垂直排列,每个记录R[i]看作是重量为R[i].key的气泡.根据轻气泡不能在重气泡之下的原则,从下往上扫描数组R:凡扫描到违反本原则的轻气泡,就使其向上"飘

交换排序之冒泡排序和快速排序

交换排序 所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动. 排序入门之冒泡排序 冒泡排序是典型的交换排序算法.冒泡排序的时间复杂度为O(n2),可以说效率比较低,但是,冒泡排序体现的思想是学习排序算法很好的入门,尤其是对学习快速排序(在冒泡排序基础之上发展起来的)很有帮助. 基本思想 冒泡排序的基本思想是,进行(最多进行)n-1趟冒泡,其中n为数据的个数,其中每次冒泡会将未排序的最大

内部排序算法(一):交换排序(冒泡排序,快速排序)

这是我的博文系列<内部排序算法>的第一篇.所谓排序,就是要整理文件中的记录,使之按关键字递增(或递减)次序排列起来.所谓内部排序,是指在排序过程中,若整个文件都是放在内存中处理,排序时不涉及数据的内.外存交换(外排序的定义则相反). 内部排序法按照策略可以划分为五类:插入排序.选择排序.交换排序.归并排序和分配排序.待排文件的存储方式采用顺序表(或直接用向量)作为存储结构(其他的存储结构还有以链表作为存储结构等). 在这个系列的博文中,我按照排序算法的给出,排序算法的分析(包括算法的时空复杂度

常见的排序算法(二) 交换排序(冒泡排序,快速排序)

今天,给大家带来的是交换排序. 首先,我们来了解一下什么叫交换排序.所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动.   那么接下来,我们来看一下.冒泡排序. 冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法. 它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排