二分查找和快速排序

一、二分查找

二分查找的基本思想:

​ 二分查找就是给定一个已经排序好的数组,输入你想查找的数值,然后对数组进行折半查找,找到直接返回在数组中的位置,否则返回-1。它充分利用了元素间的次序关系,采用分治策略,可在最坏的情况下用O(log n)完成搜索任务。

具体实现:

1、binarySearch函数传入已经排序好的数组(nums[]),你想查找的目标数值(target),数组的长度(length)

2、binarySearch中先设置数组的左右边界left、right,然后求解数组的中间位置mid,判断其与目标数值的大小,如果中间位置的数值刚好等于目标数值,则直接返回mid。如果中间数值小于目标数值,说明目标数值在中间位置后方重置left=mid+1,反之目标数值就是在中间位置的前方重置right=mid-1。直到查找到目标数值并且返回目标数值在数组中的位置。

二分查找算法的时间复杂度分析:
时间复杂度即是while循环的次数。总共有n个元素,渐渐跟下去就是n,n/2,n/4,…n/2k(接下来操作元素的剩余个数),其中k就是循环的次数由于你n/2k取整后>=1,即令n/2^k=1,可得k=log2n,(是以2为底,n的对数)。所以时间复杂度可以表示O(h)=O(log2n)=O(log n)。

O(log2n)是以2为底数,n为对数的对数函数,O(log n)同理只不过底数2省略了

//二分查找:对有顺序的数组中特定元素进行的快速查找的算法 。 
#include<stdio.h>

int binarySearch(int nums[],int target,int length);

int main(){
	int i,n,target;
	scanf("%d %d",&n,&target);
	int a[n];
	for(i=0;i<n;i++){
		scanf("%d",&a[i]);
	}
	printf("%d",binarySearch(a,target,n));
	return 0;
}

int binarySearch(int nums[], int target,int length) {
    //设置左右边界
    int left = 0; 
    int right = length - 1; 

    while(left <= right) { 
        //计算数组的中间位置mid
        int mid = (right + left) / 2; 
        if(nums[mid] == target)  //如果中间位置找到直接返回
            return mid; 
        else if (nums[mid] < target)//如果中间位置的数值小于目标数值,说明目标数值在数组的右边
            left = mid + 1; 
        else if (nums[mid] > target)//如果中间位置的数值大于目标数值,说明目标数值在数组的左边
            right = mid - 1; 
        }
    return -1;
}

二、快速排序

快速排序的基本思想:

  1. 先从给定的数组中取出一个基准数
  2. 划分过程,小于等于基准数的放在左边,大于基准数的放在右边
  3. 再对左右区间重复第2步操作,直到各区间只有一个数

快速排序的时间复杂度分析:

快速排序的一次划分算法从两头交替搜索,直到low和hight重合,因此其时间复杂度是O(n);而整个快速排序算法的时间复杂度与划分的趟数有关。 [4]

理想的情况是,每次划分所选择的中间数恰好将当前序列几乎等分,经过log2n趟划分,便可得到长度为1的子表。这样,整个算法的时间复杂度为O(nlog2n)。 [4]

最坏的情况是,每次所选的中间数是当前序列中的最大或最小元素,这使得每次划分所得的子表中一个为空表,另一子表的长度为原表的长度-1。这样,长度为n的数据表的快速排序需要经过n趟划分,使得整个排序算法的时间复杂度为O(n2)。 [4]

为改善最坏情况下的时间性能,可采用其他方法选取中间数。通常采用“三者值取中”方法,即比较H->r[low].key、H->r[high].key与H->r[(low+high)/2].key,取三者中关键字为中值的元素为中间数。 [4]

可以证明,快速排序的平均时间复杂度也是O(nlog2n)。因此,该排序方法被认为是目前最好的一种内部排序方法。

快速排序的时间复杂度分析引用于百度百科
百度百科-快速排序算法

//快速排序:不断的划分左右两边的数值 ,以一个数为基准左边的数永远小于右边的数。最后的划分都是对两个数值的比较。 
#include<stdio.h>

void QuickSort(int a[],int p,int r); //分治代码

int Partition(int a[],int p,int r);//填坑代码

int main(){
	int i,n;
	scanf("%d",&n);
	int a[n];
	for(i=0;i<n;i++){
		scanf("%d",&a[i]);
	}
	
	QuickSort(a,0,n-1);
	
	for(i=0;i<n;i++){
		printf("%d",a[i]);
	}
	return 0;
}

void QuickSort(int a[],int p,int r){
	if(p<r){
		int q = Partition(a,p,r);
		QuickSort(a,p,q-1);
		QuickSort(a,q+1,r); 
	}
}

//对a的数组从p到r以a[p]为基准进行分割,左边永远比a[p]小,右边永远比a[p]大。
int Partition(int a[],int p,int r){
	int tmp; 
	int i=p,j=r+1;
	//以第一个数为基准来进行左右两边的划分! 
	int x=a[p];
	printf("%d\n",x); 
	while(true){
		while(a[++i]<x&&i<r) ;//找出左边第一个比数值大的 
		while(a[--j]>x) ; //找出右边第一个比数值小的 
		if(i>=j) break;
		//Swap(a[i],a[j]);    交换两个数的位置 
		tmp=a[i];
		a[i]=a[j];
		a[j]=tmp;
	}
	a[p]=a[j];
	a[j]=x;
	return j;
}

快速排序还有很多改进版本,如随机选择基准数,区间内数据较少时直接用另的方法排序以减小递归深度 。

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值