编程语言
首页 > 编程语言> > 笔试必备,8种排序算法的Java实现,附标准答案!

笔试必备,8种排序算法的Java实现,附标准答案!

作者:互联网

一、Java版希尔排序(缩小增量排序)

复杂度 平均 O(n^1.3) 最好O(n) 最差O(n^s)[1

内循环通过模拟并行的方式完成分组的内部直接插入排序,而不是一个一个分组分组的排,在10w的随机数据20w的随机数据均表现优异。

public void shellSort(int[] a) {
	if (null == a || a.length < 2) {
		return;
	}
	for (int d = a.length/2; d > 0; d/=2) {
		// 从1B开始先和1A比较 然后2A与2B...然后再1C向前与同组的比较
		for (int i = d; i < a.length; i++) {
		// 内部直接插入
			int temp = a[i];
			int j = i - d;
			while (j >=0 && temp < a[j]) {
				a[j+d] = a[j];
				j -= d;
			}
			a[j+d] = temp;
		}
	}
}

二、Java版插入排序 

适用于小数组,数组已排好序或接近于排好序速度将会非常快

复杂度:O(n^2) - O(n) - O(n^2) - O(1)[平均 - 最好 - 最坏 - 空间复杂度]

public void insertionSort(int[] a) {
		if (null == a || a.length < 2) {
			return;
		}
		for (int i = 1; i < a.length; i++) {
			// 暂存当前值
			int temp = a[i];
			int j = i - 1;
			while (j >= 0 && temp < a[j]) {
				// 后移
				a[j + 1] = a[j];
				j--;
			}
			// 当前值归位
			a[j + 1] = temp;
		}
	}

三、Java版冒泡排序

复杂度:O(n^2) - O(n) - O(n^2) - O(1)[平均 - 最好 - 最坏 - 空间复杂度]

public void bubbleSort(int[] a) {
		if (null == a || a.length < 2) {
			return;
		}
		boolean flag;
		for (int i = 0; i < a.length-1; i++) {
			flag = false;
			for (int j = 0; j < a.length-1-i; j++) {
				if (a[j] > a[j+1]) {
					int temp = a[j];
					a[j] = a[j+1];
					a[j+1] = temp;
					flag = true;
				}
			}
			if (false == flag) {
				return;
			}
		}
	}

四、Java版归并排序

原理:采用分治法

复杂度:O(nlogn) - O(nlgn) - O(nlgn) - O(n)[平均 - 最好 - 最坏 - 空间复杂度]

// 排序
	public void mergeSort(int[] a, int low, int high) {

		int mid = (low + high) / 2;
		if (low < high) {
			// 左边排序
			mergeSort(a, low, mid);
			// 右边排序
			mergeSort(a, mid + 1, high);
			// 有序序列合并
			merge(a, low, mid, high);
		}
	}
	
	// 合并
	private void merge(int a[], int low, int mid, int high) {
		// 临时数组
		int[] temp = new int[high - low + 1];
		// 左指针
		int i = low;
		// 右指针
		int j = mid + 1;
		// 临时数组索引
		int k = 0;
		
		while (i <= mid && j <= high) {
			if (a[i] < a[j]) {
				temp[k++] = a[i++];
			} else {
				temp[k++] = a[j++];
			}
		}
		
		// 把左边剩余的数移入数组  
		while (i <= mid) {
			temp[k++] = a[i++];
		}
		
		// 把右边剩余的数移入数组  
		while (j <= high) {
			temp[k++] = a[j++];
		}
		
		// 注意这里是low + t
		for (int t = 0; t < temp.length; t++) {
			a[low + t] = temp[t];
		}
	}

五、Java版选择排序

原理:每次从无序序列选取最小的

复杂度:O(n^2) - O(n^2) - O(n^2) - O(1)[平均 - 最好 - 最坏 - 空间复杂度]

public void selectSort(int[] a) {
		if (null == a || a.length < 2) {
			return;
		}
		for (int i = 0; i < a.length; i++) {
			int k = i;
			for (int j = i + 1; j < a.length; j++) {
				if (a[j] < a[k]) {
					k = j;
				}
			}
			if (k!=i) {
				int temp = a[k];
				a[k] = a[i];
				a[i] = temp;
			}
		}
	}

六、Java版堆排序

堆一般指二叉堆。

复杂度:O(nlogn) - O(nlgn) - O(nlgn) - O(1)[平均 - 最好 - 最坏 - 空间复杂度]

大顶堆实现从小到大的升序排列,小顶堆一般用于构造优先队列

	public void heapSort(int[] a) {
		if (null == a || a.length < 2) {
			return;
		}
		
		buildMaxHeap(a);
		
		for (int i = a.length - 1; i >= 0; i--) {
			int temp = a[0];
			a[0] = a[i];
			a[i] = temp;
			
			adjustHeap(a, i, 0);
		}
	}

	// 建堆
	private void buildMaxHeap(int[] a) {
		int mid = a.length / 2;
		for (int i = mid; i >= 0; i--) {
			adjustHeap(a, a.length, i);
		}
	}
	
	// 递归调整堆
	private void adjustHeap(int[] a, int size, int parent) {
		int left = 2 * parent + 1;
		int right = 2 * parent + 2;
		
		int largest = parent;
		if (left < size && a[left] > a[parent]) {
			largest = left;
		}
		
		if (right < size && a[right] > a[largest]) {
			largest = right;
		}
		
		if (parent != largest) {
			int temp = a[parent];
			a[parent] = a[largest];
			a[largest] = temp;
			adjustHeap(a, size, largest);
		}
	}

七、Java版快速排序

原理:分治+递归

复杂度:O(nlgn) - O(nlgn) - O(n^2) - O(1)[平均 - 最好 - 最坏 - 空间复杂度]

栈空间0(lgn) - O(n)

// 固定基准
public void quickSort(int[] a, int low, int high) {
		if (null == a || a.length < 2) {
			return;
		}
		if (low < high) {
			int mid = partition(a, low, high);
			quickSort(a, low, mid-1);
			quickSort(a, mid+1, high);
		}
	}

	private int partition(int[] a, int low, int high) {
		int pivot = a[low];

		while (low < high) {
			// 注意等于,否则死循环
			while (low < high && a[high] >= pivot) {
				high--;
			}
			a[low] = a[high];
			// 注意等于,否则死循环
			while (low < high && a[low] <= pivot) {
				low++;
			}
			a[high] = a[low];
		}
		a[low] = pivot;
		
		return low;
	}

八、Java版基数排序

原理:分配加收集

复杂度: O(d(n+r)) r为基数d为位数 空间复杂度O(n+r)

// 基数排序
	public void radixSort(int[] a, int begin, int end, int digit) {
		// 基数
		final int radix = 10;
		// 桶中的数据统计
		int[] count = new int[radix];
		int[] bucket = new int[end-begin+1];
		
		// 按照从低位到高位的顺序执行排序过程
		for (int i = 1; i <= digit; i++) {
			// 清空桶中的数据统计
			for (int j = 0; j < radix; j++) {
				count[j] = 0;
			}
			
			// 统计各个桶将要装入的数据个数
			for (int j = begin; j <= end; j++) {
				int index = getDigit(a[j], i);
				count[index]++;
			}
			
			// count[i]表示第i个桶的右边界索引
			for (int j = 1; j < radix; j++) {
				count[j] = count[j] + count[j - 1]; 
			}
			
			// 将数据依次装入桶中
            // 这里要从右向左扫描,保证排序稳定性 
			for (int j = end; j >= begin; j--) {
				int index = getDigit(a[j], i);
				bucket[count[index] - 1] = a[j];
				count[index]--;
			}
			
			// 取出,此时已是对应当前位数有序的表
			for (int j = 0; j < bucket.length; j++) {
				a[j] = bucket[j];
			}
		}
	}
	
	// 获取x的第d位的数字,其中最低位d=1
	private int getDigit(int x, int d) {
		String div = "1";
		while (d >= 2) {
			div += "0";
			d--;
		}
		return x/Integer.parseInt(div) % 10;
	}
}

点击此处免费领取Java全套学习资料:包含2021最新完整面试题及答案(都整理成文档),有很多干货,包含mysql,netty,spring,线程,spring cloud、JVM、源码、算法等详细讲解,也有详细的学习规划图,面试题整理等学习资料!

如果觉得本文对你有帮助,请三连支持一下 谢谢!

标签:笔试,Java,temp,int,复杂度,标准答案,high,length,low
来源: https://blog.csdn.net/Soar_M/article/details/116542907