快速排序-双指针
public class Sort {
/**
* 快速排序API
*
* @param arr
*/
public void quickSort(int[] arr) {
quickSort(arr, 0, arr.length - 1);
}
/**
* 快速排序
*
* @param arr 数组
* @param start 起点
* @param end 终点
*/
private void quickSort(int[] arr, int start, int end) {
//边界
if (start >= end) {
return;
}
//基准元素下标
int pivotIdx = partition(arr, start, end);
//快速排序左半数组,即:数组[start,pivotIdx)
quickSort(arr, start, pivotIdx - 1);
//快速排序右半数组,即:数组(pivotIdx,end]
quickSort(arr, pivotIdx + 1, end);
}
/**
* 划分
*
* @param arr 数组
* @param start 起点
* @param end 终点
* @return
*/
private int partition(int[] arr, int start, int end) {
//基准
int pivot = arr[start];
//左右双指针
int l = start, r = end;
while (l != r) {
//右指针向左移动
while (l < r && arr[r] > pivot) {
r--;
}
//左指针向右移动
while (l < r && arr[l] <= pivot) {
l++;
}
if (l < r) {
swap(arr, l, r);
}
}
//注意:必然有 arr[l]<= arr[start]
swap(arr, start, l);
return l;
}
/**
* 交换
*
* @param arr 数组
* @param n n
* @param m m
*/
private void swap(int[] arr, int n, int m) {
int tmp = arr[n];
arr[n] = arr[m];
arr[m] = tmp;
}
}
快速排序-单边遍历
public class Sort {
/**
* 快速排序API
*
* @param arr
*/
public void quickSort(int[] arr) {
quickSort(arr, 0, arr.length - 1);
}
/**
* 快速排序
*
* @param arr 数组
* @param start 起点
* @param end 终点
*/
private void quickSort(int[] arr, int start, int end) {
//边界
if (start >= end) {
return;
}
//基准元素下标
int pivotIdx = partition(arr, start, end);
//快速排序左半数组,即:数组[start,pivotIdx)
quickSort(arr, start, pivotIdx - 1);
//快速排序右半数组,即:数组(pivotIdx,end]
quickSort(arr, pivotIdx + 1, end);
}
/**
* 划分
*
* @param arr 数组
* @param start 起点
* @param end 终点
* @return
*/
private int partition(int[] arr, int start, int end) {
//基准
int pivot = arr[start];
//左侧下标
int idx = start;
//单边遍历
for (int i = start + 1; i <= end; i++) {
if (arr[i] < pivot) {
idx++;
swap(arr, i, idx);
}
}
//注意: 必然有 arr[idx] <= arr[start]
swap(arr, idx, start);
return idx;
}
/**
* 交换
*
* @param arr 数组
* @param n n
* @param m m
*/
private void swap(int[] arr, int n, int m) {
int tmp = arr[n];
arr[n] = arr[m];
arr[m] = tmp;
}
}
冒泡排序
public class Sort {
public void bobbleSort(int[] arr) {
int len = arr.length;
if (len == 0) {
return;
}
//冒泡趟数 k
for (int k = 0; k < len - 1; k++) {
//单趟下标 idx
for (int idx = 0; idx < len - 1 - k; idx++) {
//交换相邻逆序两数
if (arr[idx] > arr[idx + 1]) {
swap(arr, idx, idx + 1);
}
}
}
}
/**
* 交换
*
* @param arr 数组
* @param n n
* @param m m
*/
private void swap(int[] arr, int n, int m) {
int tmp = arr[n];
arr[n] = arr[m];
arr[m] = tmp;
}
}
冒泡排序-优化(避免无交换冒泡趟数)
public class Sort {
public void bobbleSortAdv(int[] arr) {
int len = arr.length;
if (len == 0) {
return;
}
//冒泡趟数 k
for (int k = 0; k < len - 1; k++) {
//数组是否有序标记
boolean isSorted = true;
//单趟下标 idx
for (int idx = 0; idx < len - 1 - k; idx++) {
//交换相邻逆序两数
if (arr[idx] > arr[idx + 1]) {
swap(arr, idx, idx + 1);
//本趟交换了则意味着数组任然可能逆序
isSorted = false;
}
}
if (isSorted) {
break;
}
}
}
/**
* 交换
*
* @param arr 数组
* @param n n
* @param m m
*/
private void swap(int[] arr, int n, int m) {
int tmp = arr[n];
arr[n] = arr[m];
arr[m] = tmp;
}
}
冒泡排序-优化(逐步缩小排序范围)
public class Sort {
public void bobbleSortAdv(int[] arr) {
int len = arr.length;
if (len == 0) {
return;
}
//最后交换位置
int lastExchangeIdx = 0;
//排序边界
int sortBorder = len - 1;
//冒泡趟数 k
for (int k = 0; k < len - 1; k++) {
//数组是否有序标记
boolean isSorted = true;
//单趟下标 idx 范围 0至sortBorder
for (int idx = 0; idx < sortBorder; idx++) {
//交换相邻逆序两数
if (arr[idx] > arr[idx + 1]) {
swap(arr, idx, idx + 1);
//本趟交换了则意味着数组任然可能逆序
isSorted = false;
//修改最后交换位置
lastExchangeIdx = idx;
}
}
//缩小排序边界
sortBorder = lastExchangeIdx;
if (isSorted) {
break;
}
}
}
/**
* 交换
*
* @param arr 数组
* @param n n
* @param m m
*/
private void swap(int[] arr, int n, int m) {
int tmp = arr[n];
arr[n] = arr[m];
arr[m] = tmp;
}
}
冒泡排序-单链表
public class Sort {
/**
* 链表节点
*/
public static class Node {
int val;
Node next;
Node(int val) {
this.val = val;
}
}
Node bobbleSort(Node node) {
if (node == null) {
return null;
}
//冒泡结束标记
Node tail = null;
//冒泡趟数控制
while (tail != node.next) {
//前一节点 当前节点 后一节点
Node preNode = null, curNode = node, nextNode = node.next;
//单趟冒泡
while (nextNode != tail) {
if (curNode.val > nextNode.val) {
//交换节点
curNode.next = nextNode.next;
nextNode.next = curNode;
if (preNode == null) {
//修改首节点指针
node = nextNode;
} else {
preNode.next = nextNode;
}
//移动指针
preNode = nextNode;
nextNode = curNode.next;
continue;
}
//移动指针
preNode = curNode;
curNode = nextNode;
nextNode = nextNode.next;
}
//修改本趟冒泡尾标记
tail = curNode;
}
return node;
}
}
冒泡排序-鸡尾酒排序
public class Sort {
/**
* 鸡尾酒排序-冒泡排序变体
*
* @param arr
*/
public void cockTailSort(int[] arr) {
int len = arr.length;
if (len == 0) {
return;
}
//趟数 k
for (int k = 0; k < len / 2; k++) {
//有序标记
boolean isSorted = true;
for (int idx = k; idx < len - 1 - k; idx++) {
if (arr[idx] > arr[idx + 1]) {
swap(arr, idx, idx + 1);
isSorted = false;
}
}
//判断是否已经有序
if (isSorted) {
break;
}
isSorted = true;
for (int idx = len - 1 - k; idx > k; idx--) {
if (arr[idx] < arr[idx - 1]) {
swap(arr, idx, idx - 1);
isSorted = false;
}
}
//判断是否已经有序
if (isSorted) {
break;
}
}
}
/**
* 交换
*
* @param arr 数组
* @param n n
* @param m m
*/
private void swap(int[] arr, int n, int m) {
int tmp = arr[n];
arr[n] = arr[m];
arr[m] = tmp;
}
}
冒泡排序-鸡尾酒排序优化(逐步缩小排序范围)
public class Sort {
/**
* 鸡尾酒排序-冒泡排序变体
*
* @param arr
*/
public void cockTailSortAdv(int[] arr) {
int len = arr.length;
if (len == 0) {
return;
}
int leftExchange = -1, rightExchange = -1;
//排序左右边界
int leftSortBorder = 0, rightSortBorder = len - 1;
//趟数 k
for (int k = 0; k < len / 2; k++) {
//有序标记
boolean isSorted = true;
for (int idx = leftSortBorder; idx < rightSortBorder; idx++) {
if (arr[idx] > arr[idx + 1]) {
swap(arr, idx, idx + 1);
isSorted = false;
rightExchange = idx;
}
}
//判断是否已经有序
if (isSorted) {
break;
}
rightSortBorder = rightExchange;
isSorted = true;
for (int idx = rightSortBorder; idx > leftSortBorder; idx--) {
if (arr[idx] < arr[idx - 1]) {
swap(arr, idx, idx - 1);
isSorted = false;
leftExchange = idx;
}
}
//判断是否已经有序
if (isSorted) {
break;
}
leftSortBorder = leftExchange;
}
}
/**
* 交换
*
* @param arr 数组
* @param n n
* @param m m
*/
private void swap(int[] arr, int n, int m) {
int tmp = arr[n];
arr[n] = arr[m];
arr[m] = tmp;
}
}
计数排序
public class Sort {
public int[] countSort(int[] arr) {
int len = arr.length;
if (len == 0) {
return new int[0];
}
//数列最大、最小值
int max = arr[0], min = arr[0];
for (int idx = 1; idx < len; idx++) {
if (max < arr[idx]) {
max = arr[idx];
}
if (min > arr[idx]) {
min = arr[idx];
}
}
//计数表
int[] cnt = new int[max - min + 1];
for (int idx = 0; idx < len; idx++) {
cnt[arr[idx] - min]++;
}
//计数表 -> 顺位表
for (int idx = 1; idx < cnt.length; idx++) {
cnt[idx] += cnt[idx - 1];
}
//逆序遍历原数组(保证相同数值的两数顺位)
int[] res = new int[len];
for (int idx = len - 1; idx >= 0; idx--) {
res[cnt[arr[idx] - min] - 1] = arr[idx];
cnt[arr[idx] - min]--;
}
return res;
}
}
桶排序
public class Sort {
public double[] bucketSort(double[] arr) {
int len = arr.length;
if (len == 0) {
return new double[0];
}
//最大最小值
double max = arr[0], min = arr[0];
for (int idx = 1; idx < len; idx++) {
if (min > arr[idx]) {
min = arr[idx];
}
if (max < arr[idx]) {
max = arr[idx];
}
}
//桶 桶的数目等于数组长度,则最悲观情况下一个桶一个元素
List<LinkedList<Double>> bucket = new ArrayList<>(len);
for (int idx = 0; idx < len; idx++) {
bucket.add(new LinkedList<>());
}
//元素置入桶中
for (int idx = 0; idx < len; idx++) {
//桶编号
int num = (int) ((arr[idx] - min) * (len-1) / (max - min));
bucket.get(num).add(arr[idx]);
}
//桶内排序
for (int idx = 0; idx < len; idx++) {
Collections.sort(bucket.get(idx));
}
//构建结果集
double[] res = new double[len];
int idx = 0;
for (LinkedList<Double> l : bucket) {
for (double e : l) {
res[idx++] = e;
}
}
return res;
}
}
未完待续...