排序算法

排序,即按照特定规则改变一组元素的顺序。其目的在于高效地进行查找。比如有一组数,我们要从中取出第N大的数。如果我们没有排序的话,则每次都要进行多次比较,十分麻烦。以下是用java实现一些排序算法的代码和理解。对于一组元素,要采取什么排序算法,要根据元素的特征来进行选择。在一般情况下,快速排序是最快的通用排序算法。如果元素之间的交换相对于元素之间的比较需要耗费大的多,则可以选择交换次数最少的选择排序。如果元素的的顺序接近有序,则可以选择插入排序或者希尔排序。如果元素的数量非常大,则可以选择希尔排序或者归并排序。如果元素数量非常大且允许占用更多的存储空间,则可以选择归并排序或者归并排序组合其他排序算法。如果比起平均情况下的性能,更注重最坏情况时的性能,且不能占用太多的存储空间,可以选择堆排序。

package template;

import javax.print.attribute.standard.Copies;
import java.util.Scanner;

public class SortAlgorithm {

    /*
    名字:选择排序
    简介:首先找到数组中最小的那个元素,其次,将它和数组的第一个元素交换位置,
    再次,在剩下的元素中找到最小的元素,将它与数组的第二个元素交换位置.
    如此反复,直到整个数组排序完毕.不断地在剩余元素中选择最小的元素放在剩余元素的第一位.
    分析:
    1,运行时间和输入无关.排序一组随机的元素和一组有序的元素时间是一样的.
    2,数据移动是最少的.假设数组长度为N,则只会交换N次.
     */
    public static void selection(Comparable[] a) {
        int N = a.length;
        for(int i = 0; i < N; i++) {
            int min = i;
            for(int j = i+1; j < N; j++) {
                if(a[j].compareTo(a[min]) < 0) {
                    min = j;
                }
            }
            Comparable t = a[i];
            a[i] = a[min];
            a[min] = t;
        }
    }

    /*
    名字:插入排序
    简介:当前索引的左边是有序的,右边是无序的.
    索引从二个元素开始,当索引指向一个元素时.在左边找到合适的位置并插入.
    并接着往右移动,进行同样的操作.直到到达最右端.
    分析:插入排序所用时间取决于输入元素的初始位置.更接近有序的数组,所用时间越少.
     */
    public static void insertion(Comparable[] a) {
        int N = a.length;
        for(int i = 1; i < N; i++) {
            for(int j = i; j > 0 && a[j].compareTo(a[j-1]) < 0; j--) {
                Comparable t = a[j];
                a[j] = a[j-1];
                a[j-1] = t;
            }
        }
    }

    /*
    名字:希尔排序
    简介:通过一个步长序列,将一组元素分为几组,再对这几组元素进行插入排序.
    之后依次缩小步长,对各组元素进行插入排序.直到步长为1.
    分析:插入排序的改进,有利于对大型数组进行排序.
     */
    public static void shell(Comparable[] a) {
        int N = a.length;
        int h = 1;
        while(h < N/3)
            h = 3*h + 1;
        while(h >= 1) {
            for(int i = h; i < N; i++) {
                for(int j = i; j >= h && a[j].compareTo(a[j-h]) < 0; j-=h) {
                    Comparable t = a[j];
                    a[j] = a[j-h];
                    a[j-h] = t;
                }
            }
            h = h/3;
        }
    }

    /*
    名字:归并排序
    简介:归并是指将两组有序的元素,组合成一组有序的元素.
    归并排序是递归的将要排序的元素分为对等的两组,接着一一归并.
    分析:适合排序大型数组,与其他排序方式组合.
     */
    private static Comparable[] aux;
    public static void merge(Comparable[] a, int lo, int mid, int hi) {
        //lo是a数组的第一个元素的坐标,hi是数组最后一个元素数组的坐标.
        //mid是数组中间元素的坐标.
        int i = lo, j = mid+1;
        for(int k = lo; k <= hi; k++) {
            aux[k] = a[k];
        }
        for(int k = lo; k <= hi; k++) {
            if(i > mid) a[k] = aux[j++];
            else if(j > hi) a[k] = aux[i++];
            else if(aux[i].compareTo(aux[j]) < 0) a[k] = aux[i++];
            else a[k] = aux[j++];
        }
    }

    //自顶向下的归并排序
    public static void mergeSort(Comparable[] a) {
        aux = new Comparable[a.length];
        mergeSort(a, 0, a.length-1);
    }
    private static void mergeSort(Comparable[] a, int lo, int hi) {
        if(hi <= lo)
            return;
        int mid = lo + (hi-lo)/2;
        mergeSort(a, lo, mid);
        mergeSort(a, mid+1, hi);
        merge(a, lo, mid, hi);
    }

    //自底向上的归并排序
    public static void mergeSortBU(Comparable[] a) {
        int N = a.length;
        aux = new Comparable[N];
        for(int sz = 1; sz < N; sz = sz*2) {
            for(int lo = 0; lo+sz < N; lo+=sz+sz) {
                merge(a, lo, lo+sz-1, Math.min(lo+sz+sz-1, N-1));
            }
        }
    }

    /*
    名字:快速排序
    简介:在将要排序的数组里面找一个切分位置,把比其小的放在左边,比其大的放在右边.
    然后递归地对左右两边进行相同的处理.
    分析:在一般应用中比其他排序算法快.但是两种情况下效率会比较低下.
    对于在排序过程中,切分不平衡,会会十分低效.
    对于小数组,快速排序比插入排序慢.
     */

    public static void quick(Comparable[] a) {
        quickSort(a, 0, a.length-1);
    }

    public static void quickSort(Comparable[] a, int lo, int hi) {
        if(lo >= hi)
            return;
        //找出切分位置
        int i = lo, j = hi+1;
        Comparable t;
        while(true) {
            while(a[++i].compareTo(a[lo]) < 0 && i!=hi);
            while(a[--j].compareTo(a[lo]) > 0 && j!=lo);
            if(i >= j)
                break;
            t = a[i];
            a[i] = a[j];
            a[j] = t;
        }
        t = a[lo];
        a[lo] = a[j];
        a[j] = t;
        quickSort(a, lo, j);
        quickSort(a, j+1, hi);
    }

    /*
    名字:堆排序
    简介:本质上为优先队列,先进行堆有序化, 在不断将优先级高的元素放置到最后一位,剩余再进行有序化,
    不断的重复此操作,直到剩下最后一个元素。
    分析:堆排序一般比快排慢,但最差的时间为nlogn,比快排好
     */

    public static void heapSort(Comparable[] a) {
        int N = a.length;
        for(int k = N/2; k >= 1; k--)
            sink(a, k, N);
        while(N > 1) {
            Comparable t = a[N-1];
            a[N-1] = a[0];
            a[0] = t;
            sink(a, 1, --N);
        }

    }
    public static void sink(Comparable[] a, int begin, int end) {
        while(begin*2 <= end) {
            int i = begin*2;
            //此分支选择主要比较begin结点的左右子结点,找到更大优先级的字结点
            if(i < end && a[i-1].compareTo(a[i]) < 0)
                i++;
            if(a[begin-1].compareTo(a[i-1]) >= 0)
                break;
            Comparable t = a[begin-1];
            a[begin-1]  = a[i-1];
            a[i-1] = t;
            begin = i;
        }
    }

    public static void main(String[] args) {
        java.util.Scanner sc = new java.util.Scanner(System.in);
        String s = sc.nextLine();
        Integer[] a = new Integer[]{4,6,2,9,1};
        if("selection".equals(s))
            SortAlgorithm.selection(a);
        else if("insertion".equals(s))
            SortAlgorithm.insertion(a);
        else if("shell".equals(s))
            SortAlgorithm.shell(a);
        else if("merge".equals(s))
            SortAlgorithm.mergeSort(a);
        else if("mergeBU".equals(s))
            SortAlgorithm.mergeSortBU(a);
        else if("quick".equals(s))
            SortAlgorithm.quick(a);
        else if("heap".equals(s))
            SortAlgorithm.heapSort(a);
        for(int i = 0; i < a.length; i++) {
            System.out.print(a[i]+" ");
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值