分治法求第K大元素2

#include<iostream>
#include<algorithm>
using namespace std;

/***************************************
* 选择第k小元素算法
*
* 输入:元素数组A[],元素个数n,求的k
* 输出:第k小元素
***************************************/
template<class Type>
Type select(Type A[], int n, int k){
	int i, j, s, t;
	Type m, *p, *q, *r;
	if (n<38){                     //     如果元素个数小于38:则直接排序
		sort(A, A + n);
		return A[k - 1];
	}
	p = new Type[3 * n / 4];
	q = new Type[3 * n / 4];
	r = new Type[3 * n / 4];
	for (i = 0; i<n / 5; i++){  //        五个一组,把每组的中值元素存放进数组p
		mid(A, i, p);
	}
	m = select(p, i, i / 2 + i % 2);      //    递归调用,取得中值元素存入m
	i = j = s = 0;
	for (t = 0; t<n; i++) //  按<m、=m、>m把数组分成三组
	{   
		if (A[t]<m){
			p[i++] = A[t];
		}
		else{
			if (A[t] == m){
				q[j++] = A[t];
			}
			else{
				r[s++] = A[t];
			}

		}
	}
	if (i>k){                                //      若k<i,则该元素就在数组p中,进入p继续查找
		return select(p, i, k);
	}
	else{
		if (i + j >= k){               //   若i<k<i+j,则该元素在q数组中,即值为m
			return m;
		}
		else{        //        若k>i+j,则该元素在r数组中,进入r继续寻找
			return select(r, s, k - i - j);
		}
	}
}

/***************************************
* 计算中值元素
*
* 输入:元素数组A[],组号i
* 输出:存放中值元素的数组p[]
***************************************/
template<class Type>
void mid(Type A[], int i, Type p[]){
	int k = 5 * i;
	if (A[k]>A[k + 2]){
		swap(A[k], A[k + 2]);
	}
	if (A[k + 1]>A[k + 3]){
		swap(A[k + 1], A[k + 3]);
	}
	if (A[k]>A[k + 1]){
		swap(A[k], A[k + 1]);
	}
	if (A[k + 2]>A[k + 3]){
		swap(A[k + 2], A[k + 3]);
	}
	if (A[k + 1]>A[k + 2]){
		swap(A[k + 1], A[k + 2]);
	}
	if (A[k + 4]>A[k + 2]){
		p[i] = A[k + 2];
	}
	else{
		if (A[k + 4]>A[k + 1]){
			p[i] = A[k + 4];
		}
		else{
			p[i] = A[k + 1];
		}
	}
}

int main()
{
	int n, m;
	int x, y;
	int k1, k2;
	cout << "请输入数组元素个数:";
	cin >> n;
	cout << "请输入要求的k1,k2:";
	cin >> k1;
	cin >> k2;

	int *A = new int[n];
	int i;

	cout << "请输入数组元素:" << endl;
	for (i = 0; i<n; i++){
		cin >> A[i];
	}
	x = select(A, n, n - k1 + 1);
	y = select(A, n, n - k2 + 1);
	//cout << "第" << m << "大元素是:";
	//cout << select(A, n, n - m + 1) << endl;    // 输出第(n-m+1)小元素<=>第m大元素
	//获取数组下标方式
	for (int i = 0; i < n;i++)
	{
		if (A[i] == x || A[i] == y)
		{
			k1 = i;
			break;
		}
	}
	for (int i = n; i > 0; i--)
	{
		if (A[i] == x || A[i] == y)
		{
			k2 = i;
			break;
		}
	}
	for (; k1 <= k2;k1++)
	{
		cout << A[k1] <<" ";
	}
	system("pause");
	return 0;
}

 

#include<iostream> 
using namespace std;
#define max  100 
typedef struct Data
{
	int data;
	bool flag;
}Data, Mat[max];
Mat a;
void Found_k1_k2(Mat &a, int n, int k1, int k2)//用减治法查找无序列表中第k1到第k2小的整数 
{
	int x = 0;
	int y = n - 1;
	while (x<k1 - 1 || y>k2 - 1)
	{
		int temp;
		int f1, f2;//存储最小和最大数的下标 
		f1 = x;
		f2 = y;
		for (int i = x; i <= y; i++)
		{
			if (a[f1].data > a[i].data)
				f1 = i;    if (a[f2].data < a[i].data)
				f2 = i;
		}
		if (x < k1 - 1)
		{
			temp = a[x].data;
			a[x].data = a[f1].data;
			a[f1].data = temp;
			a[x].flag = 0;
			x++;
		}
		if (y > k2 - 1)
		{
			temp = a[y].data;
			a[y].data = a[f2].data;
			a[f2].data = temp;
			a[y].flag = 0;
			y--;
		}
	}
}
void Show(Mat &a, int n, int k1, int k2)
{
	cout << "第" << k1 << "小到" << k2 << "小之间的所有整数有:";
	for (int i = 0; i < n; i++)
	{
		if (a[i].flag)
			cout << a[i].data << "  ";
	}
	cout << endl;
}
void main()
{
	int choice;
	cout << "                       1: 执行程序 2: 退出程序" << endl;
	do
	{
		cout << "请选择你的操作:";
		cin >> choice;
		switch (choice)
		{
		case 1:
		{      int n;
		int k1, k2;
		cout << "请输入无序列表n的大小:";
		cin >> n;
		cout << "请输入无序列表中的所有整数:";
		for (int i = 0; i < n; i++)
		{
			a[i].flag = 1;
			cin >> a[i].data;
		}
		cout << "请输入k1k2的值:";
		cin >> k1 >> k2;
		if (k1 > k2)
		{
			int temp = k1;
			k1 = k2;
			k2 = temp;
		}
		if (k1<0 || k2>n || n < 0)
		{
			cout << "输入不和法!!请重新输入!!" << endl;
			break;
		}
		Found_k1_k2(a, n, k1, k2);
		Show(a, n, k1, k2);
		break;
		}
		case 2:
		{
				  cout << "退出程序";
				  break;
		}
		default:cout << "选择不合理请重选" << endl;
		}
	}
	while (choice != 2);
}

 

#include<iostream> 
using namespace std;
#define  swap(x, y) {int a = x; x = y; y = a;}
#define max  100 
typedef struct Data
{
	int data;
	bool flag;
}Data, Min[max];
Min a;
void Binary_search(Min &a, int n, int k1, int k2)
{
	//用减治法查找无序列表中第k1到第k2小的整数 
	int x = 0;
	int y = n - 1;
	while (x < k1 - 1 || y > k2 - 1)
	{
		int temp;
		//存储最小和最大数的下标 
		int f1, f2;
		f1 = x;
		f2 = y;
		
		for (int i = x; i <= y; i++)
		{
			if (a[f1].data > a[i].data)
				f1 = i;    //缩小空间
			if (a[f2].data < a[i].data)
				f2 = i;
		}
		//下面两段if相当于把不在k1,k2范围内的数组元素统统删掉
		if (x < k1 - 1)
		{
			temp = a[x].data;
			a[x].data = a[f1].data;
			a[f1].data = temp;
			a[x].flag = 0;
			x++;
		}
		if (y > k2 - 1)
		{
			temp = a[y].data;
			a[y].data = a[f2].data;
			a[f2].data = temp;
			a[y].flag = 0;
			y--;
		}
	}

	cout << "第" << k1 << "小到" << k2 << "小之间的所有整数有:";
	for (int i = 0; i < n; i++)
	{
		if (a[i].flag)
			cout << a[i].data << "  ";
	}
	cout << endl;
}

void main()
{
	    int n;
		int k1, k2;
		cout << "请输入无序列表大小::";
		cin >> n;
		cout << "请输入无序列表中元素:";
		for (int i = 0; i < n; i++)
		{
			a[i].flag = 1;
			cin >> a[i].data;
		}
		cout << "请输入k1k2的值:";
		cin >> k1 >> k2;
		if (k1 > k2)
			swap(k1, k2);
		if (k1<0 || k2>n || n < 0)
		{
			cout << "输入不合法!" << endl;
		}
		Binary_search(a, n, k1, k2);
		system("pause");
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值