您的位置:首页 > 其它

线性时间选择

2017-04-30 22:30 288 查看
给定线性序集中n个元素和一个整数k,1≤k≤n,要求找出这n个元素中第k小的元素。

Step1. 从a[]中选取划分基准元素,将a[0:n-1]划分为2部分,得到A[0:q]:

1、a[0:q],q+1个元素,包括a[q]

2、a[q+1, n-1],n-q-1个元素

Step2. 

1、L=q+1>=k, q>=k-1, 则左半段至少有k个不大于x=a[q]的小元素,第k小的元素在左半段,递归搜索a[0:q]

2、L=q+1<k, q<k-1, 左半段比x=a[q]小的元素少于k个,x=a[q]不可能是第k小元素,第k小的元素在右半段,并且为右半段的第k-q小,递归搜索a[q+1:n-1]

为降低最坏复杂性,要求尽可能保证划分后的2个子集大小接近,相差过大将导致不平衡。

解决思路:以n(例如5)的长度将数组分割成若干小段,通过排序取到个小段的中位数,再取各中位数的中位x,以此为基准划分至少与位于左半部分的3n/10-1个元素小于x,保证划分后的子集长度相近

原题:采用线性时间选择算法,根据基站k-dist距离,挑选出

k-dist值最小的基站

k-dist第5小的基站

k-dist值第50小的基站

k-dist值最大的基站

#include<iostream>
#include<string>
#include<fstream>
#include<cstdlib>
#define max 2000
using namespace std;

typedef struct Basestation
{
int ENODEBID;
float LONGITUDE;//经度
float LATITUDE;//纬度
float K_DIST ;
}Basestation;

Basestation a[max];

int Max(int a, int b);
int Partition(Basestation a[], int p, int r, Basestation z);
int RandomizedPartition(Basestation a[], int p, int r);
Basestation Select(Basestation a[], int p, int r, int ak);

int main()
{
int i = 1;
int num = 0;
Basestation temp;
ifstream file;
file.open("Data_Of_Basestation.txt", ios::in);
if(file.bad())
{
cout<<"打开文件时发生错误"<<endl;
return 0;
}
while(!file.eof())
{
file>>a[i].ENODEBID>>a[i].LONGITUDE>>a[i].LATITUDE>>a[i].K_DIST;
i++;
num++;
//cout<<a[i].ENODEBID<<" "<<a[i].LONGITUDE<<" "<<a[i].LATITUDE<<" "<<a[i].K_DIST<<endl;
file.get();
if(file.peek()==EOF)
break;
}
cout<<"==============================================================================="<<endl;
cout<<"\t\t\t基站编号 "<<"\t"<<" 基站经度 "<<"\t"<<" 基站纬度 "<<"\t"<<" K_DIST"<<endl;
cout<<"K_DIST最小的基站是:\t";
temp = Select(a, 1, num, 1);
cout<<temp.ENODEBID<<"\t\t"<<temp.LONGITUDE<<"\t\t"<<temp.LATITUDE<<"\t\t"<<temp.K_DIST<<endl;
cout<<"K_DIST第五小的基站是:\t";
temp = Select(a, 1, num, 5);
cout<<temp.ENODEBID<<"\t\t"<<temp.LONGITUDE<<"\t\t"<<temp.LATITUDE<<"\t\t"<<temp.K_DIST<<endl;
cout<<"K_DIST第五十小的基站是:";
temp = Select(a, 1, num, 50);
cout<<temp.ENODEBID<<"\t\t"<<temp.LONGITUDE<<"\t\t"<<temp.LATITUDE<<"\t\t"<<temp.K_DIST<<endl;
cout<<"K_DIST最大的基站是:\t";
temp = Select(a, 1, num, num);
cout<<temp.ENODEBID<<"\t\t"<<temp.LONGITUDE<<"\t\t"<<temp.LATITUDE<<"\t\t"<<temp.K_DIST<<endl;
cout<<"==============================================================================="<<endl;
file.close();
return 0;
}

int Max(int a, int b)
{
return (a>b)?a:b;
}

int Partition(Basestation a[], int p, int r, Basestation z)//z表示以数组中第z个为基准
{
int i = p;
int j = r+1;
int k;
Basestation beitai;
for(k=p; k<=r; k++)
{
if(a[k].K_DIST==z.K_DIST)
break;
}
beitai = a[k];
a[k] = a[p];
a[p] = beitai;
Basestation x = a[p];
while(i<j)
{
while (a[++i].K_DIST <x.K_DIST && i<r); //扩展左端a[p:i],左→右搜索大元素a[i]>=x
while (a[--j].K_DIST >x.K_DIST); //扩展右端a[j:r],左←右搜索小元素a[i]<=x
if(i >= j)
{
break;
}
beitai = a[i];
a[i] = a[j];
a[j] = beitai;
}
a[p] = a[j];
a[j] = x;
return j;
}

Basestation Select(Basestation a[], int p, int r, int k)
{
Basestation beitai;
Basestation final;
if(r-p<20)//如果数组足够小,简单排序,寻找第k小元素
{
for(int i = 0; i<r-p+1; i++)
{
for(int j = p+1; j<=r-i; j++)
{
if(a[j].K_DIST<a[j-1].K_DIST)
{
beitai = a[j];
a[j] = a[j-1];
a[j-1] = beitai;
}
}
}
return a[p+k-1];
}
int s;
int t;
for ( int i = 0; i<=(r-p-4)/5; i++ )
{
s= p + 5*i;
t = s + 4;
for(int k=0; k<3; k++)
{
for(int j=s+1; j<=t-k; j++)
if(a[k].K_DIST<a[k-1].K_DIST)
{
beitai = a[j];
a[j] = a[j-1];
a[j-1] = beitai;
}
}
beitai = a[p+i];
a[p+i] = a[s+2];
a[s+2] = beitai;
}
final = Select(a, p, p+(r-p-4)/5, (r-p+6)/10);
int i = Partition(a, p, r, final);
int j = i-p+1;
if(k==j)
return a[i];
else if(k<j)
return Select(a, p, i, k);
else
return Select(a, i+1, r, k-j);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  分治