几种常见排序总结
冒泡排序
冒泡排序可以说是所有排序中最简单的排序,它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。
/**
* 冒泡法排序
* 需要排序的整型数组
*/
public static void bubbleSort01(int[] numbers) {
int temp; // 记录临时中间值
int size = numbers.length; // 数组大小
for (int i = 0; i < size - 1; i++) {
for (int j = i + 1; j < size; j++) {
if (numbers[i] < numbers[j]) { // 交换两数的位置
temp = numbers[i];
numbers[i] = numbers[j];
numbers[j] = temp;
}
}
}
}
插入排序
插入排序是由N-1趟排序组成,对于p=1到N-1趟,插入排序保证从0到p的元素都已排序状态。如图:
代码如下:
/**
* 插入排序
*
* @param a
* @param <AnyType>
*/
public static <AnyType extends Comparable<? super AnyType>> void insertionSort(AnyType[] a) {
int j;
for (int p = 1; p < a.length; p++) {
AnyType tmp = a[p];
for (j = p; j > 0 && tmp.compareTo(a[j - 1]) < 0; j--) {
a[j] = a[j - 1];
a[j - 1] = tmp;
}
}
for (AnyType i : a) {
System.out.print(i + " ");
}
}
选择排序
选择排序就是在未排序序列中找到最小元素,存放到排序序列的起始位置,再从剩余未排序元素中继续寻找最小元素,然后放到排序序列起始位置。以此类推,直到所有元素均排序完毕。
/**
* 选择排序
*
* @param numbers
*/
public static void selectSort(int[] numbers) {
int size = numbers.length;
int temp;
for (int i = 0; i < size; i++) {
int k = i;
for (int j = size - 1; j >i; j--) {
if (numbers[j] < numbers[k]) {
k = j;
}
}
temp = numbers[i];
numbers[i] = numbers[k];
numbers[k] = temp;
}
}
希尔排序
希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
具体流程如下:
1、将包含n个元素的数组,分成n/2个数组序列,第一个数据和第n/2+1个数据为一对…
2、对每对数据进行比较和交换,排好顺序;
3、然后分成n/4个数组序列,再次排序;
4、不断重复以上过程,随着序列减少并直至为1,排序完成。
/**
* 希尔排序
*
* @param a
* @param <AnyType>
*/
public static <AnyType extends Comparable<? super AnyType>> void shellSort(AnyType[] a) {
for (int gap = a.length / 2; gap > 0; gap /= 2) {
for (int i = gap; i < a.length; i++) {
AnyType tmp = a[i];
for (int j = i; j >= gap && tmp.compareTo(a[j - gap]) < 0; j -= gap) {
a[j] = a[j - gap];
a[j - gap] = tmp;
}
}
}
for (AnyType i : a) {
System.out.print(i + " ");
}
}
快速排序
快速排序是数列中挑出一个元素,称为“基准”,重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分割之后,该基准是它的最后位置。这个称为分割(partition)操作。递归地把小于基准值元素的子数列和大于基准值元素的子数列排序。
public static void quickSort(int[] numbers, int start, int end) {
if (start < end) {
int base = numbers[start]; // 选定的基准值(第一个数值作为基准值)
int temp; // 记录临时中间值
int i = start, j = end;
do {
while ((numbers[i] < base) && (i < end))
i++;
while ((numbers[j] > base) && (j > start))
j--;
if (i <= j) {
temp = numbers[i];
numbers[i] = numbers[j];
numbers[j] = temp;
i++;
j--;
}
} while (i <= j);
if (start < j)
quickSort(numbers, start, j);
if (end > i)
quickSort(numbers, i, end);
}
}
归并排序
归并排序简单的可理解为先将数组进行拆分出a,b将等分数组并将其进行初始排序,然后a,b进行比较,将数字小的值放入新数组c中,并将比较后大的值继续与其另一数组中的值进行比较,以此类推,如图所示:
最终输出数组C。
代码如下:
/**
* 归并排序
* @param a
* @param <AnyType>
*/
public static <AnyType extends Comparable<? super AnyType>> void mergeSort(AnyType[] a) {
AnyType[] tmpArray = (AnyType[]) new Comparable[a.length];
mergeSort(a, tmpArray, 0, a.length - 1);
System.out.print("归并排序结果为:" );
for (AnyType i : tmpArray) {
System.out.print(i + " ");
}
}
private static <AnyType extends Comparable<? super AnyType>> void mergeSort(AnyType[] a, AnyType[] tmpArray, int left, int right) {
if (left < right) {
int center = (left + right) / 2;
mergeSort(a, tmpArray, left, center);
mergeSort(a, tmpArray, center + 1, right);
merge(a, tmpArray, left, center + 1, right);
}
}
private static <AnyType extends Comparable<? super AnyType>> void merge(AnyType[] a, AnyType[] tmpArray, int leftPos, int rightPos, int rightEnd) {
int leftEnd = rightPos - 1;
int tmpPos = leftPos;
int numElements = rightEnd - leftPos + 1;
while (leftPos <= leftEnd && rightPos <= rightEnd) {
if (a[leftPos].compareTo(a[rightPos]) <= 0) {
tmpArray[tmpPos++] = a[leftPos++];
} else {
tmpArray[tmpPos++] = a[rightPos++];
}
}
while (leftPos <= leftEnd) {
tmpArray[tmpPos++] = a[leftPos++];
}
while (rightPos <= rightEnd) {
tmpArray[tmpPos++] = a[rightPos++];
}
for (int i = 0; i < numElements; i++, rightEnd--) {
a[rightEnd] = tmpArray[rightEnd];
}
}