1. 冒泡排序
- 理论:
- 比较相邻的元素。如果前一个元素比后一个元素大,就交换这两个元素的位置
- 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对元素。最终最后位置的元素就是最大值。
- 演示:
- 代码实现:
package com.tiger.study.DataStructure.Sort;
public class BubbleSort {
public static void sort(Comparable[] a) {
for (int i = a.length - 1; i > 0; i--) {
for (int j = 0; j < i; j++) {
if (greater(a[j], a[j + 1])) {
exch(a, j, j + 1);
}
}
}
}
private static boolean greater(Comparable v, Comparable w) {
return v.compareTo(w) > 0;
}
private static void exch(Comparable[] a, int i, int j) {
Comparable temp;
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
2. 选择排序
- 理论:
- 每次遍历的过程中,都假定第一个索引处的元素是最小值,和其他索引处的值依次进行比较,如果当前索引处的值大于其他某个索引处的值,则假定其他某个索引处的值为最小值,最后可以找到最小值所在的索引。
- 交换第一个索引处和最小值所在的索引处的值
- 演示:
- 代码实现:
package com.tiger.study.DataStructure.Sort;
public class SelectSort {
public static void sort(Comparable[] a) {
for (int i = 0; i < a.length - 1; i++) {
int minIndex = i;
for (int j = i + 1; j < a.length; j++) {
if (greater(a[minIndex], a[j])) {
minIndex = j;
}
}
exch(a, minIndex, i);
}
}
private static boolean greater(Comparable v, Comparable w) {
return v.compareTo(w) > 0;
}
private static void exch(Comparable[] a, int i, int j) {
Comparable temp;
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
3. 插入排序
- 理论:
- 把所有元素分为两组,已经排序和未排序的
- 找到未排序的组中的第一个元素,向已经排序的组中进行插入
- 倒叙遍历已经排序的元素,依次和待插入元素进行比较,直到找到一个元素小于等于待插入元素,那么就把待插入元素放到这个位置,其他元素向后移动一位。
- 演示:
- 代码实现:
package com.tiger.study.DataStructure.Sort;
public class InsertSort {
public static void sort(Comparable[] a) {
for (int i = 1; i < a.length; i++) {
for (int j = i; j > 0; j--) {
if (greater(a[j - 1], a[j])) {
exch(a, j - 1, j);
} else {
break;
}
}
}
}
private static boolean greater(Comparable v, Comparable w) {
return v.compareTo(w) > 0;
}
private static void exch(Comparable[] a, int i, int j) {
Comparable temp;
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
4. 希尔排序
- 理论:
- 选定要给增长量h,按照增长量h作为数据分组的依据对数据进行分组
- 对分好组的每一组数据完成插入排序
- 减小增长量,最小减为1,重复第二步操作
- 演示:
- 代码演示(包含了增长量的确定和减小规则):
package com.tiger.study.DataStructure.Sort;
public class ShellSort {
public static void sort(Comparable[] a) {
int h = getH(a.length);
while (h >= 1) {
for (int i = h; i < a.length; i++) {
for (int j = i; j >= h; j-=h) {
if (greater(a[j - h], a[j])) {
exch(a, j - h, j);
} else {
break;
}
}
}
h = h / 2;
}
}
public static int getH(int len) {
int h = 1;
while (h < (len / 2)) {
h = 2 * h + 1;
}
return h;
}
private static boolean greater(Comparable v, Comparable w) {
return v.compareTo(w) > 0;
}
private static void exch(Comparable[] a, int i, int j) {
Comparable temp;
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
5. 归并排序
- 原理:
- 尽可能的一组数据拆分成两个元素相等的子组,并对每一个子组继续拆分,直到拆分后每一个子组元素个数为1
- 将相邻的两个子组进行合并成一个有序的大组
- 不断重复步骤2,直到最终只有一个组为止
- 演示:
- 代码演示:
package com.tiger.study.DataStructure.Sort;
public class MergeSort {
public static void main(String[] args) {
int[] arr = {24, 17, 40, 28, 13, 14, 22, 32, 40, 21, 48, 4, 47, 8, 37, 18};
int[] result = new int[arr.length];
mergeSort(arr, 0, arr.length - 1, result);
for (int i = 0; i < result.length; i++) {
System.out.println(result[i]);
}
}
private static void mergeSort(int[] arr, int left, int right, int[] result) {
if (right == left) return;
int mid = (right + left) / 2;
mergeSort(arr, left, mid, result);
mergeSort(arr, mid + 1, right, result);
merge(arr, left, right, result);
}
private static void merge(int[] arr, int left, int right, int[] result) {
int mid = (right + left) / 2;
int left_head = left, right_head = mid + 1, result_index = left;
while (left_head <= mid && right_head <= right) {
if (arr[left_head] <= arr[right_head]) {
result[result_index++] = arr[left_head++];
} else {
result[result_index++] = arr[right_head++];
}
}
if (left_head <= mid) {
for (int i = left_head; i <= mid; i++) {
result[result_index++] = arr[i];
}
}
if (right_head <= right) {
for (int i = right_head; i <= right; i++) {
result[result_index++] = arr[i];
}
}
for (int i = left; i <= right; i++) {
arr[i] = result[i];
}
}
}
6. 快速排序
- 原理
- 首先设定一个分界值,通过该分界值将数组分为左右两个部分
- 将大于或等于分界值的数据放到数组右边,小于分界值的数据放到数组的左边。此时左边部分各个元素都小于或等于分界值,而右边部分中各个元素都大于或等于分界值
- 然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。
- 重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左侧和右侧两个部分的数据排完序后,整个数组的排序也就完成了
- 演示
- 代码实现
package com.tiger.study.DataStructure.Sort;
import java.util.Random;
public class QuickSort {
public static void main(String[] args) {
int[] arr = {2, 6, 7, 1, 3, 5, 6, 4};
quickSort(arr, 0, arr.length - 1);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
System.out.println("=====");
quickSortRandom(arr, 0, arr.length - 1);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
private static void quickSort(int[] arr, int left, int right) {
if (left >= right) return;
int mainEleIndex = partition(arr, left, right);
quickSort(arr, left, mainEleIndex - 1);
quickSort(arr, mainEleIndex + 1, right);
}
private static int partition(int[] arr, int left, int right) {
int mainEleIndex = right;
int i = left - 1, j = left;
while (j < right) {
if (arr[mainEleIndex] > arr[j]) {
int temp = arr[i + 1];
arr[i + 1] = arr[j];
arr[j] = temp;
j++;
i++;
} else {
j++;
}
}
int temp = arr[i + 1];
arr[i + 1] = arr[mainEleIndex];
arr[mainEleIndex] = temp;
return i + 1;
}
private static void quickSortRandom(int[] arr, int left, int right) {
if (left >= right) return;
int mainEleIndex = partitionRandom(arr, left, right);
quickSort(arr, left, mainEleIndex - 1);
quickSort(arr, mainEleIndex + 1, right);
}
private static int partitionRandom(int[] arr, int left, int right) {
Random random = new Random();
int mainEleIndex = left + random.nextInt(right - left + 1);
int i = left - 1, j = left;
while (j < right) {
if (arr[mainEleIndex] > arr[j]) {
int temp = arr[i + 1];
arr[i + 1] = arr[j];
arr[j] = temp;
j++;
i++;
} else {
j++;
}
}
int temp = arr[i + 1];
arr[i + 1] = arr[mainEleIndex];
arr[mainEleIndex] = temp;
return i + 1;
}
}