⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 find.cpp

📁 在o(n)时间内
💻 CPP
字号:
//本题首先要感谢黄群同学为我提供了帮助,并且在红皮书《数据结构与算法-学习指导与习题解析》P210找到了答案
//算法描述:先给出一个在0(n)时间内找到序列中第k小的数的算法Search,然后在调用这个算法找中位数,其时间代价也为0(n)的。
//把数组按照每5个一组分为多组,分别排序,然后递归调用算法Search找到这些中位数。利用partition算法,以该中位数为轴值,将数组
//分成两部分,然后在其中一部分元素中递归调用算法Search,找到第k小的元素。
int Search(int * a,int i,int j,int k)//寻找数组a中从i到j中第k小的元素
{
	int p1,m,p2,value;
	if(j - i < 5)
	{
		a = sort(a,i,j - i + 1);//直接插入排序
		value = a[i + k];//找到
	}
	else
	{
		for(m = 0;m < (j - i + 4) / 5;m ++)
		{
			a = sort(a,i + m * 5,5);//分成(j - i + 4) / 5个部分
			a = swap(a,i + m * 5,i + m);//把各部分的中间值换到数组的排序段的前面?i + m * 5不是中间值
		}
		p1 = Search(a,i,i + (j - i + 4) / 5 - 1,(j - i + 4) / 10);//先找到那一部分中间值的中间值
		p2 = partition(a,i,j,p1);//找到轴值p1的位置
		if(k == p2)//找到
			value = a[i + k];
		else if(k < p2)//把中间值位置与k比较
			value = Search(a,i,p2,k);
		else
			value = Search(a,p2,j,k - p2);
	}
	return value;//返回第k小的值
}
void mainsearch(int * a,int n)
{
	int value;
	if(n % 2 == 1)//奇数只有一个中位数
		cout << Search(a,0,n / 2,n - 1) << endl;
	else
	{
		cout << Search(a,0,n / 2,n - 1)<< " ";//偶数有两个中位数
		cout << Search(a,0,n / 2 + 1,n - 1)<< endl;
	}
	return;
}
算法代价评估:设代价为T(n)
分组排序中,每组代价为o(1),共n/5组,所以总共为o(n);
对数组最前面的中值进行排序,代价为T(n/5)。partition算法代价为o(n),再递归调用该算法,代价上限为0(7n/10)。这是
因为n/5个中位数中,有n/10个大于等于p1,而每个5个一组的小数组中又有2个大于等于这个小数组的中位数,则整个数组中至少有3n/10
个大于等于p1,同理至少有3n/10个数小于等于p1,最后用p1划分数组,留下进一步递归的数至多有7n/10个,所以得出其时间代价为:
T(n) <= T(n/5) + o(n) + T(7n/10)
用递归树法解此递归方程,得到T(n) = o(n);


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -