前言
这里的博客主要是想将学习的排序算法的代码复习记录一下。
一、插入排序
//插入排序
public void insertSort(int[] arr) {
for (int i = 1; i < arr.length; i++) {
int temp = arr[i];
int j = i - 1;
for (; j >= 0; j--) {
if (temp < arr[j]) {
arr[j + 1] = arr[j];
} else {
break;
}
}
arr[j + 1] = temp;
}
}
二、希尔排序
public void shellSort(int[] arr) {
int gap = arr.length;
while (gap > 1) {
gap /= 2;
shell(arr, gap);
}
}
public void shell(int[] arr, int gap) {
for (int i = gap; i < arr.length; i ++) {
int temp = arr[i];
int j = i - gap;
for (; j >= 0; j -= gap) {
if (arr[j] > temp) {
arr[j + gap] = arr[j];
} else {
break;
}
}
arr[gap + j] = temp;
}
}
三、选择排序
//选择排序
public void selectSort(int[] arr) {
for (int i = 0; i < arr.length; i++) {
int min = i;
for (int j = i + 1; j < arr.length; j++) {
if (arr[j] < arr[i]) {
min = j;
}
}
swap(arr, i, min);
}
}
public void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
四、堆排序
public void headSort(int[] arr) {
createHeap(arr);
int end = arr.length - 1;
while (end > 0) {
swap(arr, 0, end);
siftDown(arr, 0, end);
end--;
}
}
public void createHeap(int[] arr) {
for (int i = (arr.length - 2) / 2; i >= 0; i--) {
siftDown(arr, i, arr.length);
}
}
public void siftDown(int[] arr, int parent, int end) {
int child = 2 * parent + 1;
while (child < end) {
if (child + 1 < end && arr[child] < arr[child + 1])
child++;
}
if (arr[child] > arr[parent]) {
swap(arr, child, parent);
parent = child;
child = parent * 2 + 1;
}
}
}
五、冒泡排序
public void bubbleSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
boolean flg = true;
for (int j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
flg = false;
swap(arr, j, j + 1);
}
}
if (flg) {
return ;
}
}
}
六、快速排序
递归方法:
//快排
public void quickSort(int[] arr) {
quick(arr, 0, arr.length - 1);
}
public void quick(int[] arr, int start, int end) {
if (start >= end) {
return;
}
//这里用到了插入排序,因为插入排序在待排序数据接近有序时,排序速度比较快
//当快排达到以下条件时说明数据已经快接近有序了,这是就可以直接使用插入排序来提升速度
if (end - start + 1 < 10) {
insertSortForQ(arr, start, end);
return;
}
//这里是将start、end以及它们的中位数mid指向的元素进行比较选出中间值作为基准进行快排
//这样可以使排序结构尽量接近二叉树从而提高排序效率
int index = getMidNumIndex(arr, start, end);
swap(arr, index, start);
int pivot = partition(arr, start, end);
quick(arr, start, pivot - 1);
quick(arr, pivot + 1, end);
}
public void insertSortForQ(int[] arr, int start, int end) {
for (int i = start + 1; i <= end; i++) {
int temp = arr[i];
int j = i - 1;
for (; j >= start; j--) {
if (arr[j] > temp) {
arr[j + 1] = arr[j];
} else {
break;
}
}
arr[j + 1] = temp;
}
}
//partition函数分为两种,这种为填坑法
public int partition(int[] arr, int left, int right) {
int temp = arr[left];
while (left < right) {
while (right > left && arr[right] >= temp) {
right--;
}
arr[left] = arr[right];
while (left < right && arr[left] <= temp) {
left++;
}
arr[right] = arr[left];
}
arr[left] = temp;
return left;
}
//另一种为Hoare法
public int partitionHoare(int[] arr, int left, int right) {
int temp = arr[left];
while (left < right) {
while (left < right && arr[right] >= temp) {
right--;
}
while (left < right && arr[left] <= temp) {
left++;
}
swap(arr, left, right);
}
swap(arr, 0, left);
return left;
}
public int getMidNumIndex(int[] arr, int left, int right) {
int mid = (right - left) / 2 + left;
if (arr[left] > arr[right]) {
if (arr[mid] > arr[left]) {
return left;
} else if (arr[mid] < arr[right]) {
return right;
} else {
return mid;
}
} else {
if (arr[mid] > arr[right]) {
return right;
} else if (arr[mid] < arr[left]) {
return left;
} else {
return mid;
}
}
}
非递归方法:
//快排非递归
public void quickSortNor(int[] arr) {
Stack<Integer> stack = new Stack<>();
int left = 0;
int right = arr.length - 1;
int pivot = partition(arr, left, right);
if (pivot - 1 > left) {
stack.push(left);
stack.push(pivot - 1);
}
if (right > pivot + 1) {
stack.push(pivot + 1);
stack.push(right);
}
while (!stack.isEmpty()) {
right = stack.pop();
left = stack.pop();
pivot = partition(arr, left, right);
if (pivot - 1 > left) {
stack.push(left);
stack.push(pivot - 1);
}
if (right > pivot + 1) {
stack.push(pivot + 1);
stack.push(right);
}
}
}
七、归并排序
递归方法:
//归并排序
public void mergeSort(int[] arr) {
merge(arr, 0, arr.length - 1);
}
public void merge(int[] arr, int start, int end) {
if (start >= end) {
return;
}
int mid = (end - start) / 2 + start;
merge(arr, start, mid);
merge(arr, mid + 1, end);
mergeFunc(arr, start, end, mid);
}
public void mergeFunc(int[] arr, int start, int end, int mid) {
int s1 = start;
int s2 = mid + 1;
int e1 = mid;
int e2 = end;
int[] newArr = new int[end - start + 1];
int index = 0;
while (s1 <= e1 && s2 <= e2) {
if (arr[s1] < arr[s2]) {
newArr[index] = arr[s1];
s1++;
index++;
} else {
newArr[index] = arr[s2];
s2++;
index++;
}
}
while (s1 <= e1) {
newArr[index] = arr[s1];
s1++;
index++;
}
while (s2 <= e2) {
newArr[index] = arr[s2];
s2++;
index++;
}
for (int i = 0; i < newArr.length; i++) {
arr[start + i] = newArr[i];
}
}
非递归方法:
public void mergeSortNor(int[] arr) {
int gap = 1;
while (gap < arr.length) {
for (int i = 0; i < arr.length; i += 2 * gap) {
int left = i;
int mid = left + gap - 1;
if (mid >= arr.length) {
mid = arr.length - 1;
}
int right = mid + gap;
if (right >= arr.length) {
right = arr.length - 1;
}
mergeFunc(arr, left, right, mid);
}
gap *= 2;
}
}
八、计数排序
//计数排序
public void countSort(int[] arr) {
int max = arr[0];
int min = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] < min) {
min = arr[i];
}
if (arr[i] > max) {
max = arr[i];
}
}
int[] newArr = new int[max - min + 1];
for (int i = 0; i < arr.length; i++) {
newArr[arr[i] - min] += 1;
}
int index = 0;
for (int i = 0; i < newArr.length; i++) {
int temp = newArr[i];
while (temp != 0) {
arr[index] = i + min;
index++;
temp--;
}
}
}