最近对问题----分治法

照着书上和老师讲解,理解了使用分治法解决最大对问题,并用代码实现了一下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include <iostream>
#include<cmath>
#include<algorithm>
using namespace std;
int n;
typedef struct point
{
 double x, y;
}point;
/*
快速排序
*/
void quicksort(point po[], int left, int right)
{   
 point temp, t;
 //如果只有三个或两个点 那么不用排序 直接蛮力法求各点距离
 if (right <= 3) return;
 if (left > right) return;
 int i = left;
 int j = right;
 temp = po[left];
 while (i != j)
 {
  while (po[j].x >= temp.x&&i < j)
   j--;
  while (po[i].x <= temp.x&&i < j)
   i++;
  if (i < j)
  {
   t = po[i];
   po[i] = po[j];
   po[j] = t;
  }
 }
 po[left] = po[i];
 po[i] = temp;
 quicksort(po, left, i - 1);
 quicksort(po, i + 1, right);
}
/*
  排序参数
*/
bool Comp(const point &p1, const point &p2)
{
 return p1.y < p2.y;
}
/*
  计算距离函数
*/
double Distance(point a, point b)
{
 return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
}
/*
  分治法求解
*/
double Closest(point po[], int low, int high)
{
 //只有两个点
 if (high - low == 1)
  return Distance(po[low], po[high]);
 //只有三个点
 if (high - low == 2)
 {
  double d1 = Distance(po[low], po[low + 1]);
  double d2 = Distance(po[low + 1], po[high]);
  double d3 = Distance(po[low], po[high]);
  if ((d1 < d2) && (d1 < d3))
   return d1;
  else if (d2 < d3) return d2;
  else return d3;
 }
 //递归求解子问题
 double d;
 double d1, d2;
 int mid = (low + high) / 2;
 d1 = Closest(po, low, mid);
 d2 = Closest(po, mid + 1, high);
 if (d1 <= d2) d = d1;
 else d = d2;
 point P[100];
 //x坐标在-d~+d之间的点并入一个集合
 int index = 1;
 for (int i = mid; (i >= low) && (po[mid].x - po[i].x) < d; i--)
  P[index++] = po[i];
 for (int i = mid + 1; (i <= high) && (po[i].x - po[mid].x) < d; i++)
  P[index++] = po[i];
 //y坐标升序排序
 sort(&P[1], &P[index - 1], Comp);
//在x集合内循环 找x y坐标差值都小于d的点 计算距离d
 for (int i = 1; i < index; i++)
  for (int j = i + 1; j < index; j++)
   if ((P[j].y - P[i].y) >= d) break;
   else
   {
    double d3 = Distance(P[i], P[j]);
    if (d3 < d) d = d3;
   }
 return d;
}
/*
主函数
*/
int main()
{
 cout << "输入点的对数N(N>=2)" << '\n';
 cin >> n;
 point po[100];
 cout << "依次输入各点坐标" << '\n';
 for (int i = 1; i <= n; i++)
  cin >> po[i].x >> po[i].y;
 quicksort(po, 1, n);
 cout << "各点之间最短距离为" << " " << Closest(po, 1, n);
 return 0;
}

时间复杂度分析:
【算法分析】当求a[0…n-1]中n个点的最近点时,设执行时间为T(n),求左右部分中最近点对的时间为T(n/2),求中间部分的时间为O(n),则:
  T(n)=O(1) 当n<4
  T(n)=2T(n/2)+O(n) 其他情况

从而推出算法的时间复杂度为O(nlog2n)。

记录一下遇到的问题
1.对各点x坐标进行快速排序的时候 如果少于4个点 直接ruturn 如果left>right 直接return
后者通过调试之后才看清错误
2.思考并理解鸽舍定理,如何转化成代码实现
3.测试了几个数据,感觉应该是没有问题

发布了19 篇原创文章 · 获赞 2 · 访问量 745

猜你喜欢

转载自blog.csdn.net/qq_45639157/article/details/104848628
今日推荐