减治法以及减治法的两个例子(两个序列的中位数;二叉查找树)

💬推荐一款模拟面试、刷题神器,从基础到大厂面试题👉点击跳转刷题网站进行注册学习


提示:以下是本篇文章正文内容,下面案例可供参考

一、减治法是什么以及减治法和分治法的区别?

分治法是把一个大问题划分为若干个子问题,分别求解各个子问题,然后再把子问题的解进行合并得到原问题的解。

减治法同样是把一个大问题划分为若干个子问题,但是这些子问题不需要分别求解,只需求解其中的一个子问题,因而也无需对子问题的解进行合并。

所以,严格的说,减治法应该是一种退化了的分治法,时间复杂性一般是O(log2 n)。

减治法在将原问题分解为若干个子问题后,利用了规模为n的原问题的解与较小规模(通常是n/2)的子问题的解之间的关系,这种关系通常表现为:

(1)原问题的解只存在于其中一个较小规模的子问题中;

(2)原问题的解与其中一个较小规模的解之间存在某种对应关系。

二、例子

1.两个序列的中位数

【问题】 一个长度为n(n>=1)的升序序列S,处在第n/2个位置的数称为序列SD中位数。
S1={6,9,10,21,44,45};
S2={5,7,9,11,36,46};
则S1和S2的中位数为10.
【算法思想】
(1)分别求出两个序列的中位数,记为a和b。

(2) 比较a和b,有下列三种情况:

①a=b,则a即为两个序列的中位数;

②a<b,则中位数只能出现在a和6之间,在序列A中舍弃a之前的元素得到序列A1,在序列B中舍弃b之后的元素得到序列B1;

③a>b,则中位数只能出现在b和a之间,在序列A中舍弃a之后的元素得到序列A1在序列B中舍弃b之前的元素得到序列B1。

(3)在A1和B1中分别求出中位数,重复上述过程,直到两个序列中只有一个元素,则较小者即为所求

注意: 两个序列的长度必须一样且升降序得一致;
如果一个序列的长度是偶数,那么它舍去后,两序列的长度不想等,必须再舍去自身。如(第一次:S1的中位数是10,S2的中位数是9;10>9,我们要舍去S1 10之后的,以及S2 9之前的数字,S1的长度为3,S2的长度为4,这时我们要舍去9,才能使两序列长度一致)
因为这里是以升序序列做例子,如果是降序,我们要把相应的操作取反。
代码如下(示例):

int median(int a[],int b[],int n) {
	int mid1,mid2;
	int start1=0,end1=n-1,start2=0,end2=n-1; //初始化两序列的上下界
	while(start1<end1&&start2<end2) {     //循环直至区间只有一个元素
		mid1=(start1+end1)/2;      //序列a的中位数下标
		mid2=(start2+end2)/2;      //序列b的中位数下标
		if (a[mid1]==b[mid2]) {    //相等则中位数就是这个
			return a[mid1];
		}
		if (a[mid1]<b[mid2]) {    
			if((start1+end1)%2==0)   //索引从0开始,所以余数为0是,序列长度为奇数无序去除自身
				start1=mid1;
			else                    //反之则为偶数,要去除自身
				start1=mid1+1;
			end2=mid2;              //重新定义上下界
		}
		if (a[mid1]>b[mid2]) {
			if((start2+end2)%2==0)
				start2=mid2;
			else
				start2=mid2+1;
			end1=mid1;
		}
	}
	if (a[start1]<b[start2])             //返回较小值
		return a[start1];
	else 
		return b[start2];

}

2.二叉查找树

二叉查找树(binary search tree)是具有 下列性质的二叉树: (1)若它的左子树不空,则左子树上所有结点的值均小于根结点的值: (2)若它的右子树不空,则右子树上所有结点的值均大于根结点的值; (3)它的左右子树也都是二叉排序树。

在二叉查找树上进行查找,与待查值比较后,根据比较结果只需要查找两个子树之一,因此,二叉查找树 也是减治技术的成功应用。

[问题] 在一个无序序列中执行查 找操作,可以将无序序列建立一棵二叉查找树,然后在二叉查找树中查找值为k的记录,若查找成功,返回记录k的存储地址,若查找失败,返回空指针,

[想法] 由二叉查找树的定义 ,在二叉查找树root 中查找给定值k的过程如下。(1)若root是空树,则查找失败;

(2)若k=根结点的值,则查找成功;

(3)若k<根结点的值,则在root的左子树上查找;

(4)若k>根结点的值,则在root的右子树上查找。

代码如下(示例):

typedef struct BiNode{
	int data;                 //结点值
	BiNode *lchild,*rchild;   //左右子树指针
}BiNode;
BiNode* InsertBST(BiNode *T,int data){    //创建二叉查找树
	if (T==NULL){
		T=new BiNode;
		T->data=data;
		T->lchild=T->rchild=NULL;
		return T;
	}
	if(data<=T->data){
		T->lchild=InsertBST(T->lchild,data);
	}else{
		T->rchild=InsertBST(T->rchild,data);
	}
	return T;
}
BiNode* CreateBST(int r[],int n){ //创建二叉查找树
	BiNode* T=NULL;
	for (int i=0;i<n;i++){
		T=InsertBST(T,r[i]);
	}
	return T;
}
BiNode* SearchBST(BiNode *T,int k){    //查找
	if (T==NULL){
		return NULL;
	}
	if(T->data==k)
	return T;
	if(k<T->data){
		return SearchBST(T->lchild,k);
	}
	if(k>T->data){
		return SearchBST(T->rchild,k);
	}
} 

总结

减治法例子还有很多,后续依次补充。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值