生活随笔
收集整理的這篇文章主要介紹了
蛮力法-分治法-处理最近对问题
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
兩種方法對最近對問題的解釋
背景描述:
??終于,隔了將近一周,開始更新第二篇算法博客。今天的問題是最近對問題。問題描述如下:對于二維坐標系中的若干個點,從中判斷出相距最近的兩個點,并輸出最近的這個距離。
??我之前也翻看了很多篇博客,大家都解釋的很好,但是都只是輸出了最近的距離,而我希望這個程序不僅能輸出最近距離,同時還能鎖定是哪兩個點得到的這個最近距離。于是,經過反復試錯后,終于得到滿意的結果,馬不停蹄過來更新博客了。
蠻力法:
??首先介紹蠻力法的思路。顧名思義,就是從第一個點開始,求它和第二個點之間的距離,然后求它和第三個點之間的距離,依次往后遍歷。經過兩重循環之后就可以得出最短的距離,同時鎖定是哪兩個點產生的。
??可以設置兩個一維數組,一個存儲橫坐標,另一個存儲縱坐標,注意要兩個數組彼此之間一一對應。完整算法如下(由于蠻力法較為簡單,此處只給出算法部分,完整程序請參考下面分治法):
float Getclosedpoint(int *x
, int *y
, int n
, int &index1
, int &index2
)
{float min
= (x
[0] - x
[1])*(x
[0] - x
[1]) + (y
[0] - y
[1])*(y
[0] - y
[1]);float path
;for (int i
= 0; i
< n
- 1; i
++){for (int j
= i
+ 1; j
< n
; j
++){path
= (x
[i
] - x
[j
])*(x
[i
] - x
[j
]) + (y
[i
] - y
[j
])*(y
[i
] - y
[j
]);if (path
<= min
){min
= path
;index1
= i
;index2
= j
;}}}return min
;
}
蠻力法時間復雜度分析:
??假設有n個點,則從外層循環是從第一個數字開始,循環到第n-1個數停止,共循環n-1次。內層循環一開始從第一個數開始,遍歷求與后面所有的點之間的距離,共n-1次,最后一次循環從第n-1個數開始,求和第n個數之間的距離,執行1次。所以共執行1+2+…+(n-2)+(n-1)=n(n-1)/2;所以時間復雜度O(n2).
分治法
??分治法顧名思義是分而治之,將一個大問題分解成幾個小問題再逐個解決。對于最近對問題,分治法的思路如下:
??1.首先將這些雜亂的點按照橫坐標進行排序,然后取中間值mid將這堆點分成左右兩部分。
??2.分別對左邊和右邊的兩小堆點集再次遞歸使用分治法,進而得到對應的最短距離d1和d2。
??3.接下來處理mid中間線部分的情況。因為有一種可能就是距離最短的兩個點一個在左區域一個在右區域。因此我們要對這種情況進行解決。辦法是從剛才第二步中的兩個結果中取最小值d,然后以步驟1中的中間值mid為基準,劃分出寬度為2d的一個區域,然后將這個區域中的點進行蠻力法求得對應的最短距離d3。
??4.最后將結果進行比較。
??算法的完整程序如下:
#include<iostream>
#include<math.h>
#include<time.h>
using namespace std
;struct point {int x
, y
;
};
int Partition(point
*R
, int low
, int high
)
{int pivotkey
;R
[0] = R
[low
];pivotkey
= R
[low
].x
;while (low
< high
){while (low
< high
&&R
[high
].x
>= pivotkey
)high
--;if (low
< high
)R
[low
++] = R
[high
];while (low
< high
&&R
[low
].x
<= pivotkey
)low
++;if (low
< high
)R
[high
--] = R
[low
];}R
[low
] = R
[0];return low
;
}
void Sort(point
*R
, int s
, int t
)
{int pivotloc
;if (s
< t
){pivotloc
= Partition(R
, s
, t
);Sort(R
, s
, pivotloc
- 1);Sort(R
, pivotloc
+ 1, t
);}
}
void QuickSort(point
*R
, int n
)
{Sort(R
, 1, n
- 1);
}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 index(double x
, point
*S
, int low
, int high
)
{for (int i
= 0; i
< high
- low
+ 1; i
++){if (S
[i
].x
<= x
&& S
[i
+ 1].x
> x
)return i
;}
}
double Closest(point S
[], int low
, int high
,int &loc1
,int &loc2
)
{double d1
, d2
, d3
, d
;int a1
, b1
, a2
, b2
; int mid
;int n1
= 0; int n2
= 0;if (high
- low
== 1) {loc1
= low
;loc2
= high
;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
)){loc1
= low
;loc2
= low
+ 1;return d1
;}else if (d2
< d3
){loc1
= low
+ 1;loc2
= high
;return d2
;}else{loc1
= low
;loc2
= high
;return d3
;}}mid
= (low
+ high
) / 2; d1
= Closest(S
, low
, mid
, a1
, a2
); d2
= Closest(S
, mid
+ 1, high
, b1
, b2
); if (d1
< d2
) {d
= d1
;loc1
= a1
;loc2
= a2
;}else{d
= d2
;loc1
= b1
;loc2
= b2
;}int index1
= 0;int index2
= 0;for (int i
= 0; i
< high
- low
+ 1; i
++){if (S
[i
].x
<= S
[mid
].x
- d
&& S
[i
+ 1].x
> S
[mid
].x
- d
){index1
= i
;break;}}for (int i
= 0; i
< high
- low
+ 1; i
++){if (S
[i
].x
<= S
[mid
].x
+ d
&& S
[i
+ 1].x
> S
[mid
].x
+ d
){index2
= i
;break;}}for (int i
= index1
; i
< index2
- index1
; i
++){for (int j
= i
+ 1; j
< index2
- index1
; j
++){if (S
[j
].y
- S
[i
].y
>= 0)break;else{d3
= Distance(S
[i
], S
[j
]);if (d3
< d
){d
= d3
;loc1
= i
;loc2
= j
;}}}}return d
;
}int main()
{point
*S
= new point
[11];int x
[10] = { 12,14,4,77,89,9,99,96,77,93 };int y
[10] = { 13,56,55,67,34,21,65,78,87,22 };S
[0].x
= 0;S
[0].y
= 0;for (int i
= 1; i
< 11; i
++){S
[i
].x
= x
[i
- 1];S
[i
].y
= y
[i
- 1];}QuickSort(S
, 11);int index1
= 0;int index2
= 0;cout
<< Closest(S
, 1, 10, index1
, index2
) << endl
;cout
<< "(" << S
[index1
].x
<< "," << S
[index1
].y
<< ") 和 (" << S
[index2
].x
<< "," << S
[index2
].y
<< ")" << endl
;cout
<< "The run time is:" << (double)clock() / CLOCKS_PER_SEC
<< "s" << endl
;
}
分治法的時間復雜度分析
??對于分治法,假設有k個數,當k=2時,時間復雜度為:T(n)=1;
當k>2時,時間復雜度為T(n)=2T(n/2)+n;對這樣的遞推式最終得到T(n)=O(nlog2n )。
算法總結
??對于分治法,有三點總結:1.寫遞歸函數時,一定一定一定要考慮到遞歸跳出的情況,寫出這種情況時如何return。2.對于確定點的坐標,遞歸函數中將index作為引用參數,傳入函數體內,這種思路沒毛病,需要注意的是,在函數體內再次調用遞歸函數時,傳入的引用不能再是index,要用新的變量。否則的話index就得不到想要的值。3.對于遞歸函數,也是可以用new函數動態分配內存空間的,如果報錯,原因極可能是代碼出錯。
??最后的最后,這幾天莫名的有些焦慮。因為挑戰杯,因為大學生計算機設計大賽,很多比賽擺在面前但是我卻不知道怎么參加,不知道和誰一起參加,不知道自己的能力夠不夠參加,但是內心對于參賽這種經歷的渴望又在催促我去參加。自我的懷疑和對未知的渴望在我心中糾纏,好焦慮。唉,明天還是去找老師聊一聊伐。
總結
以上是生活随笔為你收集整理的蛮力法-分治法-处理最近对问题的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。