排序算法
冒泡排序
说明
冒泡排序是交换类的排序算法,它的排序是通过一系列的交换动作完成的.
它会依次比较相邻的元素之间的值的大小,以升序排序,如果前边的值大于后边的值,则交换这两个相邻的元素的值.每一轮都会有一个较大值移动到后面,经过n-1轮排序,最终整个数组变成一个有序数组.
时间复杂度 O(n^2)
最好情况下的时间复杂度 O(n)
代码实现
public void bubbleSort(int[] arr) {
int temp = 0;
boolean flag = false;
for (int i = 0; i < arr.length - 1; i++) {
flag = false;
for (int j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
flag = true;
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
if (!flag) {
break;
}
}
}
选择排序
说明
选择和冒泡有些类似,从头至尾扫描整个数组,找出最小的元素和前边的第一个元素交换,接着从剩下的元素中
继续这种选择和交换,最终使整个数组有序.
代码实现
public void selectSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
int min = arr[i];
for (int j = i + 1; j < arr.length; j++) {
if (min > arr[j]) {
arr[i] = arr[j];
arr[j] = min;
min = arr[i];
}
}
}
}
插入排序
说明
我这里的插入排序借助于一个临时数组实现的,
将原数组的第一个元素存入到这个临时数组中,临时数组中只有一个元素,那么它也是一个有序序列.
循环原数组的所有元素,每一次都会将原数组中的一个元素插入到有序序列的适当位置上去,直到原数组的所有元素都插入到了临时数组为止.
代码实现
public int[] insertSort(int[] arr) {
int[] newArr = new int[arr.length];
System.arraycopy(arr, 0, newArr, 0, 1);
int index = 0;
int value = 0;
for (int i = 1; i < arr.length; i++) {
index = i - 1;
value = arr[i];
while (index >= 0 && value < newArr[index]) {
newArr[index + 1] = newArr[index];
index--;
}
newArr[index + 1] = value;
}
return newArr;
}
希尔排序
说明
希尔排序又叫缩小增量排序,其本质还是插入排序,其实现就是将整个待排序的序列分为若干个子序列,
分别对这若干个子序列进行插入排序,每一趟排序都会让整个序列更加有序,最后一次排序就是在整个序列基本有序的情况下进行一次插入排序,效率非常高.
代码实现
public void shelloSort(int[] arr) {
int temp = 0;
for (int step = arr.length / 2; step > 0; step /= 2) {
for (int i = step; i < arr.length; i++) {
for (int j = i - step; j >= 0; j -= step) {
if (arr[j] > arr[j + step]) {
temp = arr[j];
arr[j] = arr[j + step];
arr[j + step] = temp;
}
}
}
}
}
public void shelloSortInsert(int[] arr) {
int insertIndex = 0;
int value = 0;
for (int step = arr.length / 2; step > 0; step /= 2) {
for (int i = step; i < arr.length; i++) {
insertIndex = i;
value = arr[i];
if (arr[insertIndex] < arr[insertIndex - step]) {
while (insertIndex - step >= 0 && value < arr[insertIndex - step]) {
arr[insertIndex] = arr[insertIndex - step];
insertIndex -= step;
}
arr[insertIndex] = value;
}
}
}
}
快速排序
说明
快速排序属于交换排序的一种.
执行流程:
每一轮选取一个随机元素(头元素或者尾都可以)作为枢轴(pivot),将序列中比枢轴小的元素移动到枢轴左边
比枢轴大的元素移动到枢轴后边,当本轮的排序完成后,就可以得到一组更短的子序列(也有可能只有一个子序列),它们将成为下一轮排序的初始序列.
代码实现
public void quickSort(int[] arr, int left, int right) {
int l = left;
int r = right;
if (l >= r) {
return;
}
int pivot = arr[l];
while (l < r) {
while (l < r && arr[r] >= pivot) {
r--;
}
if (l < r) {
arr[l] = arr[r];
l++;
}
while (l < r && arr[l] < pivot) {
l++;
}
if (l < r) {
arr[r] = arr[l];
r--;
}
if (l == r) {
arr[l] = pivot;
}
}
if (r > left) {
quickSort(arr, left, l - 1);
}
if (l < right) {
quickSort(arr, l + 1, right);
}
}
归并排序
说明
归并排序,归并排序使用的就是分治法,将一个序列分解成两个子序列,每一个子序列还可以继续分成两个子序列,直到只有一个元素时才停止,最终将排好序的子序列合并得到一个有序序列.
代码实现
public void mergeSort(int[] arr, int[] temp, int left, int right) {
if (left < right) {
int mid = (left + right) / 2;
mergeSort(arr, temp, left, mid);
mergeSort(arr, temp, mid + 1, right);
merge(arr, temp, left, right, mid);
}
}
public void merge(int[] arr, int[] temp, int left, int right, int mid) {
int l = left;
int r = mid + 1;
int tempIndex = 0;
while (l <= mid && r <= right) {
if (arr[l] < arr[r]) {
temp[tempIndex++] = arr[l++];
} else {
temp[tempIndex++] = arr[r++];
}
}
while (l <= mid) {
temp[tempIndex++] = arr[l++];
}
while (r <= right) {
temp[tempIndex++] = arr[r++];
}
tempIndex = 0;
l = left;
while (l <= right) {
arr[l++] = temp[tempIndex++];
}
}
基数排序
说明
基数排序就是典型的空间换时间策略.
核心就是分配和收集,分配就是将每个元素分配到它的指定位数的值对应的桶中,
核心思想:
将所有的待排序元素看做是拥有同样数位长度的元素,数位较短的前面补0,然后从最低位开始,依次进行排序,
位数的值就对应着元素应该被分配到哪个桶中,每一轮排序过后在重新按照桶的顺序收集,就这样从最低位的比较到最高位的比较完成之后,整个序列就是一个有序序列了.
代码实现
public void radixSort(int[] arr) {
int[][] buckets = new int[10][arr.length];
int[] bucketIndex = new int[10];
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
int maxLength = (max + "").length();
int base = 1;
int tempValue = 0;
while (maxLength-- > 0) {
int arrIndex = 0;
for (int i = 0; i < arr.length; i++) {
tempValue = arr[i] / base % 10;
buckets[tempValue][bucketIndex[tempValue]] = arr[i];
bucketIndex[tempValue] = ++bucketIndex[tempValue];
}
for (int i = 0; i < buckets.length; i++) {
if (bucketIndex[i] >= 0) {
for (int j = 0; j < bucketIndex[i]; j++) {
arr[arrIndex++] = buckets[i][j];
}
}
}
Arrays.fill(bucketIndex, 0);
base *= 10;
}
}