冒泡排序
两个数比较大小,较大的数下沉,较小的数冒起来。
/**
* *冒泡排序
*
* @param nums
*/
public static void bubbleSort(int[] nums) {
for (int i = 0; i < nums.length; i++) {
boolean flag = false;
for (int j = 0; j < nums.length - 1 - i; j++) {
if (nums[j] > nums[j + 1]) {
int temp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = temp;
flag = true;
}
}
if (!flag) {
break;
}
}
}
选择排序
在长度为N的无序数组中,第一次遍历n-1个数,找到最小的数值与第一个元素交换;
第二次遍历n-2个数,找到最小的数值与第二个元素交换;
第n-1次遍历,找到最小的数值与第n-1个元素交换,排序完成
/**
* *选择排序
*
* @param nums
*/
public static void selectionSort(int[] nums) {
for (int i = 0; i < nums.length; i++) {
int minIndex = i;//最小下标
for (int j = i + 1; j < nums.length; j++) {
if (nums[j] < nums[minIndex]) {
minIndex = j;
}
}
if (minIndex != i) {
int temp = nums[i];
nums[i] = nums[minIndex];
nums[minIndex] = temp;
}
}
}
插入排序
在要排序的一组数中,假定前n-1个数已经排好序,现在将第n个数插到前面的有序数列中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序。
/**
* *插入排序
*
* @param nums
*/
public static void insertionSort(int[] nums) {
for (int i = 0; i < nums.length - 1; i++) {
for (int j = i + 1; j > 0; j--) {
if (nums[j] < nums[j - 1]) {
int temp = nums[j];
nums[j] = nums[j - 1];
nums[j - 1] = temp;
} else {
break;
}
}
}
}
希尔排序
在要排序的一组数中,根据某一增量分为若干子序列,并对子序列分别进行插入排序。
然后逐渐将增量减小,并重复上述过程。直至增量为1,此时数据序列基本有序,最后进行插入排序。
/**
* *希尔排序
*
* @param nums
*/
public static void shellSort(int[] nums) {
/*for (int gap = nums.length / 2; gap > 0; gap /= 2) {//增量分段
for (int i = 0; i < gap; i++) {//第一段的第i个
for (int j = i + gap; j < nums.length; j += gap) {//每一段的第i个
for (int k = j; k > i; k -= gap) {//每一段的第i个比较
if (nums[k] < nums[k - gap]) {
int temp = nums[k];
nums[k] = nums[k - gap];
nums[k - gap] = temp;
}
}
}
}
}*/
for (int gap = nums.length / 2; gap > 0; gap /= 2) {//增量分段
for (int i = gap; i < nums.length; i++) {//第一段后开始
int temp = nums[i];
int preIndex = i - gap;
while (preIndex >= 0 && nums[preIndex] > temp) {//从后往前,比较每一段的第i%gap个
nums[preIndex + gap] = nums[preIndex];
preIndex -= gap;
}
nums[preIndex + gap] = temp;
}
gap /= 2;
}
}
快速排序
- 先从数列中取出一个数作为key值;
- 将比这个数小的数全部放在它的左边,大于或等于它的数全部放在它的右边;
- 对左右两个小数列重复第二步,直至各区间只有1个数。
/**
* *快速排序
*
* @param nums
*/
public static void quickSort(int[] nums, int l, int r) {
if (l >= r) {
return;
}
int i = l, j = r;
int key = nums[i];
while (i < j) {
while (i < j && nums[j] >= key)
j--;
if (i < j) {
nums[i] = nums[j];
i++;
}
while (i < j && nums[i] <= key)
i++;
if (i < j) {
nums[j] = nums[i];
j--;
}
}
nums[i] = key;
quickSort(nums, l, i - 1);
quickSort(nums, i + 1, r);
}
归并排序
将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。
/**
* *归并排序
*
* @param nums
*/
public static int[] mergeSort(int[] nums) {
if (nums.length < 2) {
return nums;
}
int mid = nums.length / 2;
int[] left = Arrays.copyOfRange(nums, 0, mid);
int[] right = Arrays.copyOfRange(nums, mid, nums.length);
return merge(mergeSort(left), mergeSort(right));
}
private static int[] merge(int[] left, int[] right) {
int[] ans = new int[left.length + right.length];
for (int index = 0, l = 0, r = 0; index < ans.length; index++) {
if (l >= left.length) {
ans[index] = right[r++];
} else if (r >= right.length) {
ans[index] = left[l++];
} else if (left[l] > right[r]) {
ans[index] = right[r++];
} else if (left[l] < right[r]) {
ans[index] = left[l++];
}
}
return ans;
}
堆排序
利用堆的性质:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。
/**
* *堆排序
*
* @param nums
*/
public static void heapSort(int[] nums) {
//非叶子节点个数nums.length/2-1
//构建堆
for (int i = nums.length / 2 - 1; i >= 0; i--) {
adjustHead(nums, i, nums.length);
}
//将最大的元素放到末尾,反复执行,直到有序
for (int j = nums.length - 1; j >= 0; j--) {
int temp = 0;
temp = nums[0];
nums[0] = nums[j];
nums[j] = temp;
adjustHead(nums, 0, j);
}
}
/**
* *构建堆
*
* @param nums 待调整的数组
* @param i 非叶子节点在数组的下标
* @param length 表示对多少个元素进行调整,length的值在逐渐变少
*/
private static void adjustHead(int[] nums, int i, int length) {
//取出非叶子节点值
int temp = nums[i];
for (int k = i * 2 + 1; k < length; k = k * 2 + 1) {
if (k + 1 < length && nums[k] < nums[k + 1]) {//左节点小于右节点
k++;
}
if (nums[k] > temp) {//子节点大于父节点
nums[i] = nums[k];
i = k;
} else {
break;
}
}
nums[i] = temp;
}
基数排序
基数排序是按照低位到高位依次放进对应的桶里,在放回原数组
/**
* *计数排序
*
* @param nums
*/
public static void countingSort(int[] nums) {
if (nums.length == 0) return;
int bias, min = nums[0], max = nums[0];
for (int i = 1; i < nums.length; i++) {//找最大最小
if (nums[i] > max)
max = nums[i];
if (nums[i] < min)
min = nums[i];
}
bias = 0 - min;
int[] cnt = new int[max - min + 1];
Arrays.fill(cnt, 0);
for (int i = 0; i < nums.length; i++) {//统计nums中元素出现的个数,放在cnt中,这样一定是顺序排好的,nums = i-bias
cnt[nums[i] + bias]++;
}
int index = 0, i = 0;
while (index < nums.length) {
if (cnt[i] != 0) {
nums[index] = i - bias;
cnt[i]--;
index++;
} else
i++;
}
}
计数排序
- 找出待排序的数组中最大和最小的元素;
- 统计数组中每个值为i的元素出现的次数,存入数组cnt的第i项;
- 反向填充目标数组
/**
* *计数排序
*
* @param nums
*/
public static void countingSort(int[] nums) {
if (nums.length == 0) return;
int bias, min = nums[0], max = nums[0];
for (int i = 1; i < nums.length; i++) {//找最大最小
if (nums[i] > max)
max = nums[i];
if (nums[i] < min)
min = nums[i];
}
bias = 0 - min;
int[] cnt = new int[max - min + 1];
Arrays.fill(cnt, 0);
for (int i = 0; i < nums.length; i++) {//统计nums中元素出现的个数,放在cnt中,这样一定是顺序排好的,nums = i-bias
cnt[nums[i] + bias]++;
}
int index = 0, i = 0;
while (index < nums.length) {
if (cnt[i] != 0) {
nums[index] = i - bias;
cnt[i]--;
index++;
} else
i++;
}
}