常见排序方法的时间、空间复杂度及其稳定性汇总(JAVA,含对数器)

常见排序(带输入)和对数器测试(不带输入)

1、冒泡排序

package 苟熊岭熊哒;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

//冒泡排序
public class BubbleSort {
	public static void swap(int[] arr, int i, int j) {
		int tmp = arr[i];
		arr[i] = arr[j];
		arr[j] = tmp;
	}

	public static void bubbleSort(int[] arr) {
		if (arr == null || arr.length < 2) {
			return;
		}

		for (int i = 0; i < arr.length - 1; i++) {
			for (int j = 0; j < arr.length - 1 - i; j++) {
				if (arr[j + 1] < arr[j]) {
					swap(arr, j + 1, j);
				}
			}
		}
	}

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		System.out.println("请输入元素个数:");
		int n = Integer.parseInt(br.readLine());
		int[] arr = new int[n];

		System.out.println("请输入元素内容(每个元素之间用空格分隔):");
		String[] line = br.readLine().split(" ");
		for (int i = 0; i < line.length; i++) {
			arr[i] = Integer.parseInt(line[i]);
		}

		bubbleSort(arr);// 冒泡排序
		System.out.println("排序后:" + Arrays.toString(arr));
	}
}

输出结果:

image.png

对数器测试

package 苟熊岭熊哒;

import java.util.Arrays;

//冒泡排序
public class BubbleSort {
	// 交换
	public static void swap(int[] arr, int i, int j) {
		int tmp = arr[i];
		arr[i] = arr[j];
		arr[j] = tmp;
	}

	// 用系统提供的方式进行排序
	public static void comparator(int[] arr) {
		Arrays.sort(arr);
	}

	// 生成一个随机数组
	public static int[] generateRandomArray(int maxSize, int maxValue) {
		int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
		for (int i = 0; i < arr.length; i++) {
			arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) ((maxValue + 1) * Math.random());
		}

		return arr;
	}

	// 拷贝数组
	public static int[] copyArray(int[] arr) {
		if (arr == null) {
			return null;
		}

		int[] res = new int[arr.length];
		for (int i = 0; i < arr.length; i++) {
			res[i] = arr[i];
		}
		return res;
	}

	// 判断arr1和arr2中的每个值是否相等
	public static boolean isEqual(int[] arr1, int[] arr2) {
		int i = 0;
		while (i < arr1.length) {
			if (arr1[i] == arr2[i]) {
				i++;
			} else {
				return false;
			}
		}
		return true;
	}

	// 打印数组
	public static void printArray(int[] arr) {
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i] + " ");
		}
	}

	// test

	// 冒泡排序
	public static void bubbleSort(int[] arr) {
		if (arr == null || arr.length < 2) {
			return;
		}

//		for(int i=arr.length-1; i>0; i--) {
//			for(int j=0; j<i; j++) {
//				if(arr[j]>arr[j+1]) {
//					swap(arr,j,j+1);
//				}
//			}
//		}

		for (int i = 0; i < arr.length - 1; i++) {
			for (int j = 0; j < arr.length - 1 - i; j++) {
				if (arr[j] > arr[j + 1]) {
					swap(arr, j, j + 1);
				}
			}
		}
	}

	public static void main(String[] args) {
		int testTime = 500000;// 测试次数,50万次
		int maxSize = 100;// 数组的规模不大于100
		int maxValue = 100;// 数组中每个值的范围,-100~+100
		boolean succeed = true;
		for (int i = 0; i < testTime; i++) {
			int[] arr1 = generateRandomArray(maxSize, maxValue);
			// 创建一个数组,长度随机,值也随机
			int[] arr2 = copyArray(arr1);
			bubbleSort(arr1);// (此处放自己写的排序算法)(arr1);
			comparator(arr2);// 用系统提供的排序,来排arr2
			// 排完序后,比较arr1和arr2的每个位置的值都是不是一样
			if (isEqual(arr1, arr2) == false) {
				// 若值不一样,则该次测试失败
				succeed = false;
				printArray(arr1);// 打印arr1排成了什么样
				printArray(arr2);// 打印arr2排成了什么样
				break;// 跳出循环
			}
		}
		System.out.println(succeed == true ? "完全正确!" : "有错误");
	}
}

测试结果:

image.png


2、直接插入排序

package 苟熊岭熊哒;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

//直接插入排序
public class InsertSort {
	public static void swap(int[] arr, int i, int j) {
		int tmp = arr[i];
		arr[i] = arr[j];
		arr[j] = tmp;
	}

	// 直接插入排序
	public static void insertSort(int[] arr) {
		if (arr == null || arr.length < 2) {
			return;
		}

		for (int i = 0; i < arr.length - 1; i++) {
			for (int j = i + 1; (j > 0) && (arr[j] < arr[j - 1]); j--) {
				swap(arr, j, j - 1);
			}
		}
	}

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		System.out.println("请输入元素个数:");
		int n = Integer.parseInt(br.readLine());
		int[] arr = new int[n];

		System.out.println("请输入元素内容(每个元素之间用空格分隔):");
		String[] line = br.readLine().split(" ");
		for (int i = 0; i < line.length; i++) {
			arr[i] = Integer.parseInt(line[i]);
		}

		insertSort(arr);// 直接插入排序
		System.out.println("排序后:" + Arrays.toString(arr));
	}
}

输出结果:

image.png

对数器测试

package 苟熊岭熊哒;

import java.util.Arrays;

//直接插入排序
public class InsertSort {
	// 用系统提供的方法进行排序
	public static void comparator(int[] arr) {
		Arrays.sort(arr);
	}

	// 生成一个随机数组
	public static int[] generateRandomArray(int maxSize, int maxValue) {
		// Math.random() -> 随机在[0,1)范围内返回一个double类型的数(等概率)
		// Math.random()*A -> 随机在[0,A)范围内返回一个double类型的数(等概率)
		// (int)(Math.random()*A) -> 随机在[0,A-1]范围内返回一个int类型的数(等概率)
		int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
		for (int i = 0; i < arr.length; i++) {
			arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) ((maxValue + 1) * Math.random());
		}
		return arr;
	}

	// 拷贝数组
	public static int[] copyArray(int[] arr) {
		if (arr == null) {
			return null;
		}

		int[] res = new int[arr.length];
		for (int i = 0; i < arr.length; i++) {
			res[i] = arr[i];
		}
		return res;
	}

	// 判断arr1和arr2中的每个值是否相等
	public static boolean isEqual(int[] arr1, int[] arr2) {
		int i = 0;
		while (i < arr1.length) {
			if (arr1[i] == arr2[i]) {
				i++;
			} else {
				return false;
			}
		}
		return true;
	}

	// 打印数组
	public static void printArray(int[] arr) {
		for (int a : arr) {
			System.out.print(a + " ");
		}
		System.out.println();
	}

	// test

	public static void swap(int[] arr, int i, int j) {
		int tmp = arr[i];
		arr[i] = arr[j];
		arr[j] = tmp;
	}

	public static void insertSort(int[] arr) {
		if (arr == null || arr.length < 2) {
			return;
		}

		for (int i = 0; i < arr.length - 1; i++) {
			for (int j = i + 1; (j > 0) && (arr[j] < arr[j - 1]); j--) {
				swap(arr, j, j - 1);
			}
		}
	}

	public static void main(String[] args) {
		int testTime = 500000;// 测试次数,50万次
		int maxSize = 100;// 数组的规模不大于100
		int maxValue = 100;// 数组中每个值的范围,-100~+100
		boolean succeed = true;
		for (int i = 0; i < testTime; i++) {
			int[] arr1 = generateRandomArray(maxSize, maxValue);
			// 创建一个数组,长度随机,值也随机
			int[] arr2 = copyArray(arr1);
			insertSort(arr1);// (此处放自己写的排序算法)(arr1);
			comparator(arr2);// 用系统提供的排序,来排arr2
			// 排完序后,比较arr1和arr2的每个位置的值都是不是一样
			if (isEqual(arr1, arr2) == false) {
				// 若值不一样,则该次测试失败
				succeed = false;
				printArray(arr1);// 打印arr1排成了什么样
				printArray(arr2);// 打印arr2排成了什么样
				break;// 跳出循环
			}
		}
		System.out.println(succeed == true ? "完全正确!" : "有错误");
	}
}

测试结果:

image.png


3、选择排序

package 苟熊岭熊哒;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

//选择排序
public class SelectSort {
	public static void swap(int[] arr, int i, int j) {
		int tmp = arr[i];
		arr[i] = arr[j];S
		arr[j] = tmp;
	}

	// 选择排序
	public static void selectSort(int[] arr) {
		if (arr == null || arr.length < 2) {
			return;
		}

		int min = 0;
		for (int i = 0; i < arr.length; i++) {
			min = i;
			for (int j = i + 1; j < arr.length; j++) {
				if (arr[min] > arr[j]) {
					min = j;
				}
			}
			swap(arr, i, min);
		}

	}

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		System.out.println("请输入元素个数:");
		int n = Integer.parseInt(br.readLine());
		int[] arr = new int[n];

		System.out.println("请输入元素内容(每个元素之间用空格分隔):");
		String[] line = br.readLine().split(" ");
		for (int i = 0; i < line.length; i++) {
			arr[i] = Integer.parseInt(line[i]);
		}

		selectSort(arr);// 选择排序
		System.out.println("排序后:" + Arrays.toString(arr));
	}
}

输出结果:

image.png

对数器测试

package 苟熊岭熊哒;

import java.util.Arrays;

//选择排序
public class SelectSort {
	// 用系统提供的方法进行排序
	public static void comparator(int[] arr) {
		Arrays.sort(arr);
	}

	// 生成一个随机数组
	public static int[] generateRandomArray(int maxSize, int maxValue) {
		// Math.random() -> 随机在[0,1)范围内返回一个double类型的数(等概率)
		// Math.random()*A -> 随机在[0,A)范围内返回一个double类型的数(等概率)
		// (int)(Math.random()*A) -> 随机在[0,A-1]范围内返回一个int类型的数(等概率)
		int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
		for (int i = 0; i < arr.length; i++) {
			arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) ((maxValue + 1) * Math.random());
		}
		return arr;
	}

	// 拷贝数组
	public static int[] copyArray(int[] arr) {
		if (arr == null) {
			return null;
		}

		int[] res = new int[arr.length];
		for (int i = 0; i < arr.length; i++) {
			res[i] = arr[i];
		}
		return res;
	}

	// 判断arr1和arr2中的每个值是否相等
	public static boolean isEqual(int[] arr1, int[] arr2) {
		int i = 0;
		while (i < arr1.length) {
			if (arr1[i] == arr2[i]) {
				i++;
			} else {
				return false;
			}
		}
		return true;
	}

	// 打印数组
	public static void printArray(int[] arr) {
		for (int a : arr) {
			System.out.print(a + " ");
		}
		System.out.println();
	}

	// test

	public static void swap(int[] arr, int i, int j) {
		int tmp = arr[i];
		arr[i] = arr[j];
		arr[j] = tmp;
	}

	public static void selectSort(int[] arr) {
		if (arr == null || arr.length < 2) {
			return;
		}

		for (int i = 0; i < arr.length; i++) {
			int min = i;
			for (int j = i + 1; j < arr.length; j++) {
				if (arr[j] < arr[min]) {
					min = j;
				}
			}
			swap(arr, i, min);
		}
	}

	public static void main(String[] args) {
		int testTime = 500000;// 测试次数,50万次
		int maxSize = 100;// 数组的规模不大于100
		int maxValue = 100;// 数组中每个值的范围,-100~+100
		boolean succeed = true;
		for (int i = 0; i < testTime; i++) {
			int[] arr1 = generateRandomArray(maxSize, maxValue);
			// 创建一个数组,长度随机,值也随机
			int[] arr2 = copyArray(arr1);
			selectSort(arr1);// (此处放自己写的排序算法)(arr1);
			comparator(arr2);// 用系统提供的排序,来排arr2
			// 排完序后,比较arr1和arr2的每个位置的值都是不是一样
			if (isEqual(arr1, arr2) == false) {
				// 若值不一样,则该次测试失败
				succeed = false;
				printArray(arr1);// 打印arr1排成了什么样
				printArray(arr2);// 打印arr2排成了什么样
				break;// 跳出循环
			}
		}
		System.out.println(succeed == true ? "完全正确!" : "有错误");
	}
}

测试结果:

image.png


4、归并排序

package 苟熊岭熊哒;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

//归并排序
public class MergeSort {
	public static void swap(int[] arr, int i, int j) {
		int tmp = arr[i];
		arr[i] = arr[j];
		arr[j] = tmp;
	}

	// 归并排序--归并
	private static void merge(int[] arr, int left, int mid, int right) {
		// (right-left)+1:传过来的数组内的元素个数
		int[] tmp = new int[(right - left) + 1];

		int p = 0;// 临时数组tmp的下标
		int p1 = left;// 左半边组的初始下标
		int p2 = mid + 1;// 右半边组的初始下标

		// 归并
		while (p1 <= mid && p2 <= right) {
			tmp[p++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
			// 如果p1指向的数小于等于p2指向的数 (默认规定) ,则将p1指向的数拷入tmp数组中
			// 反之则将p2指向的数拷入tmp数组中
		}

		// 当右边的组已经排完后,将左边组剩余的所有数直接拷到tmp数组中
		while (p1 <= mid) {
			tmp[p++] = arr[p1++];
		}

		// 当左边的组已经排完后,将右边组剩余的所有数直接拷到tmp数组中
		while (p2 <= right) {
			tmp[p++] = arr[p2++];
		}

		// 拷贝数组
		for (int i = 0; i < tmp.length; i++) {
			// 注意:arr数组是从i+left开始的
			arr[i + left] = tmp[i];
		}

	}

	// 归并排序--分组
	private static void process(int[] arr, int left, int right) {
		if (left == right) {
			// 当left==right,说明已经分到只有一个数了,故直接返回
			return;
		}

		int mid = left + ((right - left) >> 1);

		process(arr, left, mid);// 分组--左半边
		process(arr, mid + 1, right);// 分组--右半边
		merge(arr, left, mid, right);// 归并
	}

	// 归并排序
	public static void mergeSort(int[] arr) {
		if (arr == null || arr.length < 2) {
			return;
		}

		int left = 0;
		int right = arr.length - 1;
		process(arr, left, right);
	}

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		System.out.println("请输入元素个数:");
		int n = Integer.parseInt(br.readLine());
		int[] arr = new int[n];

		System.out.println("请输入元素内容(每个元素之间用空格分隔):");
		String[] line = br.readLine().split(" ");
		for (int i = 0; i < line.length; i++) {
			arr[i] = Integer.parseInt(line[i]);
		}

		mergeSort(arr);// 归并排序
		System.out.println("排序后:" + Arrays.toString(arr));
	}
}

输出结果:

image.png

对数器测试

package 苟熊岭熊哒;

import java.util.Arrays;

//归并排序
public class MergeSort {
	// 用系统提供的方法进行排序
	public static void comparator(int[] arr) {
		Arrays.sort(arr);
	}

	// 生成一个随机数组
	public static int[] generateRandomArray(int maxSize, int maxValue) {
		// Math.random() -> 随机在[0,1)范围内返回一个double类型的数(等概率)
		// Math.random()*A -> 随机在[0,A)范围内返回一个double类型的数(等概率)
		// (int)(Math.random()*A) -> 随机在[0,A-1]范围内返回一个int类型的数(等概率)
		int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
		for (int i = 0; i < arr.length; i++) {
			arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) ((maxValue + 1) * Math.random());
		}
		return arr;
	}

	// 拷贝数组
	public static int[] copyArray(int[] arr) {
		if (arr == null) {
			return null;
		}

		int[] res = new int[arr.length];
		for (int i = 0; i < arr.length; i++) {
			res[i] = arr[i];
		}
		return res;
	}

	// 判断arr1和arr2中的每个值是否相等
	public static boolean isEqual(int[] arr1, int[] arr2) {
		int i = 0;
		while (i < arr1.length) {
			if (arr1[i] == arr2[i]) {
				i++;
			} else {
				return false;
			}
		}
		return true;
	}

	// 打印数组
	public static void printArray(int[] arr) {
		for (int a : arr) {
			System.out.print(a + " ");
		}
		System.out.println();
	}

	// test

	private static void mergeSort(int[] arr) {
		if (arr == null || arr.length < 2) {
			return;
		}

		int left = 0;
		int right = arr.length - 1;
		process(arr, left, right);
	}

	// 归并排序--分组
	private static void process(int[] arr, int left, int right) {
		if (left == right) {
			// 当left==right,说明已经分到只有一个数了,故直接返回
			return;
		}

		int mid = left + ((right - left) >> 1);

		process(arr, left, mid);// 分组--左半边
		process(arr, mid + 1, right);// 分组--右半边
		merge(arr, left, mid, right);// 归并
	}

	// 归并排序--归并
	private static void merge(int[] arr, int left, int mid, int right) {
		// (right-left)+1:传过来的数组内的元素个数
		int[] tmp = new int[(right - left) + 1];

		int p = 0;// 临时数组tmp的下标
		int p1 = left;// 左半边组的初始下标
		int p2 = mid + 1;// 右半边组的初始下标

		// 归并
		while (p1 <= mid && p2 <= right) {
			tmp[p++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
			// 如果p1指向的数小于等于p2指向的数 (默认规定) ,则将p1指向的数拷入tmp数组中
			// 反之则将p2指向的数拷入tmp数组中
		}

		// 当右边的组已经排完后,将左边组剩余的所有数直接拷到tmp数组中
		while (p1 <= mid) {
			tmp[p++] = arr[p1++];
		}

		// 当左边的组已经排完后,将右边组剩余的所有数直接拷到tmp数组中
		while (p2 <= right) {
			tmp[p++] = arr[p2++];
		}

		// 拷贝数组
		for (int i = 0; i < tmp.length; i++) {
			// 注意:arr数组是从i+left开始的
			arr[i + left] = tmp[i];
		}

	}

	public static void main(String[] args) {
		int testTime = 500000;// 测试次数,50万次
		int maxSize = 100;// 数组的规模不大于100
		int maxValue = 100;// 数组中每个值的范围,-100~+100
		boolean succeed = true;
		for (int i = 0; i < testTime; i++) {
			int[] arr1 = generateRandomArray(maxSize, maxValue);
			// 创建一个数组,长度随机,值也随机
			int[] arr2 = copyArray(arr1);
			mergeSort(arr1);// (此处放自己写的排序算法)(arr1);
			comparator(arr2);// 用系统提供的排序,来排arr2
			// 排完序后,比较arr1和arr2的每个位置的值都是不是一样
			if (isEqual(arr1, arr2) == false) {
				// 若值不一样,则该次测试失败
				succeed = false;
				printArray(arr1);// 打印arr1排成了什么样
				printArray(arr2);// 打印arr2排成了什么样
				break;// 跳出循环
			}
		}
		System.out.println(succeed == true ? "完全正确!" : "有错误");
	}
}

测试结果:

image.png


5、堆排序

package 苟熊岭熊哒;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

//堆排序
public class HeapSort {
	public static void swap(int[] arr, int i, int j) {
		int tmp = arr[i];
		arr[i] = arr[j];
		arr[j] = tmp;
	}

	// 下沉--heapify
	public static void heapify(int[] nums, int index, int heapSize) {
		// index开始等于0,表示从0开始向下沉
		// index也表示父节点的索引

		int left = index * 2 + 1;// 左孩子的下标
		while (left < heapSize) {// 表示下方还有孩子
			// 左孩子和右孩子相比,谁的值大,谁把下标给largest变量
			// 若left+1>=heapSize,表示没有右孩子
			int largest = left + 1 < heapSize && nums[left + 1] > nums[left] ? left + 1 : left;
			// 父亲和较大的孩子之间,谁的值大,谁把下标给largest变量
			largest = nums[largest] > nums[index] ? largest : index;

			if (largest == index) {
				// 如果父节点最大,则下沉过程结束
				break;
			}

			// 若上述判断条件不成立,则交换父节点和较大孩子的值
			swap(nums, largest, index);
			index = largest;// 父节点继续下沉
			left = index * 2 + 1;// 表示左孩子的索引
		}
	}

	// 上浮--heapInsert
	public static void heapInsert(int[] nums, int index) {
		while (nums[index] > nums[(index - 1) / 2]) {
			swap(nums, index, (index - 1) / 2);
			index = (index - 1) / 2;
		}
	}

	// 堆排序
	public static void heapSort(int[] nums) {
		if (nums == null || nums.length < 2) {
			return;
		}

		// 先用上浮算法,构建堆结构
		// O(N*logN)
		for (int i = 0; i < nums.length; i++) { // O(N)
			// 一个一个上浮
			heapInsert(nums, i); // O(logN)
		}

		// 使用下沉算法,进行堆排序
		int heapSize = nums.length;
		swap(nums, 0, --heapSize);
		while (heapSize > 0) { // O(N)
			heapify(nums, 0, heapSize); // O(logN)
			swap(nums, 0, --heapSize); // O(1)
		}
	}

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		System.out.println("请输入元素个数:");
		int n = Integer.parseInt(br.readLine());
		int[] arr = new int[n];

		System.out.println("请输入元素内容(每个元素之间用空格分隔):");
		String[] line = br.readLine().split(" ");
		for (int i = 0; i < line.length; i++) {
			arr[i] = Integer.parseInt(line[i]);
		}

		heapSort(arr);// 堆排序
		System.out.println("排序后:" + Arrays.toString(arr));
	}
}

输出结果:
image.png

对数器测试

package 苟熊岭熊哒;

import java.util.Arrays;

//堆排序
public class HeapSort {
	// 用系统提供的方法进行排序
	public static void comparator(int[] arr) {
		Arrays.sort(arr);
	}

	// 生成一个随机数组
	public static int[] generateRandomArray(int maxSize, int maxValue) {
		// Math.random() -> 随机在[0,1)范围内返回一个double类型的数(等概率)
		// Math.random()*A -> 随机在[0,A)范围内返回一个double类型的数(等概率)
		// (int)(Math.random()*A) -> 随机在[0,A-1]范围内返回一个int类型的数(等概率)
		int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
		for (int i = 0; i < arr.length; i++) {
			arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) ((maxValue + 1) * Math.random());
		}
		return arr;
	}

	// 拷贝数组
	public static int[] copyArray(int[] arr) {
		if (arr == null) {
			return null;
		}

		int[] res = new int[arr.length];
		for (int i = 0; i < arr.length; i++) {
			res[i] = arr[i];
		}
		return res;
	}

	// 判断arr1和arr2中的每个值是否相等
	public static boolean isEqual(int[] arr1, int[] arr2) {
		int i = 0;
		while (i < arr1.length) {
			if (arr1[i] == arr2[i]) {
				i++;
			} else {
				return false;
			}
		}
		return true;
	}

	// 打印数组
	public static void printArray(int[] arr) {
		for (int a : arr) {
			System.out.print(a + " ");
		}
		System.out.println();
	}

	// test

	// 交换
	public static void swap(int[] nums, int i, int j) {
		int tmp = nums[i];
		nums[i] = nums[j];
		nums[j] = tmp;
	}

	// 下沉--heapify
	public static void heapify(int[] nums, int index, int heapSize) {
		// index开始等于0,表示从0开始向下沉
		// index也表示父节点的索引

		int left = index * 2 + 1;// 左孩子的下标
		while (left < heapSize) {// 表示下方还有孩子
			// 左孩子和右孩子相比,谁的值大,谁把下标给largest变量
			// 若left+1>=heapSize,表示没有右孩子
			int largest = left + 1 < heapSize && nums[left + 1] > nums[left] ? left + 1 : left;
			// 父亲和较大的孩子之间,谁的值大,谁把下标给largest变量
			largest = nums[largest] > nums[index] ? largest : index;

			if (largest == index) {
				// 如果父节点最大,则下沉过程结束
				break;
			}

			// 若上述判断条件不成立,则交换父节点和较大孩子的值
			swap(nums, largest, index);
			index = largest;// 父节点继续下沉
			left = index * 2 + 1;// 表示左孩子的索引
		}
	}

	// 上浮--heapInsert
	public static void heapInsert(int[] nums, int index) {
		while (nums[index] > nums[(index - 1) / 2]) {
			swap(nums, index, (index - 1) / 2);
			index = (index - 1) / 2;
		}
	}

	// 堆排序
	public static void heapSort(int[] nums) {
		if (nums == null || nums.length < 2) {
			return;
		}

		// 先用上浮算法,构建堆结构
		// O(N*logN)
		for (int i = 0; i < nums.length; i++) { // O(N)
			// 一个一个上浮
			heapInsert(nums, i); // O(logN)
		}

		// 使用下沉算法,进行堆排序
		int heapSize = nums.length;
		swap(nums, 0, --heapSize);
		while (heapSize > 0) { // O(N)
			heapify(nums, 0, heapSize); // O(logN)
			swap(nums, 0, --heapSize); // O(1)
		}
	}

	public static void main(String[] args) {
		int testTime = 500000;// 测试次数,50万次
		int maxSize = 100;// 数组的规模不大于100
		int maxValue = 100;// 数组中每个值的范围,-100~+100
		boolean succeed = true;
		for (int i = 0; i < testTime; i++) {
			int[] arr1 = generateRandomArray(maxSize, maxValue);
			// 创建一个数组,长度随机,值也随机
			int[] arr2 = copyArray(arr1);
			heapSort(arr1);// (此处放自己写的排序算法)(arr1);
			comparator(arr2);// 用系统提供的排序,来排arr2
			// 排完序后,比较arr1和arr2的每个位置的值都是不是一样
			if (isEqual(arr1, arr2) == false) {
				// 若值不一样,则该次测试失败
				succeed = false;
				printArray(arr1);// 打印arr1排成了什么样
				printArray(arr2);// 打印arr2排成了什么样
				break;// 跳出循环
			}
		}
		System.out.println(succeed == true ? "完全正确!" : "有错误");
	}
}

测试结果:

image.png


6、快速排序

package 苟熊岭熊哒;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

//快速排序
public class QuickSort {
	public static void swap(int[] arr, int i, int j) {
		int tmp = arr[i];
		arr[i] = arr[j];
		arr[j] = tmp;
	}

	public static int[] partition(int[] arr, int L, int R) {
		int less = L - 1;// 小于区的右边界
		int more = R;// 大于区的左边界
		while (L < more) {
			// L表示当前数的位置,arr[R]表示划分值
			if (arr[L] < arr[R]) {
				swap(arr, ++less, L++);
				// 如果当前数小于划分值
				// 则当前数和小于区有边界后面一个元素做交换
				// 并将小于区向后扩大1位
				// less++;
				// L++;
			} else if (arr[L] > arr[R]) {
				swap(arr, --more, L);
			} else {
				L++;
			}
		}
		swap(arr, more, R);
		return new int[] { less + 1, more };
		// 返回等于区所处的范围
	}

	public static void process(int[] arr, int L, int R) {
		if (L < R) {
			swap(arr, L + (int) (Math.random() * (R - L + 1)), R);
			// 随机在数组中找一个元素和末尾的值做交换
			int[] p = partition(arr, L, R);
			process(arr, L, p[0] - 1);// 小于区
			process(arr, p[1] + 1, R);// 大于区
		}
	}

	// 快速排序
	public static void quickSort(int[] arr) {
		if (arr == null || arr.length < 2) {
			return;
		}

		int L = 0;
		int R = arr.length - 1;
		process(arr, L, R);// 开始执行
	}

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		System.out.println("请输入元素个数:");
		int n = Integer.parseInt(br.readLine());
		int[] arr = new int[n];

		System.out.println("请输入元素内容(每个元素之间用空格分隔):");
		String[] line = br.readLine().split(" ");
		for (int i = 0; i < line.length; i++) {
			arr[i] = Integer.parseInt(line[i]);
		}

		quickSort(arr);// 快速排序
		System.out.println("排序后:" + Arrays.toString(arr));
	}
}

输出结果:

image.png

对数器测试

package 苟熊岭熊哒;

import java.util.Arrays;

//快速排序
public class QuickSort {
	// 用系统提供的方法进行排序
	public static void comparator(int[] arr) {
		Arrays.sort(arr);
	}

	// 生成一个随机数组
	public static int[] generateRandomArray(int maxSize, int maxValue) {
		// Math.random() -> 随机在[0,1)范围内返回一个double类型的数(等概率)
		// Math.random()*A -> 随机在[0,A)范围内返回一个double类型的数(等概率)
		// (int)(Math.random()*A) -> 随机在[0,A-1]范围内返回一个int类型的数(等概率)
		int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
		for (int i = 0; i < arr.length; i++) {
			arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) ((maxValue + 1) * Math.random());
		}
		return arr;
	}

	// 拷贝数组
	public static int[] copyArray(int[] arr) {
		if (arr == null) {
			return null;
		}

		int[] res = new int[arr.length];
		for (int i = 0; i < arr.length; i++) {
			res[i] = arr[i];
		}
		return res;
	}

	// 判断arr1和arr2中的每个值是否相等
	public static boolean isEqual(int[] arr1, int[] arr2) {
		int i = 0;
		while (i < arr1.length) {
			if (arr1[i] == arr2[i]) {
				i++;
			} else {
				return false;
			}
		}
		return true;
	}

	// 打印数组
	public static void printArray(int[] arr) {
		for (int a : arr) {
			System.out.print(a + " ");
		}
		System.out.println();
	}

	// test

	public static void swap(int[] arr, int i, int j) {
		int tmp = arr[i];
		arr[i] = arr[j];
		arr[j] = tmp;
	}

	public static int[] partition(int[] arr, int L, int R) {
		int less = L - 1;// 小于区的右边界
		int more = R;// 大于区的左边界
		while (L < more) {
			// L表示当前数的位置,arr[R]表示划分值
			if (arr[L] < arr[R]) {
				swap(arr, ++less, L++);
				// 如果当前数小于划分值
				// 则当前数和小于区有边界后面一个元素做交换
				// 并将小于区向后扩大1位
				// less++;
				// L++;
			} else if (arr[L] > arr[R]) {
				swap(arr, --more, L);
			} else {
				L++;
			}
		}
		swap(arr, more, R);
		return new int[] { less + 1, more };
		// 返回等于区所处的范围
	}

	public static void process(int[] arr, int L, int R) {
		if (L < R) {
			swap(arr, L + (int) (Math.random() * (R - L + 1)), R);
			// 随机在数组中找一个元素和末尾的值做交换
			int[] p = partition(arr, L, R);
			process(arr, L, p[0] - 1);// 小于区
			process(arr, p[1] + 1, R);// 大于区
		}
	}

	public static void quickSort(int[] arr) {
		if (arr == null || arr.length < 2) {
			return;
		}

		int L = 0;
		int R = arr.length - 1;
		process(arr, L, R);// 开始执行
	}

	public static void main(String[] args) {
		int testTime = 500000;// 测试次数,50万次
		int maxSize = 100;// 数组的规模不大于100
		int maxValue = 100;// 数组中每个值的范围,-100~+100
		boolean succeed = true;
		for (int i = 0; i < testTime; i++) {
			int[] arr1 = generateRandomArray(maxSize, maxValue);
			// 创建一个数组,长度随机,值也随机
			int[] arr2 = copyArray(arr1);
			// 拷贝arr1中的值和长度
			quickSort(arr1);// 快速排序
			comparator(arr2);// 用系统提供的排序,来排arr2
			// 排完序后,比较arr1和arr2的每个位置的值都是不是一样
			if (isEqual(arr1, arr2) == false) {
				// 若值不一样,则该次测试失败
				succeed = false;
				printArray(arr1);// 打印arr1排成了什么样
				printArray(arr2);// 打印arr2排成了什么样
				break;// 跳出循环
			}
		}
		System.out.println(succeed == true ? "完全正确!" : "有错误");
	}
}

测试结果:

image.png


7、*计数排序(不含对数器)

应用范围很有限,如果数据有变动,算法很可能要大规模重写

package 牛客算法基础入门;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

//计数排序
public class CountSort {
	public static void countSort(int[] arr) {
		if (arr == null | arr.length < 2) {
			return;
		}

		int max = Integer.MIN_VALUE;

		// 找出最大值
		for (int i = 0; i < arr.length; i++) {
			max = Math.max(max, arr[i]);
		}

		// 准备一个 max+1 个桶
		int[] bucket = new int[max + 1];

		// 计数
		for (int i = 0; i < arr.length; i++) {
			bucket[arr[i]]++;
		}

		int i = 0;
		// 倒出
		for (int j = 0; j < bucket.length; j++) {
			while (bucket[j]-- > 0) {
				arr[i++] = j;
			}
		}
	}

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		System.out.println("请输入元素个数:");
		int n = Integer.parseInt(br.readLine());
		int[] arr = new int[n];

		System.out.println("请输入元素内容(每个元素之间用空格分隔):");
		String[] line = br.readLine().split(" ");
		for (int i = 0; i < line.length; i++) {
			arr[i] = Integer.parseInt(line[i]);
		}

		countSort(arr);// 计数排序
		System.out.println("排序后:" + Arrays.toString(arr));
	}
}

输出结果:
image.png


8、*基数排序(不含对数器)

只能处理非负值

package 牛客算法基础入门;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

//基数排序
public class RadixSort {

	public static int maxbits(int[] arr) {
		int max = Integer.MIN_VALUE;
		for (int i = 0; i < arr.length; i++) {
			max = Math.max(max, arr[i]);
		}

		int res = 0;
		while (max != 0) {
			res++;
			max /= 10;
		}

		return res;
	}

	public static int getDigit(int x, int d) {
		return ((x / ((int) Math.pow(10, d - 1))) % 10);
	}

	public static void radixSort(int[] arr, int L, int R, int digit) {
		// digit:最大的数有几个十进制位
		final int radix = 10;// 表示10进制
		int i = 0, j = 0;

		// 有多少个数准备多少个辅助空间
		int[] bucket = new int[R - L + 1];

		for (int d = 1; d <= digit; d++) {// 有多少位就进出几次
			int[] count = new int[radix];
			// 统计数组,范围始终是[0~9]

			for (i = L; i <= R; i++) {
				j = getDigit(arr[i], d);// 取出个位数字
				count[j]++;
				// 此时的count数组,表示个位数字等于其索引值的数有几个
			}

			for (i = 1; i < radix; i++) {
				count[i] = count[i] + count[i - 1];
				// 此时的count数组,表示个位数字<=其索引值的数有几个
			}

			for (i = R; i >= L; i--) {
				j = getDigit(arr[i], d);// 取出个位数字
				bucket[count[j] - 1] = arr[i];
				count[j]--;
			}

			for (i = L, j = 0; i <= R; i++, j++) {
				arr[i] = bucket[j];
				// 将bucket的元素拷贝到原数组
			}
		}
	}

	public static void radixSort(int[] arr) {
		if (arr == null || arr.length < 2) {
			return;

		}

		radixSort(arr, 0, arr.length - 1, maxbits(arr));
	}

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		System.out.println("请输入元素个数:");
		int n = Integer.parseInt(br.readLine());
		int[] arr = new int[n];

		System.out.println("请输入元素内容(每个元素之间用空格分隔):");
		String[] line = br.readLine().split(" ");
		for (int i = 0; i < line.length; i++) {
			arr[i] = Integer.parseInt(line[i]);
		}

		radixSort(arr);// 基数排序
		System.out.println("排序后:" + Arrays.toString(arr));
	}
}


输出结果:

image.png


各排序的性能统计

image.png

总结:时间选快排,空间选堆排,稳定选归并。


常见排序的介绍到这里就结束了,如果你觉得本篇文章对你多少有些帮助,可以点个赞或者收藏一波支持一下哦,欢迎各位大佬批评指正,咱们下次再见!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值