【分治 || 排序问题、查找问题、最大子序列和问题】

本文详细介绍了几种常见的排序算法,包括分治法的快速排序、冒泡排序、选择排序以及二路归并排序,探讨了它们的时间复杂度。此外,还涉及查找最大和次大元素、折半查找、查找第K小元素以及寻找两个等长有序序列中位数的方法,均为解决数据处理中的核心问题提供了解决方案。
摘要由CSDN通过智能技术生成

分治法

选择排序

void SelectSort(int a[],int n,int i)
{
	int k;
	//递归出口
	if(i==n-1) return;
	else
	{
		k=i;
		for(int j=i+1;j<n;j++)
			if(a[j]<a[k])
				k=j;
		if(k!=i)
			swap(a[i],a[k]);
		SelectSort(a,n,i+1);
	}
}

时间复杂度:O( n 2 n^2 n2)

冒泡排序

void BubbleSort(int a[],int n,int i)
{
	bool flag;
	if(i==n-1) return;
	else
	{
		flag=false;
		for(int j=n-1;j>i;j--)
		{
			if(a[j]<a[j-1])
			{
				swap(a[j],a[j-1]);
				flag=true;
			}
		}
		if(flag==false) return;
		else BubbleSort(a,n,i+1);
	}
}

时间复杂度:O( n 2 n^2 n2)

快速排序

void QuickSort(int a[],int s,int t)
{
	if(s<t)
	{
		int i=partition(a,s,t);
		QuickSort(a,s,i-1);
		QuickSort(a,i+1,t);
	}
}
int partition(int a[],int s,int t)
{
	int i=s,j=t;
	int temp=a[s];
	while(i!=j)
	{
		while(j>i&&a[j]>=temp)
			j--;
		a[j]=a[i];
		while(i<j&&a[i]<=temp)
			i++;
		a[i]=a[j];
	}
	a[i]=temp;
	return i;
}

最好情况:O( n l o g 2 n nlog_2n nlog2n),最坏情况:O( n 2 n^2 n2)

二路归并

void Merge(int a[],int low,int mid,int high)
{
	int *tmp;
	tmp=(*int)malloc((high-low+1)*sizeof(int));
	int i=low,j=mid+1,k=0;
	while(i<=mid&&j<=high)
	{
		if(a[i]<a[j])
		{tmp[k]=a[i];i++;k++;}
		else
		{tmp[k]=a[j];j++;k++;}
	}
	while(i<=mid)
	{tmp[k]=a[i];i++;k++;}
	while(j<=high)
	{tmp[k]=a[j];j++;k++;}
	for(i=low,k=0;i<=high;i++,k++)
		a[i]=tmp[k];
	free(tmp);
}

//自底向上
/*
void MergePass(int a[],int length,int n)
{
	int i;
	while(i=0;i+2*lengh+1<n;i=i+2*lengh)
		Merge(a,i,i+length-1,i+2*length-1);
	if(i+length-1<n)
		Merge(a,i,i+length-1,n-1);
}

void MergeSort(int a[],int n)
{
	int length;
	for(length=1;length<n;length=2*length)
		MergePass(a,length,n);
}
*/
//自顶向下
void MergeSort(int a[],int low,int high)
{
	int mid;
	if(low<high)
	{
		mid=(low+high)/2;
		MergeSort(a,low,mid);
		MergeSort(a,mid+1,high);
		Merge(a,low,mid,high);
	}
}

时间复杂度:O( n l o g 2 n nlog_2n nlog2n)

查找最大和次大元素

void Solve(int a[],int low,int high,int &max1,int &max2)
{
	if(low==high)
	{max1=a[low];max2=-INF;}
	else if(low==high-1)
	{max1=max(a[low],a[high]);max2=min(a[low],a[high]);}
	else
	{
		mid=(low+high)/2;
		int lmax1,lmax2,rmax1,rmax2;
		Solve(a,low,mid,lmax1,lmax2);
		Solve(a,mid+1,high,rmax1,rmax2);
		if(lmax1>rmax1)
		{
			max1=lmax1;
			max2=max(lmax2,rmax1);
		}
		else
		{
			max1=rmax1;
			max2=max(lmax1,rmax2);
		}
	}
}

时间复杂度:O( n n n)

折半查找

int BinarySearch(int a[],int low,int high,int k)
{
	if(low<high)
	{
		int mid=(low+high)/2;
		if(a[mid]==k)
			return mid;
		if(a[mid]>k)
			return BinarySearch(a,low,mid-1,k);
		else
			return BinarySearch(a,mid+1,high,k);
	}
	else return -1;
}

时间复杂度:O( l o g 2 n log_2n log2n)

查找第K小元素

int QuickSelect(int a[],int s,int t,int k)
{
	int i=s,j=t;
	int tmp=a[s];
	if(s<t)
	{
		while(i!=j)
		{
			while(j>i&&a[j]>=tmp) j--;
			a[i]=a[j];
			while(i<j&&a[i]<=tmp) i++;
			a[j]=a[i];
		}
		a[i]=tmp;
		if(k-1==i) return a[i];
		else if(k-1<i) return QuickSelect(a,s,i-1,k);
		else return QuickSelect(a,i+1,t,k);
	}
	else if(s==t&&s==k-1)
		return a[k-1];
}

时间复杂度:O( n n n)

寻找两个等长有序序列的中位数

int midnum(int a[],int s1,int t1,int b[],int s2,int t2)
{
	int m1,m2;
	if(s1==t1&&s2=t2)
		return a[s1]<b[s2]?a[s1]:b[s2];
	else
	{
		m1=(s1+t1)/2;
		m2=(s2+t2)/2;
		if(a[m1]==b[m2])
			return a[m1];
		if(a[m1]<b[m1])
		{
			poppart(s1,t1);
			prepart(s2,t2);
			return midnum(a,s1,t1,b,s2,t2);
		}
		else
		{
			prepart(s1,t1);
			poppart(s2,t2);
			return midnum(a,s1,t1,b,s2,t2);
		}
	}
}
void prepart(int &s,int &t)
{
	int m=(s+t)/2;
	t=m;
}
void poppart(int &s,int &t)
{
	int m=(s+t)/2;
	if((s+t)%2==0)
		s=m;
	else
		s=m+1;
}

时间复杂度:O( n n n)

求最大连续子序列和

long maxSubSum(int a[],int left,int right)
{
	int i,j;
	long maxLeftSum,maxRightSum;
	long maxLeftBorderSum,leftBorderSum;
	long maxRightBorderSum,rightBorderSum;
	if(left==right)
	{
		if(a[left]>0)
			return a[left];
		else;
			return 0;
	}
	int mid=(left+right)/2; //求中间位置
   maxLeftSum= (a,left,mid); //求左边
   maxRightSum= (a,mid+1,right); //求右边
   maxLeftBorderSum=0,leftBorderSum=0;
   for (i=mid;i>=left;i--) //求出以左边加上a[mid]元素
   { 
   	leftBorderSum+=a[i]; //构成的序列的最大和
  		if (leftBorderSum>maxLeftBorderSum)
     	maxLeftBorderSum=leftBorderSum;
  }
  maxRightBorderSum=0,rightBorderSum=0;
  for (j=mid+1;j<=right;j++) //求出a[mid]右边元素
  { 
  		rightBorderSum+=a[j]; //构成的序列的最大和
   	if (rightBorderSum>maxRightBorderSum)
     	maxRightBorderSum=rightBorderSum;
  }
  return max3(maxLeftSum,maxRightSum,
	maxLeftBorderSum+maxRightBorderSum);
}

时间复杂度:O( n l o g 2 n nlog_2n nlog2n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值