文章目录
插入排序
Code实现
public static void Insert_Sort(int[] nums) {
for (int i = 2; i < nums.length; i++) {
if (nums[i - 1] > nums[i]) {
nums[0] = nums[i];
int j;
for (j = i - 1; nums[j] > nums[0]; j--) {
nums[j + 1] = nums[j];
}
nums[j + 1] = nums[0];
nums[0] = 0;
}
}
}
时间复杂度
- 最好:O(n) → 基本有序
- 最坏:O(n2) → 原本逆序
- 平均: O(n2)
空间复杂度
O(1)
算法稳定性
稳定
优化-折半插入排序
Code实现
public static void Half_Insert_Sort(int[] nums) {
for (int i = 2; i < nums.length; i++) {
nums[0] = nums[i];
int low = 1;
int high = i - 1;
while (low <= high) {
int mid = (low + high) / 2;
if (nums[mid] > nums[0])
high = mid - 1;
else
low = mid + 1;
}
for (int j = i - 1; j > high; j--) {
nums[j + 1] = nums[j];
}
nums[high + 1] = nums[0];
}
nums[0] = 0;
}
时间复杂度
- 最好:O(n) → 基本有序
- 最坏:O(n2) → 原本逆序
- 平均: O(n2)
空间复杂度
O(1)
算法稳定性
稳定
希尔排序
Code实现
public static void Shell_Sort(int[] nums) {
int increment;//增量
for (increment = nums.length / 2; increment >= 1; increment /= 2) {
for (int i = increment + 1; i < nums.length; i++) {
if (nums[i] < nums[i - increment]) {
nums[0] = nums[i];
int j;
for (j = i - increment; j > 0 && nums[0] < nums[j]; j -= increment) {
nums[j + increment] = nums[j];
}
nums[j + increment] = nums[0];
}
}
}
nums[0] = 0;
}
时间复杂度
- 未知,但是优于直接插入排序
- 和增量序列
d1、d2、d3…
的选择有关,目前无法用数学手段证明确切的时间复杂度 - 最坏时间复杂度:O(n2)
- 当n在某个范围时,可达O(n1.3)
空间复杂度
O(1)
算法稳定性
不稳定
冒泡排序
Code实现
public static void Bubble_Sort(int[] nums) {
boolean isOrder = false;//标志位
for (int i = 1; i < nums.length - 1; i++) {//第几层
for (int j = nums.length - 1; j > 1; j--) {//两两比较找出最小的
if (nums[j] < nums[j - 1]) {
nums[0] = nums[j];
nums[j] = nums[j - 1];
nums[j - 1] = nums[0];
isOrder = false;
}
}
if (isOrder == true)
break;
//当某一趟没有出现交换时,可以认为此时的数组已经整体有序,可以直接退出循环,减少不必要的循环次数,有点点重复性剪枝的思想
}
nums[0] = 0;
}
时间复杂度
- 最好:O(n) → 有序
- 最差:O(n2) → 逆序
- 平均:O(n2)
空间复杂度
O(1)
算法稳定性
稳定
快速排序
Code实现
//一趟排序
public static int Partition(int[] nums, int low, int high) {
int pivot = nums[low];
while (low < high) {
while (low < high && nums[high] >= pivot)
high--;
nums[low] = nums[high];
while (low < high && nums[low] < pivot)
low++;
nums[high] = nums[low];
}
nums[low] = pivot;
return low;
}
//具体快速排序过程
public static void Quick_Sort(int[] nums, int low, int high) {
if (low < high) {
int pivotpos = Partition(nums, low, high);
Quick_Sort(nums, low, pivotpos);
Quick_Sort(nums, pivotpos + 1, high);
}
}
时间复杂度
- 最好:O(n2) → 每次划分很平均
- 最坏:O(nlog2n) → 原本正序或逆序
- 平均:O(nlog2n)
空间复杂度
- 最好:O(n)
- 最坏:O(log2n)
算法稳定性
不稳定
简单选择排序
Code实现
public static void Simple_Selection_Sort(int[] nums) {
//每一趟在待排序元素中选取关键字最小的元素加入有序子序列
for (int i = 1; i < nums.length; i++) {
int min = i;
for (int j = i; j < nums.length; j++) {
if (nums[j] < nums[min])
min = j;
}
if (i != min) {
int temp = nums[i];
nums[i] = nums[min];
nums[min] = temp;
}
}
}
时间复杂度
O(n2)
空间复杂度
O(1)
算法稳定性
不稳定
堆排序
Code实现
public static void Heap_Sort(int[] nums, int len) {
//len为待排序的数字数目
BuildMaxHeap(nums, len);
for (int i = len; i > 0; i--) {
int temp = nums[i];
nums[i] = nums[1];
nums[1] = temp;
AdjustMaxHeap(nums, 1, i - 1);
}
nums[0] = 0;
}
public static void BuildMaxHeap(int[] nums, int len) {
for (int i = len / 2; i > 0; i--) {
AdjustMaxHeap(nums, i, len);
}
}
public static void AdjustMaxHeap(int[] nums, int k, int len) {
//表示从第k个数字开始调整整个数组为大根堆
nums[0] = nums[k];
for (int i = 2 * k; i <= len; i *= 2) {
if (i < len && nums[i] < nums[i + 1])
i += 1;
if (nums[i] <= nums[0]) break;
else {
nums[k] = nums[i];
k = i;
}
}
nums[k] = nums[0];
}
时间复杂度
- 建堆: O(n)
- 排序:O(nlog2n)
- 总的时间复杂度:O(nlog2n)
空间复杂度
O(1)
算法稳定性
不稳定
归并排序
Code实现
static int N = 1000001;
static int[] assist = new int[N];//这里的数组大小根据你待排序数组的大小确定
public static void merge(int[] nums, int low, int mid, int high) {
for (int i = low; i <= high; i++) {
assist[i] = nums[i];//把nums数组里面的数据保存到assist数组里面
}
int i, j, k = low;
for (i = low, j = mid + 1; i <= mid && j <= high; ) {
if (assist[i] <= assist[j])
nums[k++] = assist[i++];
else {
nums[k++] = assist[j++];
}
}
while (i <= mid) {
nums[k++] = assist[i++];
}
while (j <= high) {
nums[k++] = assist[j++];
}
}
public static void Merge_Sort(int[] nums, int low, int high) {
if (low < high) {
int mid = (low + high) / 2;
//分治思想
Merge_Sort(nums, low, mid);
Merge_Sort(nums, mid + 1, high);
merge(nums, low, mid, high);
}
时间复杂度
O(nlog2n)
空间复杂度
O(n)
利用hash的思想进行排序
Code实现
//使用数组的下标对正整数排序
//哈希表的表长度需要超过最大待排序数字
public static void Hash_Sort() {
int[] random = {999, 1, 444, 7, 88, 5, 66, 98, 20, 1, 888, 652, 59, 23, 48, 60, 481, 105, 8, 28};
int[] hash_map = new int[1000];//这里的数组大小是根据你待排序数组里面的值域确定的
for (int i = 0; i < random.length; i++) {
hash_map[random[i]]++;
}
for (int i = 0; i < hash_map.length; i++) {
for (int j = 0; j < hash_map[i]; j++) {
//若有重复的记录说明数字重复,也输出出来
//这里还把未出现过的数字即出现次数为0的数字给筛选掉了
System.out.print(i + " ");
}
}
System.out.println();
}
时间复杂度
O(表长+元素个数)