1. 选择排序、插入排序、冒泡排序
选择排序
The selection sort algorithm sorts an array by repeatedly finding the minimum element (considering ascending order) from unsorted part
and putting it at the beginning. The algorithm maintains two subarrays
in a given array.1) The subarray which is already sorted.
2) Remaining subarray which
is unsorted.
选择排序(升序时):左边为已排序数组,右边未排序。每次排序时,选择当前最小的元素。
```
/**
* @param arr
* @author fqyuan
* @see 这里的swap操作在第二层循环之外,减少了交换的次数,改善了部分性能。
*/
public static void selectSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
int minIndex = i;
for (int j = i + 1; j < arr.length; j++) {
if (arr[minIndex] > arr[j])
minIndex = j;
}
swap(arr, minIndex, i);
}
}
插入排序
Insertion sort is an in-place comparison-based sorting algorithm. Here, a sub-list is maintained which is always sorted. For example, the lower part of an array is maintained to be sorted. An element which is to be inserted into this sorted sub-list, has to find its appropriate place and then it has to be inserted there. Hence the name, insertion sort.
插入排序:是一个基于比较的排序算法。该算法维护一个已排序子数列,将待插入元素插入到已排序子数列中的算法。关键在于找到要插入点的位置,这也是‘插入排序’为该名称的缘由。
/**
* @param arr
* @author fqyuan
* @see A little twisted among the 3 simple sort method:
* select/insert/bubble.
*/
public static void insertSort(int[] arr) {
for (int i = 1; i < arr.length; i++) {
int key = arr[i];
int j = i - 1;
// Find the position to insert at: j.
for (; j >= 0 && arr[j] > key; j--)
arr[j + 1] = arr[j];
arr[j + 1] = key;
}
}
冒泡排序
Bubble sort: this is the simplest sorting algorithm that works by repeatedly swapping the adjacent elements if they are in wrong order.
冒泡排序:冒泡排序也是一种基于比较的排序算法,通过比较相邻元素如果非升序则进行交换。该算法性能表现较差,因为其平均复杂度和最差情况复杂度都是O(n^2).
/**
* @param arr
* @author fqyuan
* @see 加入了sorted flag之后,如果是已经排序好的数组,可以大幅减少排序swap次数。
*/
public static void bubbleSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
boolean sorted = true;
for (int j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
swap(arr, j, j + 1);
sorted = false;
}
}
if (sorted)
break;
}
}
2. 归并排序 Merge Sort
Merge sort is a sorting technique based on divide and conquer technique. With worst-case time complexity being O(nlognn), it’s one of the most respected algorithm.
Three steps in total to complete the merge sort.
1. If only one element in the list, it’s already sorted, return.
2. Divide the list recursively into two halves until it can no longer be divided.
3. merge the smaller lists into new list in sorted order.
归并排序:是一种采用‘分治策略’的排序算法,该算法用递归的方式将数组分为小的单元,直至不可分,采用然后将小的单元进行归并处理merge处理。
1. 判断数组元素是否只有一个,如果是,则该数组已经有序,退出。
2. 递归地将数组分为2个部分,直至该数组不在可分为止。
3. 将小的数组归并到一个新的数组中。
public static void mergeSort(int[] arr) {
if (arr.length < 2)
return;
int mid = arr.length / 2;
int[] left = new int[arr.length / 2];
int[] right = new int[arr.length - mid];
for (int i = 0; i < mid; i++)
left[i] = arr[i];
for (int i = mid; i < arr.length; i++)
right[i - mid] = arr[i];
mergeSort(left);
mergeSort(right);
merge(left, right, arr);
}
private static void merge(int[] left, int[] right, int[] arr) {
int nL = left.length;
int nR = right.length;
int i = 0, j = 0, k = 0;
while (i < nL && j < nR) {
if (left[i] <= right[j])
arr[k++] = left[i++];
else
arr[k++] = right[j++];
}
if (i < nL) {
while (i < nL)
arr[k++] = left[i++];
} else {
while (j < nR)
arr[k++] = right[j++];
}
}
3. 快速排序 Quick Sort
Quick sort is a highly efficient sorting algorithm and is based on
partitioning of array of data into smaller arrays. A large array is
partitioned into two arrays one of which holds values smaller than the
specified value, say pivot, based on which the partition is made and
another array holds values greater than the pivot value.Quick sort partitions an array and then calls itself recursively twice
to sort the two resulting subarrays. This algorithm is quite efficient
for large-sized data sets as its average and worst case complexity are
of Ο(n2), where n is the number of items.快速排序:一种高效的排序算法,通过把待排序数组分为更小的数组进行排序的方式。排序数组被分为2个数组,其中之一所包含的值小于一个给定的值pivotValue, 另一个子数组所包含的值大于给定的值pivotValue。
public static void quickSort(int arr[]) {
quickSort(arr, 0, arr.length - 1);
}
private static void quickSort(int[] arr, int startIndex, int endIndex) {
if (startIndex < endIndex) {
// int pivot = randomizePartiton(arr, startIndex, endIndex);
int pivot = partition(arr, startIndex, endIndex);
quickSort(arr, startIndex, pivot - 1);
quickSort(arr, pivot + 1, endIndex);
}
}
private static int randomizePartiton(int[] arr, int startIndex, int endIndex) {
int randomIndex = (int) Math.floor((Math.random() * (endIndex - startIndex + 1) + startIndex));
swap(arr, randomIndex, endIndex);
return partition(arr, startIndex, endIndex);
}
private static int partition(int arr[], int startIndex, int endIndex) {
// Randomize the pivot.
int randomIndex = (int) Math.floor((Math.random() * (endIndex - startIndex + 1) + startIndex));
swap(arr, randomIndex, endIndex);
int pivotValue = arr[endIndex];
int pivotIndex = startIndex;
for (int i = startIndex; i < endIndex; i++) {
if (arr[i] < pivotValue) {
swap(arr, i, pivotIndex);
pivotIndex++;
}
}
swap(arr, pivotIndex, endIndex);
return pivotIndex;
}
private static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
4. 完整代码及运行结果
package com.fqyuan.sort;
import java.util.Random;
import org.junit.Test;
public class SortUtils {
/**
* @param arr
* @author fqyuan
* @see 这里的swap操作在第二层循环之外,减少了交换的次数,改善了部分性能。
*/
public static void selectSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
int minIndex = i;
for (int j = i + 1; j < arr.length; j++) {
if (arr[minIndex] > arr[j])
minIndex = j;
}
swap(arr, minIndex, i);
}
}
/**
* @param arr
* @author fqyuan
* @see 加入了sorted flag之后,如果是已经排序好的数组,可以大幅减少排序swap次数。
*/
public static void bubbleSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
boolean sorted = true;
for (int j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
swap(arr, j, j + 1);
sorted = false;
}
}
if (sorted)
break;
}
}
/**
* @param arr
* @author fqyuan
* @see A little twisted among the 3 simple sort method:
* select/insert/bubble.
*/
public static void insertSort(int[] arr) {
for (int i = 1; i < arr.length; i++) {
int key = arr[i];
int j = i - 1;
// Find the position to insert at: j.
for (; j >= 0 && arr[j] > key; j--)
arr[j + 1] = arr[j];
arr[j + 1] = key;
}
}
public static void mergeSort(int[] arr) {
if (arr.length < 2)
return;
int mid = arr.length / 2;
int[] left = new int[arr.length / 2];
int[] right = new int[arr.length - mid];
for (int i = 0; i < mid; i++)
left[i] = arr[i];
for (int i = mid; i < arr.length; i++)
right[i - mid] = arr[i];
mergeSort(left);
mergeSort(right);
merge(left, right, arr);
}
private static void merge(int[] left, int[] right, int[] arr) {
int nL = left.length;
int nR = right.length;
int i = 0, j = 0, k = 0;
while (i < nL && j < nR) {
if (left[i] <= right[j])
arr[k++] = left[i++];
else
arr[k++] = right[j++];
}
if (i < nL) {
while (i < nL)
arr[k++] = left[i++];
} else {
while (j < nR)
arr[k++] = right[j++];
}
}
public static void quickSort(int arr[]) {
quickSort(arr, 0, arr.length - 1);
}
private static void quickSort(int[] arr, int startIndex, int endIndex) {
if (startIndex < endIndex) {
// int pivot = randomizePartiton(arr, startIndex, endIndex);
int pivot = partition(arr, startIndex, endIndex);
quickSort(arr, startIndex, pivot - 1);
quickSort(arr, pivot + 1, endIndex);
}
}
private static int randomizePartiton(int[] arr, int startIndex, int endIndex) {
int randomIndex = (int) Math.floor((Math.random() * (endIndex - startIndex + 1) + startIndex));
swap(arr, randomIndex, endIndex);
return partition(arr, startIndex, endIndex);
}
private static int partition(int arr[], int startIndex, int endIndex) {
// Randomize the pivot.
int randomIndex = (int) Math.floor((Math.random() * (endIndex - startIndex + 1) + startIndex));
swap(arr, randomIndex, endIndex);
int pivotValue = arr[endIndex];
int pivotIndex = startIndex;
for (int i = startIndex; i < endIndex; i++) {
if (arr[i] < pivotValue) {
swap(arr, i, pivotIndex);
pivotIndex++;
}
}
swap(arr, pivotIndex, endIndex);
return pivotIndex;
}
private static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public void printArr(int arr[]) {
// for (int val : arr)
// System.out.print(val + " ");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
if ((i + 1) % 10 == 0)
System.out.println();
}
System.out.println();
}
@Test
public void test() {
// selectSort time test.
long start = System.currentTimeMillis();
Random random = new Random();
int[] arr = new int[100000];
for (int i = 0; i < arr.length; i++)
arr[i] = random.nextInt(100000);
// printArr(arr);
selectSort(arr);
// printArr(arr);
long end = System.currentTimeMillis();
System.out.println("Select Sort -- time taken is: " + (end - start) + "ms");
// insertSort time test
start = System.currentTimeMillis();
arr = new int[100000];
for (int i = 0; i < arr.length; i++)
arr[i] = random.nextInt(100000);
// printArr(arr);
insertSort(arr);
// printArr(arr);
end = System.currentTimeMillis();
System.out.println("Insert Sort -- time taken is: " + (end - start) + "ms");
// bubbleSort time test
start = System.currentTimeMillis();
arr = new int[100000];
for (int i = 0; i < arr.length; i++)
arr[i] = random.nextInt(100000);
// printArr(arr);
bubbleSort(arr);
// printArr(arr);
end = System.currentTimeMillis();
System.out.println("Bubble Sort -- time taken is: " + (end - start) + "ms");
// mergeSort time test
start = System.currentTimeMillis();
arr = new int[100000];
for (int i = 0; i < arr.length; i++)
arr[i] = random.nextInt(100000);
// printArr(arr);
mergeSort(arr);
// printArr(arr);
end = System.currentTimeMillis();
System.out.println("Merge Sort -- time taken is: " + (end - start) + "ms");
// quickSort time test
start = System.currentTimeMillis();
arr = new int[100000];
for (int i = 0; i < arr.length; i++)
arr[i] = random.nextInt(100000);
// printArr(arr);
quickSort(arr);
// printArr(arr);
end = System.currentTimeMillis();
System.out.println("Quick Sort -- time taken is: " + (end - start) + "ms");
}
@Test
public void test1() {
Random random = new Random();
int[] arr = new int[100];
for (int i = 0; i < 100; i++) {
arr[i] = random.nextInt(100);
}
printArr(arr);
quickSort(arr);
printArr(arr);
}
}
//Running result:
Select Sort -- time taken is: 2585ms
Insert Sort -- time taken is: 2936ms
Bubble Sort -- time taken is: 14472ms
Merge Sort -- time taken is: 53ms
Quick Sort -- time taken is: 15ms