【快速排序】【求数组的前k个最小的数】【出现次数超过一半的数】

转自:https://blog.csdn.net/vayne_xiao/article/details/53508973

为什么快速排序一定要先从右边开始

  1. while(arr[j]>=temp&&i<j){
  2. j--;
  3. }
  4. while(arr[i]<=temp&&i<j){
  5. i++;
  6. }

这里两个while的顺序是不能改变的,想一想:

假设对如下进行排序:

如上图,6在左,9在右  我们将6作为基数。

假设从左边开始(与正确程序正好相反)

于是i 就会移动到现在的 数字 7 那个位置停下来,而  j 原来在 数字 9 那个位置 ,因为

 
  1. while(arr[j]>=temp&&i<j)

于是,j 也会停留在数字7 那个位置,于是问题来了。当你最后交换基数6与7时,不对呀!!。

问题在于当我们先从在边开始时,那么 i 所停留的那个位置肯定是大于基数6的,而在上述例子中,为了满足 i<j 于是 j也停留在7的位置

但最后交换回去的时候,7就到了左边,不行,因为我们原本 交换后数字6在边应该是全部小于6,右边全部大于6.但现在不行了。

于是,我们必须从右边开始,也就是从基数的对面开始。

 

求数组的前K个最小的数

#include<stdio.h>
#include<error.h>

#define ERROR	-22

static int quicksort(int *arr, int left, int right, int k)
{
	int l, r, base, temp;
	if(arr==NULL){
		fprintf(stderr, "arr should not be NULL\n");
		return ERROR;
	}
	if(left>right){
		return 0;
	}
	base = arr[left];
	l = left;
	r = right;
	while(l<r){
		
		// 为什么一定是先右边呢?
		//先右边
		while(base<=arr[r]&&l<r){
			r--;
		}
		//再左边
		while(base>=arr[l]&&l<r){
			l++;
		}
		if(l<r){
			temp = arr[r];
			arr[r] = arr[l];
			arr[l] = temp;
		}
	}
	arr[left] = arr[l];
	arr[l] = base;
	if(l<k){
		quicksort(arr, left, l-1, k);
		quicksort(arr, l+1, right, k);
	}else{
		quicksort(arr, left, l-1, k);
	}
	return base;
}
int main()
{
	int arr[] = {6,1,2,5,4,3,9,7,10,8};
	int b = 0;
	int k = 3;
	int ret = quicksort(arr, 0, sizeof(arr)/sizeof(arr[0]), k);
	
	
	int i =0;
	for(i=0; i<sizeof(arr)/sizeof(arr[0]); i++){
		printf("%d\t", arr[i]);
	}
	printf("\n");
}

出现次数超过一半的数

#include<stdio.h>
#include<error.h>
 
#define ERROR	-22
 
static int quicksort(int *arr, int left, int right, int k)
{
	int l, r, base, temp;
	if(arr==NULL){
		fprintf(stderr, "arr should not be NULL\n");
		return ERROR;
	}
	if(left>right){
		return 0;
	}
	base = arr[left];
	l = left;
	r = right;
	while(l<r){
		
		// 为什么一定是先右边呢?
		//先右边
		while(base<=arr[r]&&l<r){
			r--;
		}
		//再左边
		while(base>=arr[l]&&l<r){
			l++;
		}
		if(l<r){
			temp = arr[r];
			arr[r] = arr[l];
			arr[l] = temp;
		}
	}
	arr[left] = arr[l];
	arr[l] = base;
	if(l==k){
		return arr[k];
	}else if(l>k){
		quicksort(arr, left, l-1, k);
	}else{
		quicksort(arr, l+1, right, k);
	}

	return 0;
}
int main()
{
	int arr[] = {6,6,2,5,4,3,6,6,6,6};
	int b = 0;
	int k = sizeof(arr)/sizeof(arr[0])/2;
	int ret = quicksort(arr, 0, sizeof(arr)/sizeof(arr[0]), k);
	
	printf("%d\n", arr[k]);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值