这篇文章主要介绍常见的排序算法,图片来源于网络,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();
}
}