快速排序算法与舍伍德快速排序算法

排序算法是比较常见的算法,道理也比较简单,双指针法。今天被朋友问了个舍伍德排序算法,也是快速排序那种形式。尴尬,第一次听说,特意学了一下。结合快速排序,写了三个方法。
第一种:

	//不需要将基准值归位的快速排序
public static void quickSort(int []a,int left,int right) {
	if(left>=right) return ;
	int i = left ;//左指针
	int j = right ;//右指针
	int key = a[i];//基准值
	while(i<j) {
		//右指针先遍历,直到找到一个小于基准值的
		while(i<j&&a[j]>=key) j--;
		//交换右指针与左指针的值
		if(i<j&&a[j]<key) {
			int temp = a[i];
			a[i] = a[j];
			a[j] = temp;
		}
		//左指针遍历,直到找到一个大于基准值的
		while(i<j&&a[i]<=key)i++;
		//交换左右指针的值
		if(i<j&&a[j]>key) {
			int temp = a[i];
			a[i] = a[j];
			a[j] = temp;
		}
	}
	//递归处理左右数组
	quickSort(a,left,i-1);
	quickSort(a,i+1,right);
	
}

第二种:

//需要将基准值归位的快速排序
public static void quickSort2(int []a,int left,int right) {
	if(left>=right) return ;
	int i = left ;//左指针
	int j = right ;//右指针
	int key = a[i];//基准值
	while(i<j) {
		//右指针先遍历,直到找到一个小于基准值的
		while(i<j&&a[j]>=key) j--;
		//左指针遍历,直到找到一个大于基准值的
		while(i<j&&a[i]<=key)i++;
		//交换左右指针的值
		if(i<j) {
			int temp = a[i];
			a[i] = a[j];
			a[j] = temp;
		}
	}
	a[left]=a[j];
	a[j] = key;
	//递归处理左右数组
	quickSort(a,left,i-1);
	quickSort(a,i+1,right);
	
}

第三种:舍伍德算法
一般快速排序存在最好最坏情况。
最好情况:
当一组数无序,每次划分成两个数组时,都能均匀的分成两部分。这样最好情况复杂度为nlogn。()
最坏情况:
当一组数有序,每次划分都只能划分掉一个数,最终复杂度为n^2.
如1 2 3 4 5 第一次分为 1 2345
第二次分为 2 345
第三次分为 3 45
第四次 4 5
这样相当于要划分n次,每次比较数也看做n,则为n^2。
虽然快速排序平均复杂度可以看做nlogn.但算法复杂度与输入实例之间有关系,未必都是平均时间复杂度。
这就是要采用舍伍德快速排序的原因,消除掉算法复杂度与输入实例之间的关系。


//舍伍德快速排序算法(找到第K大的数)
public static int quickSort3(int []a,int k) throws Exception {
	if(k>a.length||k<=0) throw new Exception("k值输入不在异常");
	int l= 0;
	int r = a.length-1;
	while(true) {
	if(l>=r) return a[l];
	int i = l;
	//随机获取一个基准
	Random rnd = new Random();
	int j = 1+rnd.nextInt(r-1);
	//交换a[i]与基准的值,使得基准为左边第一个
	swap(a,i,j);
	j = r+1;
	int pivot = a[l];
	while(true) {
		//找到大于pivot的值后,跳出循环
		while(i<a.length-1&&a[++i]<pivot) ;
		//找到小于pivot的值后,跳出循环
		while(j>0&&a[--j]>pivot) ;
		if(i>=j) break;
		swap(a,i,j);
	}
	//第一次循环结束后,判断此时的j,处在第几大的位置
	if(j-l+1 == k) return pivot;
	//基准归位,因为此时j的值小于基准,而基准在第一个位置,下面
	//两条语句交换完后,保证左边的数都小于基准,右边的都大于
	a[l] = a[j];
	a[j] = pivot;
	//对子数组重新进行划分
	if(j-l+1<k) {
		k = k-j+l-1;
		l=j+1;//如果左边的数小于K个,l=j+1从右边数组继续划分	
	}else r=j-1;
	}
	
	
	
	
}
  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
舍伍德随机快速排序算法是一种基于快速排序的改进算法,它通过随机选择枢轴元素来提高排序的效率和稳定性。下面是舍伍德随机快速排序算法的编程实验介绍: 1. 首先,我们需要定义一个函数来实现舍伍德随机快速排序算法。函数的输入参数包括待排序数组和数组的起始位置和结束位置。 2. 在函数内部,我们首先需要判断起始位置是否小于结束位置,如果不是,则直接返回。 3. 接下来,我们需要选择一个随机的枢轴元素。可以使用随机数生成器来生成一个在起始位置和结束位置之间的随机索引,然后将对应的元素作为枢轴元素。 4. 将枢轴元素与数组的最后一个元素进行交换,这样可以方便地将枢轴元素放在正确的位置上。 5. 接下来,我们需要遍历数组,将小于枢轴元素的元素放在左边,大于枢轴元素的元素放在右边。可以使用两个指针,一个指向左边的起始位置,一个指向右边的起始位置。 6. 当左指针小于右指针时,我们需要进行以下操作: - 从左边开始找到第一个大于枢轴元素的元素,将其与右指针指向的元素进行交换。 - 从右边开始找到第一个小于枢轴元素的元素,将其与左指针指向的元素进行交换。 7. 重复步骤6,直到左指针大于等于右指针。 8. 将枢轴元素放在正确的位置上,即将其与左指针指向的元素进行交换。 9. 现在,枢轴元素左边的元素都小于它,右边的元素都大于它。我们可以递归地对左右两个子数组进行排序。 10. 最后,我们可以通过递归调用舍伍德随机快速排序函数来完成整个排序过程。 下面是一个示例的舍伍德随机快速排序算法的实现: ```python import random def shuffle_quick_sort(arr, start, end): if start < end: pivot_index = random.randint(start, end) arr[pivot_index], arr[end] = arr[end], arr[pivot_index] pivot = arr[end] i = start - 1 for j in range(start, end): if arr[j] < pivot: i += 1 arr[i], arr[j] = arr[j], arr[i] arr[i+1], arr[end] = arr[end], arr[i+1] pivot_index = i + 1 shuffle_quick_sort(arr, start, pivot_index - 1) shuffle_quick_sort(arr, pivot_index + 1, end) # 测试 arr = [5, 2, 9, 1, 7, 6, 3] shuffle_quick_sort(arr, 0, len(arr) - 1) print(arr) ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值