1. 程式人生 > >演算法 最近對問題完整程式碼分析

演算法 最近對問題完整程式碼分析

#include <iostream>
//#include <algorithm>
#include<cmath>
using namespace std;
const int n=10;
struct point{          //點
	int x;
	int 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));
}
//int cmp(const void *a, const void *b)
//{return (*(point *)a).y >(*(point *)b).y ? 1 : -1;}
int Partition(point r[], int first, int end){           //快速排序演算法中劃分區間
	int i = first, j = end;
	while (i < j){
		while (i < j&&r[i].y <= r[j].y) j--;
		if (i < j){
			point temp = r[i]; r[i] = r[j], r[j] = temp;
			i++;
		}
		while (i < j&&r[i].y <= r[j].y) i++;
		if (i < j){
			point temp = r[i]; r[i] = r[j], r[j] = temp;
			j--;
		}
	}
	return i;
}
void QuickSort(point r[], int first, int end){               //快速排序
	int pivot;
	if (first < end){
		pivot = Partition(r, first, end);
		QuickSort(r, first, pivot - 1);
		QuickSort(r, pivot + 1, end);
	}
}
double Closest(point S[], int low, int high){            //最近對劃分計算
	double d1, d2, d3, d;
	int mid, i, j, index;
	point P[n];                                    //存放 P1 P2
	if (high - low == 1){                           //只有兩點
		return Distance(S[low], S[high]);    
	}
	if (high - low == 2){                      //三個點
		d1 = Distance(S[low], S[low + 1]);
		d2 = Distance(S[low + 1], S[high]);
		d3 = Distance(S[low], S[high]);
		if ((d1 < d2) && (d1 < d3)) return d1;
		else if (d2 < d3) return d2;
		else return d3;
	}
	mid = (low + high) / 2;              //求出中值
	d1 = Closest(S, low, mid);            //遞迴求P1
	d2 = Closest(S, mid + 1, high);        //遞迴求P2
	if (d1 <= d2) d = d1;
	else d = d2;
	index = 0;                         //P1和P2之間最近對
	for (i = mid; (i >= low) && (S[mid].x - S[i].x < d); i--)
		P[index++] = S[i];
	for (i = mid + 1; (i <= high) && (S[i].x - S[mid].x < d); i++)
		P[index++] = S[i];
	QuickSort(P , 0, index - 1);      //按y上升排序         
	//qsort(P, 100, sizeof(P[0]), cmp);//不正確
	for (i = 0; i < index; i++){
		for (j = i + 1; j < index; j++){
			if (P[j].y - P[i].y >= d)
				break;
			else{d3 = Distance(P[i], P[j]);
				if (d3 < d)  d = d3;
			}
		}
	}
	return d;
}
int main(){
	while (1)           //迴圈測試
	{
		int n, i;
		double	answer;
		cout << "輸入點個數" << endl;
		cin >> n;
		while (n <= 1){     //輸入錯誤重新輸入
			cout << "點數不能小於2請重新輸入" << endl; 
			cin>>n; 
		}
		point *P;        //new 和 delete[] 要配對使用
		P = new point[n];
		for (i = 0; i < n; i++){
			cout << "input x.y:\n";
			cin >> P[i].x>> P[i].y;
		}
		for (i = 0; i < n; i++){
			cout <<"點"<<i+1<<"座標"<< P[i].x<<" "<< P[i].y<<"  ";
		}
		answer = Closest(P, 0, n-1);     //輸入n-1為了不越界
		cout << "最近對為" << answer << endl;
		delete[] P;	
	}
	return 1;
}

在這個演算法中學到了 struck 結構體函式的定義和用法他和陣列的區別。 以及 巨集#define 定義的常量預編譯 呼叫 和const 定義的常量 變數的優秀之處。

sort 快速排序演算法qsort  還有int *p=new int[n]     和 delete[] p  的用法。

當然最最重要的是 分治法 求解問題。 當一個複雜問題分解到很小時候可以很容易求解那麼分治法就是很好的選擇。

還有就是遞迴的理解和越界問題。