Java 常见的排序算法

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

这篇文章主要介绍常见的排序算法,图片来源于网络,java代码实现为本人编写,如若有不当之处还望指正。

分类
1)插入排序(直接插入排序、希尔排序)
2)交换排序(冒泡排序、快速排序)
3)选择排序(直接选择排序、堆排序)
4)归并排序
5)分配排序(基数排序)

所需辅助空间最多:归并排序
所需辅助空间最少:堆排序
平均速度最快:快速排序

不稳定:快速排序,希尔排序,堆排序。

先来看看8种排序之间的关系:
这里写图片描述

直接插入排序
(1)基本思想:在要排序的一组数中,假设前面(n-1)[n>=2] 个数已经是排

好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数

也是排好顺序的。如此反复循环,直到全部排好顺序。

(2)实例
这里写图片描述

package test;

public class InsertSort {

private int[] a;

public InsertSort() {
    a = new int[]{ 1, 54, 6, 3, 78, 34, 12, 45 };
}

public void insertSort() {
    if ( a.length < 2 ) {
        return;
    }
    else {
        int curPosition = 1;
        for ( ; curPosition < a.length; curPosition++ ) {
            int prePosition = curPosition - 1;
            int temp = a[ curPosition ];
            for ( ; prePosition >= 0 && temp < a[ prePosition ]; prePosition-- ) {
                a[ prePosition+1 ] = a[ prePosition ];
            }
            a[ prePosition + 1 ] = temp;
        }
    }
}

public void printResult() {
    for ( int elem : a ) {
        System.out.println( elem );
    }
}

public static void main( String[] args ) {
    InsertSort insetSort = new InsertSort();
    insetSort.printResult();
    insetSort.insertSort();
    System.out.println( "\n" );
    insetSort.printResult();
}

}

简单选择排序
(1)基本思想:在要排序的一组数中,选出最小的一个数与第一个位置的数交换;

然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止。

(2)实例:
这里写图片描述

package test;

public class SelectSort {

private int[] a;

public SelectSort() {
    a = new int[]{ 1, 54, 6, 3, 78, 34, 12, 45 };
}

public void selectSort() {
    if ( a != null && a.length != 0 ) {
        for ( int i = 0; i < a.length - 1; i++ ) {
            int temp = a[ i ];
            int min= temp ;
            int position = 0;
            for ( int j = i + 1; j < a.length; j++ ) {
                if ( a[ j ] < min ) {
                    min = a[ j ];
                    position = j;
                }
            }
            if ( min < temp ) {
                a[ i ] = a[ position ];
                a[ position ] = temp;
            }
        }
    }
}

public void printResult() {
    for ( int elem : a ) {
        System.out.println( elem );
    }
}

public static void main( String[] args ) {
    SelectSort selectSort = new SelectSort();
    selectSort.printResult();
    selectSort.selectSort();
    System.out.println( "\n" );
    selectSort.printResult();
}

}

冒泡排序
(1)基本思想:在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。

(2)实例:
这里写图片描述

package test;

public class BubbleSort {

private int[] a;

public BubbleSort() {
    a = new int[]{ 1, 54, 6, 3, 78, 34, 12, 45 };
}

public void bubbleSort() {
    if ( a.length < 2 ) {
        return;
    }
    for ( int i = 0; i < a.length - 1; i++ ) { // 每执行一次for语句的循环体,将最大的一个放在数据后面(length-1-i索引处)
        for ( int j = 0; j < a.length - 1 - i; j++ ) { // 用于对两两相邻元素进行比较,减i是因为已经有i个较大的元素放在数据的后面,不需要再比较
            if ( a[ j ] > a[ j + 1 ] ) {
                int temp = a[ j ];
                a[ j ] = a[ j + 1 ];
                a[ j + 1 ] = temp;
            }
        }
    }
}

public void printResult() {
    for ( int elem : a ) {
        System.out.println( elem );
    }
}

public static void main( String[] args ) {
    BubbleSort bubbleSort = new BubbleSort();
    bubbleSort.printResult();
    bubbleSort.bubbleSort();
    System.out.println( "\n" );
    bubbleSort.printResult();
}

}

快速排序
(1)基本思想:选择一个基准元素,通常选择第一个元素或者最后一个元素,通过一趟扫描,将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素,此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分。

(2)实例:
这里写图片描述

package test;

public class QuickSort {

private int[] a;

public QuickSort() {
    a = new int[]{ 49, 38, 65, 97, 76, 13, 27, 49, 78, 34, 12, 64, 5, 4, 62, 99, 98, 54, 56, 17, 18, 23, 34, 15, 35,
                    25, 53, 51 };
}

public int[] getDatas() {
    return a;
}

public void quickSort( int[] datas ) {
    quickSort( datas, 0, datas.length - 1 );
}

private void quickSort( int[] datas, int startIndex, int endIndex ) {
    if ( datas == null || datas.length == 0 || datas.length < 2 ) {
        return;
    }
    if ( startIndex >= endIndex ) {
        return;
    }
    int baseNum = datas[ startIndex ];// 基准值
    int i = startIndex;
    int j = endIndex;
    while ( i < j ) { // 执行一次循环体,将一个大于基准值的数和一个小于基准值的数交换位置
        while ( i < j && datas[ j ] > baseNum ) {
            j-- ;
        }
        if ( i < j ) {
            datas[ i++ ] = datas[ j ];
        }
        while ( i < j && datas[ i ] < baseNum ) {
            i++ ;
        }
        if ( i < j ) {
            a[ j-- ] = a[ i ];
        }
    }
    a[ i ] = baseNum;
    quickSort( datas, startIndex, i - 1 );
    quickSort( datas, i + 1, endIndex );
}

public void printResult() {
    for ( int elem : a ) {
        System.out.println( elem );
    }
}

public static void main( String[] args ) {
    QuickSort quickSort = new QuickSort();
    quickSort.printResult();
    quickSort.quickSort( quickSort.getDatas() );
    System.out.println( "\n" );
    quickSort.printResult();
}

}

归并排序
基本思想:

  归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。

归并排序示例:

这里写图片描述

public class MergeSortTest {

public static void main(String[] args) {
    int[] data = new int[] { 5, 3, 6, 2, 1, 9, 4, 8, 7 };
    print(data);
    mergeSort(data);
    System.out.println("排序后的数组:");
    print(data);
}

public static void mergeSort(int[] data) {
    sort(data, 0, data.length - 1);
}

public static void sort(int[] data, int left, int right) {
    if (left >= right)
        return;
    // 找出中间索引
    int center = (left + right) / 2;
    // 对左边数组进行递归
    sort(data, left, center);
    // 对右边数组进行递归
    sort(data, center + 1, right);
    // 合并
    merge(data, left, center, right);
    print(data);
}

/**
 * 将两个数组进行归并,归并前面2个数组已有序,归并后依然有序
 * 
 * @param data
 *            数组对象
 * @param left
 *            左数组的第一个元素的索引
 * @param center
 *            左数组的最后一个元素的索引,center+1是右数组第一个元素的索引
 * @param right
 *            右数组最后一个元素的索引
 */
public static void merge(int[] data, int left, int center, int right) {
    // 临时数组
    int[] tmpArr = new int[data.length];
    // 右数组第一个元素索引
    int mid = center + 1;
    // third 记录临时数组的索引
    int third = left;
    // 缓存左数组第一个元素的索引
    int tmp = left;
    while (left <= center && mid <= right) {
        // 从两个数组中取出最小的放入临时数组
        if (data[left] <= data[mid]) {
            tmpArr[third++] = data[left++];
        } else {
            tmpArr[third++] = data[mid++];
        }
    }
    // 剩余部分依次放入临时数组(`**实际上两个while只会执行其中一个**`)
    while (mid <= right) {
        tmpArr[third++] = data[mid++];
    }
    while (left <= center) {
        tmpArr[third++] = data[left++];
    }
    // 将临时数组中的内容拷贝回原数组中
    // (原left-right范围的内容被复制回原数组)
    while (tmp <= right) {
        data[tmp] = tmpArr[tmp++];
    }
}

public static void print(int[] data) {
    for (int i = 0; i < data.length; i++) {
        System.out.print(data[i] + "\t");
    }
    System.out.println();
}

}

猜你喜欢

转载自blog.csdn.net/u014207606/article/details/81945676