-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathnearest_neighbor_search.cpp
292 lines (244 loc) · 7.93 KB
/
nearest_neighbor_search.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
#include <iostream>
#include <vector>
#include <cstdio>
#include <conio.h>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <limits.h>
#include <cmath>
using namespace std;
/**
** 源文件: nearest_neighbor_search.cpp
** 功能说明:
** 测试程序,最近点对问题解决方案,蛮力法与分治法。详见以下代码。
** 作者:junkun huang e-mail:[email protected]
** 创建日期:2008-11 /
*/
//---------------------------------------------------------------------------
//点结构
typedef struct Pair
{
int x;
int y;
} Pair;
//最近点对结构
typedef struct Closest_Pair
{
Pair pair_a, pair_b;
double distance;
} Closest_Pair;
//点对结构
typedef struct Points
{
Pair* p_pair;
int pair_nums;//点对数目
} Points;
//---------------------------------------------------------------------------
Points points;
Closest_Pair closest_pair;
//int pair_nums;
//---------------------------------------------------------------------------
double Account_Distance_2(const Pair& A, const Pair& B )
{
return ( (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y) );
}
//---------------------------------------------------------------------------
void Print_Points(ostream& outs, const Points& points, const Closest_Pair& closest_pair )
{
outs << "\n\n 随机产生点对如下:\n";
for(int i=0; i<points.pair_nums; ++i)
{
outs << " (" << points.p_pair[i].x << ", " << points.p_pair[i].y << " ) ";
if((i+1)%5==0)
{
outs << endl;
}
}
outs << "\n\n 由以上点对可得最近点对为: ( "
<< closest_pair.pair_a.x << ", " << closest_pair.pair_a.y << " ), ( "
<< closest_pair.pair_b.x << ", " << closest_pair.pair_b.y << " ) ";
outs << "\n 该点对距离为:" << closest_pair.distance << endl;
}
//---------------------------------------------------------------------------
bool Brute_Force(const Points& points, Closest_Pair& closest_pair, int from, int to)
{
for(int i=from; i<=to; ++i)
{
for(int j=i+1; j<=to; ++j)
{
double next = Account_Distance_2(points.p_pair[i], points.p_pair[j]);//sqrt( )
if(closest_pair.distance > next )
{
closest_pair.pair_a = points.p_pair[i];
closest_pair.pair_b = points.p_pair[j];
closest_pair.distance = next;
}
}
}
return true;
}
//---------------------------------------------------------------------------
// 对顺序表L作归并排序。
void Merge(char sign, Pair SR[], Pair TR[], long i, long m, long n)
{
// 将有序的SR[i..m]和SR[m+1..n]归并为有序的TR[i..n]
int j=m+1,k=i;
for(; i<=m&&j<=n; ++k) // 将SR中记录由小到大地并入TR
{
if(sign=='x')
{
if ( SR[i].x < SR[j].x )
TR[k]=SR[i++];
else
TR[k]=SR[j++];
}
else
{
if ( SR[i].y < SR[j].y )
TR[k]=SR[i++];
else
TR[k]=SR[j++];
}
}
if(i<=m)
{
for(int l=0; l<=m-i; l++)
{
TR[k+l]=SR[i+l]; // 将剩余的SR[i..m]复制到TR
}
}
else //if(j<=n)
{
for(int l=0; l<=n-j; l++)
{
TR[k+l]=SR[j+l]; // 将剩余的SR[j..n]复制到TR
}
}
}
//---------------------------------------------------------------------------
void MSort(char sign, Pair SR[], Pair TR1[], long s, long t)
{
// 将SR[s..t]归并排序为TR1[s..t].
if(s==t)
{
TR1[s] = SR[s];
}
else
{
// int length = t-s+1;//
Pair* TR2 = new Pair[points.pair_nums];
long m = (s+t)/2; // 将SR[s..t]平分为SR[s..m]和SR[m+1..t]
MSort(sign, SR, TR2, s, m); // 递归地将SR[s..m]归并为有序的TR2[s..m]
MSort(sign, SR, TR2, m+1, t); // 递归地将SR[m+1..t]归并为有序的TR2[m+1..t]
Merge(sign, TR2, TR1, s, m, t); // 将TR2[s..m]和TR2[m+1..t]归并到TR1[s..t]
delete[] TR2;
}
}
//---------------------------------------------------------------------------
void Comp_CP(const Points& points, Closest_Pair& closest_pair, int mid, int mid_value)
{
int i, j;
int distance = sqrt( closest_pair.distance );
i = mid;
while( i >= 0 && points.p_pair[i].x >= (mid_value-distance) )
{
j = i + 1;
for(; points.p_pair[j].x <= (mid_value+distance) && j < points.pair_nums; ++j)
{
if( points.p_pair[j].y > (points.p_pair[i].y+distance) ||
points.p_pair[j].y < (points.p_pair[i].y-distance) )
//判断在y轴是否出界
continue;
double next = Account_Distance_2( points.p_pair[i], points.p_pair[j]);//sqrt( )
if(closest_pair.distance > next )
{
closest_pair.pair_a = points.p_pair[i];
closest_pair.pair_b = points.p_pair[j];
closest_pair.distance = next;
//cout << "Comp_CP: " << closest_pair.distance << endl;
}
}
i--;
}
}
//---------------------------------------------------------------------------
void Divide_and_Conquer(const Points& points, Closest_Pair& closest_pair, int from, int to)
{
if( (to-from) <4 )
{
/*
if( (to-from)==1 )
{
double next = Account_Distance_2( points.p_pair[from], points.p_pair[to]);//sqrt( )
if(closest_pair.distance > next )
{
closest_pair.pair_a = points.p_pair[from];
closest_pair.pair_b = points.p_pair[to];
closest_pair.distance = next;
}
cout << "2 " << closest_pair.distance <<endl;
}
else */
{
Brute_Force(points, closest_pair, from, to );
//cout << "<4 " << closest_pair.distance << endl;
//system("pause");
}
}
else
{
int mid = (from+to)/2;
int mid_value = points.p_pair[mid].x;
Divide_and_Conquer(points, closest_pair, from, mid);
Divide_and_Conquer(points, closest_pair, mid+1, to);
Comp_CP(points, closest_pair, mid, mid_value);
}
return ;
}
//---------------------------------------------------------------------------
int main()
{
time_t t;
srand((unsigned) time(&t));
char c;
do
{
system("cls");
cout << "\n\n 请输入你要随机产生点对的对数: ";
cin >> points.pair_nums;
if (points.pair_nums <= 0 || points.pair_nums > 1000)
{
cout << "输入有误,退出程序!\n";
break;
}
points.p_pair = new Pair[points.pair_nums];
for(int i=0; i<points.pair_nums; ++i)
{
points.p_pair[i].x= rand()%101;
points.p_pair[i].y= rand()%101;
}
/// 分治法求解,先排序确保蛮力法与分治法求解的数据一致。
MSort('x', points.p_pair, points.p_pair, 0, points.pair_nums-1 );
//蛮力法求解
cout << "\n\n--- 蛮力法求解 ---\n";
closest_pair.distance = ULONG_MAX;//MAX_SIZE
Brute_Force(points, closest_pair, 0, points.pair_nums );
closest_pair.distance = sqrt( closest_pair.distance );
Print_Points( cout, points, closest_pair );
// /// 分治法求解,先排序
// MSort('x', points.p_pair, points.p_pair, 0, points.pair_nums-1 );
//分治法求解
cout << "\n\n--- 分治法求解 ---\n";
closest_pair.distance = ULONG_MAX;//MAX_SIZE
Divide_and_Conquer(points, closest_pair, 0, points.pair_nums );
closest_pair.distance = sqrt( closest_pair.distance );
Print_Points( cout, points, closest_pair );
delete[] points.p_pair;
cout << "\n\n !!!按任意键继续,Esc退出程序!!!" << endl;
}
while( (c=getch())!=27 );
return 0;
}
//---------------------------------------------------------------------------