算法设计与分析——分治算法

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
/*变量定义*/
typedef struct {
 double x, y;
}point;
/*函数声明*/
void IntRand(int*& A, int min, int max, int num);//产生随机数
int Max(int A[], int l, int r);//分治法求数组最大元素
void Full(int** A, int num, int begin, int size);//数字旋转方阵
void MergeSort(int* A, int l, int r);//归并排序
void Merge(const int* A, int* B, int l, int m, int r);
void QuickSort(int* A, int l, int r);//快速排序
int Partition(int* A, int l, int r);
int MaxSum(int* A, int l, int r);//求最大子段和
double Closest(point* p, int l, int r);//求最近点对
int ClosetCmp(point p, point q);
double Distance(point p, point q);
/*函数定义*/
//产生随机数
void IntRand(int*& A, int min, int max, int num)
{
 A = new int[num];
 for (int i = 0; i < num; i++)
 {
  A[i] = rand() % (max - min + 1);
  A[i] += min;
 }
}
//分治法求最大元素
int Max(int A[], int l, int r)
{
 if (l == r) return A[l];
 int mid = (l + r) / 2;
 int maxLe = Max(A, l, mid);
 int maxRi = Max(A, mid + 1, r);
 return maxLe > maxRi ? maxLe : maxRi;
}
//数字旋转方阵
void Full(int** A, int num, int begin, int size)
{
 if (size == 0) return;
 if (size == 1) { A[begin][begin] = num; return; }
 int i = begin, j = begin;
 for (int k = 0; k < size - 1; k++) A[i++][j] = num++;
 for (int k = 0; k < size - 1; k++) A[i][j++] = num++;
 for (int k = 0; k < size - 1; k++) A[i--][j] = num++;
 for (int k = 0; k < size - 1; k++) A[i][j--] = num++;
 Full(A, num, begin + 1, size - 2);
}
//归并排序
void MergeSort(int* A, int l, int r)
{
 if (l == r) return;
 int mid = (l + r) / 2;
 int B[100];
 MergeSort(A, l, mid);
 MergeSort(A, mid + 1, r);
 Merge(A, B, l, mid, r);
 for (int i = l; i <= r; i++)
  A[i] = B[i];
}
void Merge(const int* A, int* B, int l, int m, int r)
{
 int i = l, j = m + 1, k = l;
 while (i <= m && j <= r)
 {
  if (A[i] <= A[j]) B[k++] = A[i++];
  else B[k++] = A[j++];
 }
 while (i <= m) B[k++] = A[i++];
 while (j <= r) B[k++] = A[j++];
}
//快速排序
void QuickSort(int* A, int l, int r)
{
 if (l < r)
 {
  int m = Partition(A, l, r);
  QuickSort(A, l, m - 1);
  QuickSort(A, m + 1, r);
 }
}
int Partition(int* A, int l, int r)
{
 int flag = A[l];
 while (l < r)
 {
  while (l < r && flag < A[r]) r--;
  if (l < r) A[l++] = A[r];
  while (l < r && A[l] < flag) l++;
  if (l < r) A[r--] = A[l];
 }
 A[l] = flag;
 return l;
}
//求最大子段和
int MaxSum(int* A, int l, int r)
{
 int sum = 0;
 if (l == r) sum = A[l];
 else
 {
  int mid, sumLe, sumRi, sumMid, s1, s2, lefts, rights;
  mid = (l + r) / 2;
  sumLe = MaxSum(A, l, mid);
  sumRi = MaxSum(A, mid + 1, r);
  sum = sumLe > sumRi ? sumLe : sumRi;
  //x~mid的最大子串和
  s1 = 0; lefts = 0;
  for (int i = mid; i >= l; i--)
  {
   lefts += A[i];
   if (lefts > s1) s1 = lefts;
  }
  //mid~y的最大子串和
  s2 = 0; rights = 0;
  for (int i = mid; i >= l; i--)
  {
   rights += A[i];
   if (rights > s1) s1 = rights;
  }
  sumMid = s1 + s2;
  sum = sum > sumMid ? sum : sumMid;
 }
 return sum;
}
//求最近点对
double Closest(point* p, int l, int r)
{
 double min;
 if (l >= r) min = 0;//输入不合法
 else if (r - l == 1) min = Distance(p[l], p[r]);//两个点
 else if (r - l == 2)//三个点
 {
  double min1, min2, min3;
  min1 = Distance(p[l], p[l + 1]);
  min2 = Distance(p[l], p[r]);
  min3 = Distance(p[l + 1], p[r]);
  min = min1 < min2 ? min1 : min2;
  min = min < min3 ? min : min3;
 }
 else
 {
  int mid = (l + r) / 2, ll = mid, rr = mid;
  double midx, minLe, minRi;
  if ((l - r + 1) % 2 == 0) midx = (p[mid].x + p[mid + 1].x) / 2;
  else midx = p[mid].x;
  minLe = Closest(p, l, mid);
  minRi = Closest(p, mid + 1, r);
  min = minLe < minRi ? minLe : minRi;
  while (midx - p[ll].x < min) ll--;
  while (p[rr].x - midx < min) rr++;
  for(int i=ll;p[i].x<=midx;i++)
   for (int j = rr; p[j].x > midx; j--)
   {
    double temp = Distance(p[ll], p[rr]);
    if (temp < min) min = temp;
   }
 }
 return min;
}
int ClosetCmp(point p, point q)
{
 return p.x < q.x;
}
double Distance(point p, point q)
{
 return sqrt(pow(p.x - q.x, 2) + pow(p.y - q.y, 2));
}
int main()
{
 /*数字旋转方阵
 int n;
 cin >> n;
 int** A = new int*[n];
 for (int i = 0; i < n; i++)
  A[i] = new int[n];
 Full(A, 0, 0, n);
 for (int i = 0; i < n; i++)
 {
  for (int j = 0; j < n; j++)
  {
   cout.width(5);
   cout << A[i][j];
  }
  cout << endl;
 }
 */
 /*归并排序
 int n;
 cin >> n;
 int* A = new int[n];
 for (int i = 0; i < n; i++)
  A[i] = rand() % 100;
 cout << "归并排序前:";
 for (int i = 0; i < n; i++)
 {
  cout.width(3);
  cout << A[i];
 }
 MergeSort(A, 0, n - 1);
 cout << "\n归并排序后:";
 for (int i = 0; i < n; i++)
 {
  cout.width(3);
  cout << A[i];
 }
 */
 /*快速排序
 int n;
 cin >> n;
 int* A = new int[n];
 for (int i = 0; i < n; i++)
  A[i] = rand() % 100;
 cout << "快速排序前:";
 for (int i = 0; i < n; i++)
 {
  cout.width(3);
  cout << A[i];
 }
 QuickSort(A, 0, n - 1);
 cout << "\n快速排序后:";
 for (int i = 0; i < n; i++)
 {
  cout.width(3);
  cout << A[i];
 }
 */
 /*求最大子串和
 int* a, n, maxSum;
 cin >> n;
 MyRand(a, -10, 10, n);
 maxSum = MaxSum(a, 0, n - 1);
 for (int i = 0; i < n; i++)
  cout << a[i] << ' ';
 cout << "\n最大子串和为:" << maxSum;
 */
 /*最近点对
 int n, * temp;
 cin >> n;
 point* p = new point[n];
 IntRand(temp, 0, 1000, 2 * n);
 for (int i = 0; i < n; i++)
 {
  p[i].x = temp[2 * i] / 100.0;
  p[i].y = temp[2 * i + 1] / 100.0;
 }
 sort(p, p + n, ClosetCmp);
 double min = Closest(p, 0, n - 1);
 for (int i = 0; i < n; i++)
 {
  cout.width(4);
  cout << p[i].x << ',' << p[i].y << endl;
 }
 cout << "cloest distance:" << min;
 */
 return 0;
}

猜你喜欢

转载自blog.csdn.net/The_Only_God/article/details/105373625