快速排序之数组子集划分问题

1.问题描述:已知由n(n≥2)个正整数构成的集合A={ak}(0≤k<n),将其划分为两个不相交的子集A1和A2,元素个数分别是n1和n2,A1和A2中元素之和分别为S1和S2。设计一个尽可能高效的划分算法,满足|n1-n2|最小且|S1-S2|最大。

2.设计思路:根据题目的要求,如果要满足n1-n2最小,那么两个子集中的元素个数是平均的,也就是n1=n/2;在此基础下,去满足S1-S2最大,那么就需要把n中的元素分为两部分:较大的一部分和较小的一部分;分别把这两个部分放入n1、n2中;把n分成两部分就需要中位数,这里可以使用快速排序完成每一次的中位数求解;如果基准在靠近左边,说明中位数应该在右边,那么在右边递归函数;如果基准在右边,说明中位数应该在左边,那么在左边递归函数;直到基准的位置为n/2时结束,此时找到整个数组的中位数;最后以n/2为边界输出两个子集即可;

3.代码:

/*数组子集划分问题*/
#include <stdio.h>
#define N 10
int a[N]={9,8,7,6,5,4,3,2,1,0};
int FindMidPosision(int a[],int low,int high)	//利用快速排序思想查找中间位置 
{
	int temp=a[low];		//基准
	 while(1)
	 {
	 	while(low<high&&a[high]>=temp)//从右边开始与基准进行比较,小于基准时把数转移到基准位置 
	 	{
	 		high--;
		 }
		if(low>=high)		//如果从右到左已经比较完成,就退出循环 
		{
			break;
		}
		a[low++]=a[high];		//a[high]<temp时,把a[high]转移到a[low]位置
		while(high>low&&a[low]<=temp)//从左边开始与基准进行比较,大于基准时把数转移到基准位置
		{
		 	low++;
		} 
		if(low>=high)		//如果从右到左已经比较完成,就退出循环
		{
			break;
		}
		a[high--]=a[low];   
	  } 
	a[low]=temp;		//把temp的值放到大小子集的中间位置,刚刚好把子集分为一边大,一边小 
	return low;
 } 
void Divide(int a[],int low,int high,int n)	//递归调用快速排序,找到整个数组的中间位置 
{
	int mid;
	while(low<high)
	{
		mid=FindMidPosision(a,low,high);
		if(mid==n/2)
		{
			break; 
		}
		else if(mid<n/2)	//基准小于n/2时,在右边继续递归 
		{
			low=mid+1; 
		}
		else{
			high=mid-1;
		}
	}
}
int main()
{
	Divide(a,0,N-1,N);		//调用函数把数组从中间位置分为一边大和一边小
	printf("n1=%d	:",N/2); 
	for(int i=0;i<N/2;i++)
	{
		printf("%d ",a[i]); 
	}
	printf("\nn1=%d	:",N-N/2);
	for(int i=N/2+1;i<N;i++)
	{
		printf("%d ",a[i]); 
	}
	return 0;
}

4.运行结果:

5.总结:

数组子集划分问题,使用快速排序的思路把数组分为两个部分,并且这两个部分是一边大、一边小,这样就可以满足题目的要求。

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Delphi 中的数组子集可以通过数组的索引范围来实现。你可以使用以下代码来创建一个数组子集: ```delphi type TMyArray = array of Integer; procedure CreateSubset(const SourceArray: TMyArray; StartIndex, EndIndex: Integer; var Subset: TMyArray); var i, SubsetLength: Integer; begin SubsetLength := EndIndex - StartIndex + 1; SetLength(Subset, SubsetLength); for i := StartIndex to EndIndex do Subset[i - StartIndex] := SourceArray[i]; end; var MyArray, MySubset: TMyArray; begin // 创建原始数组 SetLength(MyArray, 5); MyArray[0] := 10; MyArray[1] := 20; MyArray[2] := 30; MyArray[3] := 40; MyArray[4] := 50; // 创建子集,从索引1到索引3的元素 CreateSubset(MyArray, 1, 3, MySubset); // 输出子集元素 for i := 0 to High(MySubset) do WriteLn(MySubset[i]); end. ``` 在上面的示例中,我们首先定义了一个 `TMyArray` 类型作为数组的别名。然后,我们创建了一个名为 `CreateSubset` 的过程,它接受一个源数组、起始索引和结束索引,并通过引用参数返回子集数组。在这个过程中,我们使用 `SetLength` 函数为子集数组分配内存,并使用一个循环将源数组中指定索引范围内的元素复制到子集数组中。最后,我们使用 `WriteLn` 函数输出子集数组的元素。 在主程序中,我们创建了一个原始数组 `MyArray`,并初始化了一些元素。然后,我们调用 `CreateSubset` 过程来创建一个从索引1到索引3的子集数组 `MySubset`。最后,我们使用一个循环在控制台上输出子集数组的元素。 希望这个示例能够帮助你理解如何在 Delphi 中创建数组子集。如果你有任何进一步的问题,请随时提问!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值