JAVA的六大经典算法,代码案例简化分析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/tianyazaiheruan/article/details/47782327

   java八大经典算法:冒泡、选择、快速、插入、希尔、堆、归并、基数

1.算法实现类

package com.algorithm;

/**
 * 
 * @Title: BubbleSort.java
 * @Copyright: Copyright (c) 2005
 * @Description: <br>
 * <br>
 *               JAVA六大经典算法<br>
 *               冒泡、选择、快速、插入、希尔、堆
 * @Created on 2015年6月29日 下午12:48:14
 * @author yangkai
 */
public class AlgorithmClassic {

    /**
     * 冒泡排序
     * 
     * @return
     */
    public static int[] sortBubble(int[] datas) {
        for (int i = 0; i < datas.length - 1; i++) {
            for (int j = 0; j < datas.length - 1 - i; j++) {
                if (datas[j] > datas[j + 1])
                    AlgorithmUtil.swap(datas, j, j + 1);
            }
        }
        return datas;
    }

    /**
     * 选择排序
     * 
     * @return
     */
    public static int[] sortSelect(int[] datas) {
        for (int i = 0; i < datas.length; i++) {
            int index = i;
            for (int j = i + 1; j < datas.length; j++) {
                if (datas[j] < datas[index])
                    index = j;
            }
            if (i != index)
                AlgorithmUtil.swap(datas, i, index);
        }
        return datas;
    }

    /**
     * 插入排序法
     * 
     * @param datas
     */
    public static int[] sortInsert(int[] datas) {
        for (int i = 1; i < datas.length; i++) {
            int j = i - 1;
            AlgorithmUtil.temp = datas[i];
            for (; j >= 0 && AlgorithmUtil.temp < datas[j]; j--) {
                datas[j + 1] = datas[j];
            }
            datas[j + 1] = AlgorithmUtil.temp;
        }
        return datas;
    }

    /**
     * 快速排序;分割数组
     * 
     * @param datas
     */
    public static int QuickPartition(int[] datas, int left, int right) {
        int pivot = datas[left];
        while (left < right) {
            while (left < right && datas[right] >= pivot)
                --right;
            datas[left] = datas[right]; // 将比枢轴小的元素移到低端,此时right位相当于空,等待低位比pivotkey大的数补上
            while (left < right && datas[left] <= pivot)
                ++left;
            datas[right] = datas[left]; // 将比枢轴大的元素移到高端,此时left位相当于空,等待高位比pivotkey小的数补上
        }
        datas[left] = pivot; // 当left == right,完成一趟快速排序,此时left位相当于空,等待pivotkey补上
        return left;
    }

    /**
     * 快速排序;递归返回数组
     * 
     * @param datas
     */
    public static int[] sortQuick(int[] datas, int left, int right) {
        if (left < right) {
            int data = QuickPartition(datas, left, right);
            sortQuick(datas, left, data - 1);
            sortQuick(datas, data + 1, right);
        }
        return datas;
    }

}


2.算法工具类

package com.algorithm;

public class AlgorithmUtil {

    public static int temp,index = 0;

    /**
     * 临时值交换
     * 
     * @param datas
     *            数组
     * @param i
     * @param j
     */
    public static void swap(int[] datas, int i, int j) {
        temp = datas[i];
        datas[i] = datas[j];
        datas[j] = temp;
    }

    /**
     * 扩充数组长度
     * 
     * @param datas
     * @param value
     * @return
     */
    public static int[] expandArray(int[] datas, int value) {
        if (datas.length <= index) {
            int[] arrays = new int[datas.length * 2];
            System.arraycopy(datas, 0, arrays, 0, datas.length);
            datas = arrays;
        }
        datas[index] = value;
        index++;
        return datas;
    }
}

3.重点算法介绍

   快速排序是所有排序算法中效率最高最快的算法,这里重点介绍一下他的实现原理;

  快速排序的基本思想

         通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分关键字小,则分别对这两部分继续进行排序,直到整个序列有序。

资料一:

先看一下这幅图:


    把整个序列看做一个数组,把第零个位置看做中轴,和最后一个比,如果比它小交换,比它大不做任何处理;交换了以后再和小的那端比,比它小不交换,比他大交换。这样循环往复,一趟排序完成,左边就是比中轴小的,右边就是比中轴大的,然后再用分治法,分别对这两个独立的数组进行排序。

资料二:

  快速排序法事应用最广泛的排序算法之一,最佳情况下时间复杂度是 O(nlogn)。但是 最坏情况下可能达到 O(n^2)。说明快速排序达到最坏情况的原因。并提出改善方案并实现 之。

答:

改进方案:改进选取枢轴的方法

1、选取随机数作为枢轴。

但是随机数的生成本身是一种代价,根本减少不了算法其余部分的平均运行时间。

2、使用左端,右端和中心的中值做为枢轴元。

经验得知,选取左端,右端,中心元素的中值会减少了快排大约 14%的比较。

3、每次选取数据集中的中位数做枢轴。

选取中位数的可以在 O(n)时间内完成。(证明见《算法导论(第二版) 》) P111 第九章中位数

和顺序统计学:在平均情况下,任何顺序统计量(特别是中位数)都可以在线性时间内得到。

快排的分割策略:

第一步是通过将枢轴元与最后一个元素交换使得枢轴元离开要被分割的数据段;i 从第一个

元素开始而 j 从倒数第二个元素开始。当 i 在 j 左边时,我们将 i 右移,移过那些小于枢轴

元的元素,并将 j 左移,移过那些大于枢轴元的元素。当 i 和 j 停止时,i 指向的是大元素,

j指向的是小元素。如果 i 在 j 左边,那么将这两个元素互换。 如果此时 i 和 j 已经交错即 i>j

所以不交换。此时把枢轴元与 i 所指的元素交换。

实例演示:

计算机生成了可选文字:8149035276第1次互换后:21

 

计算机生成了可选文字:第2次交换前:21第二次交换后:口口门口口口暇肠翩孺喃口翩翩口口

 

计算机生成了可选文字:第三次交换前:21与枢轴元交换后:口口口口口口口口口口口口口口口口pivot

 

4.网上一些关于java算法不错的文章

http://www.cnblogs.com/liuling/p/2013-7-24-01.html

http://android.blog.51cto.com/268543/130450/

http://blog.csdn.net/hguisu/article/details/7776068



猜你喜欢

转载自blog.csdn.net/tianyazaiheruan/article/details/47782327