Java排序算法实现及优劣分析

1.冒泡排序

/**
 * 算法思想:
 * 冒泡排序:重复的走访要排序的数列,每次比较两个元素,如果顺序错误就交换过来
 * 走访的数列的工作重复直到没有可以交换的元素停下来
 * 算法因为较小的元素会慢慢"浮"到顶端而得名
 *
 * @author LRD
 *
 */
public class BubbleSort {

    /**
     *按从小到大排列,算法操作如下:
     *比较相邻的两个元素,如果第一个大于第二个,交换位置
     *对每一对相邻的元素作相同的工作,从第一队到最后一对,这样最后一个就是最大的元素了
     *针对除了最后一个元素之外剩下的元素,继续进行如上操作
     *持续对剩下的越来越少的元素重复如上操作
     * 
     * 算法优劣分析:
     *  时间复杂度分析:
     *     最好情况O(n),平均情况O(n的平方),最差情况O(n的平方)
     *  空间复杂度分析:
     *      辅助存储:O(1)
     *  稳定性:
     *      稳定
     *
     * @param nums 待排序数组
     */
    public void bubbleSort(int[] nums){

        int temp=0;
        int size = nums.length;

        for(int i=0;i<size;i++)
        {
            for(int j=0;j<size-(i+1);j++)
            {
                if(nums[j] > nums[j+1])
                {
                    temp = nums[j];
                    nums[j] = nums[j+1];
                    nums[j+1] = temp;
                }
            }
        }


    }

    public static void main(String[] args)
    {
        BubbleSort bs = new BubbleSort();
        int[] array = {12,45,31,34,97,46,67};
        bs.bubbleSort(array);
        System.out.println("Bubble Sort result is:");
        for(int i=0;i<array.length;i++)
        {
            System.out.print(array[i]+" ");
        }
    }
}

运行结果:
Bubble Sort result is:
12 31 34 45 46 67 97 

2.快速排序:

/**
 * 算法思想:
 * 通过一趟排序将待排序的数列分割为独立的两部分,其中一部分记录的关键字均比另外一部分的小,
 * 然后分别对两个部分继续进行快速排序,直到整个序列有序
 * 
 * @author LRD
 *
 */
public class QuickSort {


    /**
     * 按照从小到大排序,算法实现:
     * 首先将数组中的第0号位置的元素设置为中轴,与数组中末尾的元素比较,
     * 如果大于,则交换,如果小于,就不换,继续与倒数第二个比较,如果大于则交换
     * 交换以后,与比他小的那端,刚刚交换之后的后一个进行再进行比较,如此往复,
     * 一趟排序完成之后,左边就是小于中轴的,右边就是大于中轴的,
     * 然后再用分治法对左右两个数组进行排序
     *
     *算法优劣分析:
     * 时间复杂度
     *  最好情况:O(n*log n)   最坏情况:O(n的平方)  平均情况:O(n*log n)
     * 空间复杂度
     *  O(n*log n)
     * 稳定性
     *  不稳定
     * 
     * 在初始序列按照关键码有序或者基本有序时,蜕化为冒泡排序
     */

    /**
     * 首先获取中轴位置
     * 
     * @param nums  待排序数组
     * @param low   数组左边起始位
     * @param high  数组右边末尾
     * @return      中轴位置
     */
    public int getMiddle(int[] nums,int low,int high)
    {
        int temp = nums[low];
        while(low < high)
        {
            while(low < high && nums[high] > temp)
            {
                high--;
            }
            nums[low] = nums[high]; //大于中轴的移到左边

            while(low < high && nums[low] < temp)
            {
                low++;
            }
            nums[high] = nums[low];//小于中轴的移到右边
        }
        nums[low] = temp;
        return low;
    }


    public void quickSort(int[] nums,int low,int high)
    {
        if(low < high)
        {
            int middle = getMiddle(nums,low,high);  //将待排序数组一分为二
            quickSort(nums,low,middle-1);  //对左边数组进行递归排序
            quickSort(nums,middle+1,high); //对右边数组进行递归排序
        }
    }


    public static void main(String[] args)
    {
        int[] array = {12,45,31,34,97,46,67};
        QuickSort qs = new QuickSort();

        if(array.length-1 > 0)
            qs.quickSort(array, 0, array.length-1);

        System.out.println("Quick Sort result is:");
        for(int i=0;i<array.length;i++)
        {
            System.out.print(" "+array[i]);
        }
    }
}

运行结果:
Quick Sort result is:
 12 31 34 45 46 67 97

3.选择排序

/**
 * 算法思想:
 * 选择待排序数组中最小的一个,然后和第一个位置的元素交换,
 * 然后在剩下的数组元素中选择最小的,与第二个交换,一直循环到最后一个位置
 * 
 * 
 * 算法优劣分析:
 *  时间复杂度:
 *      最好情况:O(n的平方) 最坏情况:O(n的平方) 平均情况:O(n的平方)
 *  空间复杂度:
 *      O(1)
 *  稳定性:
 *      不稳定  
 *  
 * @author LRD
 *
 */
public class SelectSort {

    /**
     * 
     * 按照从小到大排列
     * @param nums
     */
    public void selectSort(int[] nums)
    {
        int size = nums.length;

        int temp=0;
        for(int j=0;j<size;j++)
        {
            int smallest = j;
            for(int i = j+1;i < size;i++)
            {
                if(nums[smallest] > nums[i])
                    smallest = i;
            }

            if(smallest != j)
            {
                temp = nums[smallest];
                nums[smallest] = nums[j];
                nums[j] = temp;
            }

        }

    }

    public static void main(String[] args)
    {
        int[] array = {12,45,31,34,97,46,67};
        SelectSort ss = new SelectSort();
        ss.selectSort(array);
        System.out.println("Selkect Sort result is:");
        for(int i=0;i<array.length;i++)
        {
            System.out.print(array[i]+" ");
        }
    }

}

运行结果:
Selkect Sort result is:
12 31 34 45 46 67 97 

4.插入排序

/**
 * 算法思想:
 * 每步将一个待排序的记录,按照其顺序码的大小插入到前面已排好序的字序列的合适位置
 * 从后向前寻找到合适的位置,直到全部的插入排序完成
 * 
 * 
 * 
 * @author LRD
 *
 */
public class InsertSort {

    /**
     * 算法实现:
     * 从第一个元素开始,将第一个元素视为已经排序好了
     * 取出下一个元素,在已经排序的元素序列中从后向前扫描
     * 如果该元素(已排序)大于新元素,将该元素向后移一位
     * 重复以上步骤,直到找到小于等于新元素的已排序的元素
     * 将新元素插入到该位置中
     * 然后重复以上步骤
     * 
     * 算法优劣分析:
     *  时间复杂度:
     *      最好情况:O(n)   最差情况:O(n的平方)    平均情况:O(n的平方)
     *  空间复杂度:
     *      辅助存储:O(1)
     *  稳定性:
     *      稳定
     *  
     * @param nums
     */
    public void insertSort(int[] nums)
    {
        int temp = 0;
        int j=0;
        for(int i=0;i<nums.length;i++)
        {
            temp = nums[i];

            for(j=i;j > 0 && temp < nums[j-1];j--)
            {
                nums[j] = nums[j-1];
            }
            nums[j] = temp;

        }
    }

    public static void main(String[] args)
    {
        int[] array = {12,45,31,34,97,46,67};
        InsertSort is = new InsertSort();
        is.insertSort(array);
        System.out.println("Insert Sort result is:");
        for(int i=0;i<array.length;i++)
        {
            System.out.print(array[i]+" ");
        }

    }

}

运行结果:
Insert Sort result is:
12 31 34 45 46 67 97 

5.希尔排序

/**
 * 算法思想:
 * 先将整个待排序的记录序列分割为若干个子序列
 * 对这些子序列分别进行插入排序
 * 待整个序列基本有序时,再对全体记录进行一次插入排序
 * 
 * 算法优劣分析:
 *  时间复杂度:
 *      最好情况:   O(n)    最坏情况:O(n的平方)        平均情况:O(n的1.5次方)
 *  空间复杂度:
 *      辅助存储:O(1)
 *  稳定性:
 *      不稳定
 * @author LRD
 *
 */
public class ShellSort {

    public static void shellSort(int[] nums)
    {
        int temp=0;
        int j=0;
        for(int increment = nums.length/2;increment > 0;increment /= 2)
        {
            for(int i=increment;i < nums.length;i++)
            {
                temp = nums[i];
                for(j=i;j>=increment;j -= increment)
                {
                    if(temp < nums[j-increment])
                        nums[j] = nums[j-increment];
                    else
                        break;
                }
                nums[j] = temp;
            }
        }
    }

    public static void main(String[] args)
    {
        int[] array = {12,45,31,34,97,46,67};

        ShellSort.shellSort(array);

        System.out.println("Shell Sort result is:");
        for(int i=0;i<array.length;i++)
            System.out.print(array[i]+" ");
    }

}
运行结果:
Shell Sort result is:
12 31 34 45 46 67 97 

6.归并排序

/**
 * 
 * 算法思想:
 * 归并的意思就是把两个(或两个以上)的有序表合并成一个新的有序表
 * 即把待排序序列分为若干个子序列,每个子序列都是有序的。
 * 然后再把有序子序列合并为整体有序序列
 * 
 * 
 * 算法优劣:
 *  时间复杂度:
 *      最好情况:O(n*log n)         最差情况:O(n*log n)         平均情况:O(n*log n)
 *  空间复杂度:
 *      辅助存储:O(1)
 *  稳定性:
 *      稳定
 * @author LRD
 *
 */
public class MergeSort {

    public static int[] sort(int[] nums,int low,int high)
    {
        int middle = (low+high)/2;
        if(low < high)
        {
            sort(nums,low,middle);
            sort(nums,middle+1,high);
            merge(nums,low,middle,high);
        }
        return nums;
    }

    /**
     * 
     * 
     * @param nums 待排序数组
     * @param low 子序列开始位置
     * @param middle 子序列中间位置
     * @param high 子序列末尾位置
     */
    public static void merge(int[] nums,int low,int middle,int high)
    {
        int[] temp = new int[high-low+1];

        int i=low;
        int j=middle+1;
        int k=0;

        //将左右两个子序列比较大小后分别存入 局部变量数组内
        while(i <= middle && j <= high)
        {
            if(nums[i] < nums[j])
                temp[k++] = nums[i++];
            else
                temp[k++] = nums[j++];
        }

        //将左子序列剩余的元素写入数组
        while(i <= middle)
        {
            temp[k++] = nums[i++];
        }

        //将右子序列剩余的元素写入数组
        while(j <= high)
        {
            temp[k++] = nums[j++];
        }

        //将局部变量数组内容写入返回变量数组里面
        for(int k2=0;k2 < temp.length;k2++)
        {
            nums[k2+low] = temp[k2];
        }

    }

    public static void main(String[] args)
    {
        int[] array = {12,45,31,34,97,46,67};
        int[] array1 = new int[array.length-1];
        array1 = sort(array,0,(array.length-1));

        System.out.println("Merge Sort result is:");
        for(int i=0;i<array1.length;i++)
        {
            System.out.print(array1[i]+" ");
        }
    }

}

7.堆排序算法

/**
 * 
 * 知识补充:
 * **堆排序是一种树形选择排序,对直接选择排序的有效优化。
 * **堆的定义如下:具有n个元素的序列(h1,h2,h3...,hn),当且仅当满足
 * **(hi >= h2i,hi >= h2i+1)或(hi <= h2i,hi <= h2i+1)时称之为堆(前者叫大顶堆后者叫小顶堆)。
 * **完全二叉树可以很直观的表示堆的结构。堆顶为根,其他为左子树和右子树
 *
 * 算法思想:
 * 初始时把待排序的数的序列看作是一颗顺序存储的二叉树,从最后一个节点的父节点开始调整排序,
 * 如果子节点大于父节点,则交换,以此类推,调整完成后使之成为一个符合要求的大顶堆。此时根节点为最大值,将它存起来
 * 然后
 * 
 * 
 * 
 * @author LRD
 *
 */
public class HeapSort {

    public static void main(String[] args)
    {
        int[] array = {12,45,31,34,97,46,67};
        for(int i=0;i<array.length-1;i++)
        {
            //建堆
            buildMaxHeap(array,(array.length-1-i));


            //交换堆顶和最后一个元素
            swap(array,0,array.length-1-i);
            System.out.println(Arrays.toString(array));

        }

    }

    public static void buildMaxHeap(int[] data,int lastIndex)
    {
        //从lastIndex节点的父节点开始
        for(int i = (lastIndex-1)/2;i >= 0;i--)
        {
            int k = i; 

            //如果当前节点k的左子节点存在
            while(k*2+1 <= lastIndex)
            {
                //获取到当前节点k的左子节点
                int biggerIndex = k*2 + 1;

                if(biggerIndex < lastIndex)
                {
                    //如果左子节点得值小于右子节点,那么biggerIndex就赋值为右子节点
                    if(data[biggerIndex] < data[biggerIndex+1])
                        biggerIndex++;

                }

                //如果较大的子节点大于父节点,那么就交换位置
                if(data[biggerIndex] > data[k])
                {

                    //调用交换函数
                    swap(data,k,biggerIndex);

                    //值移到子节点
                    k = biggerIndex;
                }
                else
                    break;
            }
        }
    }


    public static void swap(int[] data,int son,int father)
    {
        int temp = data[son];
        data[son] = data[father];
        data[father] = temp;
    }


}

运行结果:
[31, 45, 67, 34, 12, 46, 97]
[31, 45, 46, 34, 12, 67, 97]
[12, 45, 31, 34, 46, 67, 97]
[12, 34, 31, 45, 46, 67, 97]
[31, 12, 34, 45, 46, 67, 97]
[12, 31, 34, 45, 46, 67, 97]
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值