快速排序(分治算法)--例:数组a[]中找出第k小的元素

什么是快速排序呢?

说的简单点儿就是:你现在要对一串数据进行排序(如 9  4  6  3  11  7),现在有一种办法就是:假设你看到9这个数字比较舒服 你就选择5作为一个分界点开始排序 经过一轮排序下来 9左边的数都比9小 9右边的数都比9大,这只是一轮 第二轮就可以分两边了 然后依次类推 在这个过程中就需要用到递归 我们还可以知道 要对左右两边分别递归 最后就出来。这是我对快速排序最简单的理解。

现在通过图来对快速排序进行更深一步的了解

我们对数组 9 4 6 3 11 7 进行了第一轮排序;选择9作为关键字  那么在一轮排序下来后 9左边的数都比9小 9右边的数都比9大 那么又分别对9左边的数进行排序递归 对右边的数进行排序递归

相关代码实现:

package practice;

public class _15 {
	public static void sort(int[] a, int low, int high) {
		// 已经排完
		if (low >= high) {
			return;
		}
		int l = low;
		int r = high;

		// 保存基准值
		int key = a[l];
		while (l < r) {
			// 从最右边开始进行比较 如果找到比关键字小的就要将值放在左边去
			while (l < r && a[r] >= key)
				r--;
			a[l] = a[r];
			// 从最左边开始进行比较 如果找到比关键字大的就将值放到右边去
			while (l < r && a[l] <= key)
				l++;
			a[r] = a[l];
		}
		// 关键字 默认为排序数组的第一位 当然也可以自己选择
		a[l] = key;
		// 对关键字左边的数进行递归
		sort(a, low, l - 1);
		// 对关键字右边的数字进行递归
		sort(a, l + 1, high);
	}

	public static void main(String[] args) {
		int[] arr = { 9, 4, 6, 3, 11, 7 };
		sort(arr, 0, 5);
		for (int i = 0; i < 6; i++) {
			System.out.println(arr[i]);
		}
	}
}

运行结果:

例子:

数组a[]中找出第k小的元素。 它使用了类似快速排序中的分治算法,期望时间复杂度是O(N)的

这个题是一个填空题 当时做的时候我忽略了k的选取 因为始终后台报错

简单说下这个代码的意思:这个代码就是给你一个数组 让你找出第k小的元素 那么首先我们就要对数组元素进行排序 这里关键字的选择就是随机选择的 其中的i j 就相当于我们上一个代码中的l r 所以这个好理解 这里需要注意的是关于k

 (i - l + 1 < k)说明你所要找的第k小的元素不在你关键字所排序的左边 那么就在右边 那么你在对右边排序的时候 就相当于是右边  的 k - (i - l + 1)小     quickSelect(a, i + 1, r, k - (i - l + 1));

(i - l + 1 < k)就和上面的恰恰相反 这个就直接quickSelect(a, l, i - 1, k)

这个注意了 这个题就解决了

package practice;

import java.util.Random;

/**
 * 数组a[]中找出第k小的元素。 它使用了类似快速排序中的分治算法,期望时间复杂度是O(N)的
 * 
 * @author fulisha
 *
 */
public class _14 {
	public static int quickSelect(int a[], int l, int r, int k) {
		Random rand = new Random();
		int p = rand.nextInt(r - l + 1) + l;
		// 产生一个关键字 并且将关键字放在最后的最后去
		int x = a[p];
		int tmp = a[p];
		a[p] = a[r];
		a[r] = tmp;
		// 类型于两个指针 i指向第一个 位置 j指向关键字位置
		int i = l, j = r;

		while (i < j) {
			// 如果a[i]的值小于关键字就i++
			while (i < j && a[i] < x)
				i++;
			if (i < j) {
				// 当a[i]>关键字 就将关键字做一个改变 就开始移动j的位置
				a[j] = a[i];
				j--;
			}

			while (i < j && a[j] > x)
				j--;
			if (i < j) {
				a[i] = a[j];
				i++;
			}
		}
		a[i] = x;
		p = i;
		if (i - l + 1 == k)
			return a[i];
		if (i - l + 1 < k)
			// 此处为待填的空
			return quickSelect(a, i + 1, r, k - (i - l + 1));

		else
			return quickSelect(a, l, i - 1, k);
	}

	public static void main(String args[]) {
		int[] a = { 1, 4, 2, 8, 5, 7 };

		System.out.println(quickSelect(a, 0, 5, 4));
	}
}

 

 

  • 4
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值