【数据结构】Java希尔、快速、基数排序总结

  记录一下,以后面试的时候过来背背

希尔排序

  希尔排序又称“增量排序”,是直接插入排序算法的改进版本,对于中等规模数据的性能表示不错

排序思想

  希尔分组会将目前较大的分组分成若干份小组,然后分别对每一个小组进行直接插入排序,此时,由于分组较小,使用插入排序效率高
在这里插入图片描述
  希尔排序分组的标准是按照数组的length/2的下标相隔距离来进行分组的,这里下标之间的差值或距离被称为增量。再对每一组进行排序后,每个小组都有序了,虽然整个数组仍然不是有序的,所以我们可以接着进行循环,也就是使增量/2
在这里插入图片描述
  可以看到这里增量为2,同理对每个分组进行排序,使得各个分组各自有序,最后得到的数组由于增量/2为1,则整个数组被分为了一组,此时的数组接收插入排序效率较高

代码实现

public static void shellSort(int[] array){
	for(int gap = array.length / 2; gap > 0; gap /= 2){
		for(int i = gap; i < array.length; i++){
			int j = i;		//记录下标
			int temp = array[j];	//记录要位移的值
			if(array[j] < array[j-gap]){
				//如果j下标处的数字小于j-gap下标处的数字
				while(j - gap >= 0 && temp < array[j-gap]){
					//移动
					array[j]=array[j-gap];
					j -= gap;
				}
				//退出循环后就找了temp的插入位置
				array[j] = temp;
			}
		}
	}
}

快速排序

  快速排序由于排序效率在同为O(N*logN)的几种排序方法中效率较高,又因为分治法确实实用,所以面试经常有,基本思想:

  • 先从数列中取出一个数作为基准数
  • 分区过程中,较大的数放到它的右边,较小或等于它的数放到它的左边
  • 再对左右分区重复第二步,直到各区间只有一个数

排序思想

  假设最开始我们选择的基准数是数组的第一位,此时我们还需要用一个mid取去存储基准数,设置两个记录下标left=0,right=array.length-1,读取位置是设置基准数的相反位置
在这里插入图片描述

代码实现

public static void quick_sort(int[] array, int left, int right){
	if(left < right){
		int mid = get_mid(array, left, right);
		quick_sort(array, left, mid-1);
		quick_sort(array, mid+1, right);
	}
}

public static int get_mid(int[] array, int left, int right){
	int pivot = array[left];
	while(left < right){
		while(array[right]>=pivot && left < right) right--;
			array[left] = array[right];
		while(array[left] <= pivot && left < right) left++;
			array[right] = array[left];
	}
	array[left] = pivot;
	return left;
}

基数排序

  又称“桶子法”,从低位开始将待排序的数按照这一位的值放到相应的编号为0~9的桶中。等到低位排完得到一个子序列,再将这个序列按照次低位的大小进入相应的桶中,一直排到最高位为止,数组排序完成

代码实现

public static void radixSort(int[] arr){
	//定义一个二维数组表示10个桶 每个桶就是一个一维数组
	int[][] bucket = new int[10][arr.length];

	//为了记录每个桶中 实际存放了多个个数据,定义一个一维数组记录每个桶中每次放入的数据个数
	int[] bucketElementCount = new int[10];
	
	//先遍历得到数组中最大的数和它的位数
	int max = arr[0];
	for(int i = 0; i < arr.length; i++){
		if(arr[i] > max) max = arr[i];
	}
	//得到最大位数
	int maxLength = (max + "").length();

	//n用来控制位数
	for(int i = 0, n = 1; i < maxLength; i++, n*=10){
		for(int j = 0; j < arr.length; j++){
			//取出每个元素的个位的值
			int digitOfElement = arr[j] / n % 10;
			//放到对应的桶中
			bucket[digitOfElement][bucketElementCount[digitOfElement]] = arr[j];
			bucketElemerntCount[digitOfElement]++;
		}
		int index = 0;
		//按照这个桶的顺序取出数据 放入到原来的数组中
		for(int k = 0; k <bucketElementCount.length; k++){
			//如果桶中有数据 才能放置
			if(bucketElementCount[k] != 0){
				for(int l = 0; ; < bucketElementCount[k]; l++){
					arr[index++]=bucket[k][l];
				}
			}
			bucketElementCount[k] = 0;
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值