[关闭]
@rg070836rg 2016-01-01T15:17:39.000000Z 字数 8121 阅读 1615

算法概论实验三

算法概论实验


  1. 实验三
  2. 实验目的与要求:理解分治法的基本思想和设计方法。
  3. 实验题目:
  4. 1.寻找中项
  5. 【问题描述】
  6. 对于长度为n的整型数组A,随机生成其数组元素值,然后实现一个线性时间的算法,在该数组中查找其中项。
  7. 2.寻找最邻近的点对
  8. 【问题描述】
  9. p1=(x1,y1), p2=(x2,y2), , pn=(xn,yn) 是平面上n个点构成的集合S,设计和实现找出集合S中距离最近点对的算法。

1.寻找中项

  1. #include<iostream>
  2. using namespace std;
  3. struct partIndex
  4. {
  5. int partIndex0;
  6. int partIndex1;
  7. };
  8. //将arrray分成三块,并返回各块的下标
  9. partIndex partition(int *r, int low, int high) {
  10. // TODO 把数组段第一个数划分,并返回中间值的下标
  11. int pivot = r[low];// 记录pivot
  12. while (low < high)
  13. {
  14. while (low < high && r[high] > pivot)
  15. high--;
  16. if (low < high)
  17. r[low++] = r[high];
  18. while (low < high && r[low] < pivot)
  19. low++;
  20. if (low < high)
  21. r[high--] = r[low];
  22. }
  23. r[low] = pivot;
  24. partIndex pi; pi.partIndex0 = low; pi.partIndex1 = high;
  25. while (r[pi.partIndex0 - 1] == pivot)
  26. {
  27. pi.partIndex0--;
  28. }
  29. while (r[pi.partIndex1 + 1] == pivot)
  30. {
  31. pi.partIndex1++;
  32. }
  33. return pi;
  34. }
  35. /出 arrray中第k小的元素
  36. int select(int *array, int startIndex, int endIndex, int k)
  37. {
  38. int kItem;
  39. //只有2个元素的情况,返回相应值
  40. if (endIndex - startIndex < 2)
  41. {
  42. if (array[startIndex] < array[endIndex])
  43. kItem = k == 1 ? array[startIndex] : array[endIndex];
  44. else
  45. kItem = k == 1 ? array[endIndex] : array[startIndex];
  46. return kItem;
  47. }
  48. //小于段(0,partIndex0) 大于段(partIndex1,endIndex)
  49. partIndex pi = partition(array, startIndex, endIndex);
  50. if (k <= pi.partIndex0 - startIndex)
  51. {
  52. kItem = select(array, startIndex, pi.partIndex0, k);
  53. }
  54. else
  55. {
  56. if (k > pi.partIndex1 - startIndex + 1)
  57. {
  58. kItem = select(array, pi.partIndex1, endIndex, k - (pi.partIndex1 - startIndex) - 1);
  59. }
  60. else
  61. {
  62. kItem = array[pi.partIndex0];
  63. }
  64. }
  65. return kItem;
  66. }
  67. int main()
  68. {
  69. int array[43] = { 76, 80, 82, 88 };
  70. int len = 4;
  71. cout << "分治算法求的的中位数为:" << select(array, 0, len - 1, len / 2);
  72. return 0;
  73. }

2.寻找最邻近的点对

  1. import java.util.Random;
  2. public class MinDistance {
  3. public static void main(String []agrs){
  4. Point[] points = getRandomPoints(1000, 1000);
  5. System.out.println("分治法求得:");
  6. Point[] minPair1 = getMinPair_DC(points, 0, points.length - 1);
  7. printMinPair(minPair1);
  8. }
  9. //compute the minimun distance by divide and conquer
  10. /**
  11. *
  12. * @param points
  13. * @return
  14. */
  15. private static Point[] getMinPair_DC(Point[] points, int startIndex, int endIndex){
  16. int len = endIndex - startIndex + 1;
  17. double []arrayX = new double [len];
  18. for(int i = startIndex; i < len; i++){
  19. arrayX[i] = points[i].x;
  20. }
  21. quickSort(points, arrayX, startIndex, endIndex);
  22. return getMinPair(points, startIndex, endIndex);
  23. }
  24. /**
  25. *
  26. * @param points
  27. * @param startIndex
  28. * @param endIndex
  29. * @return
  30. */
  31. private static Point[] getMinPair(Point[] points, int startIndex, int endIndex){
  32. Point[] minPair = new Point[2];
  33. if(endIndex <= startIndex){
  34. minPair[0] = points[startIndex];
  35. minPair[1] = null;
  36. return minPair;
  37. }
  38. if(endIndex - startIndex == 1){
  39. minPair[0] = points[startIndex];
  40. minPair[1] = points[endIndex];
  41. return minPair;
  42. }
  43. double minDis = Double.MAX_VALUE;
  44. int mid = (endIndex + startIndex) / 2;
  45. Point[] minPair0 = getMinPair(points, startIndex, mid);
  46. Point[] minPair1 = getMinPair(points, mid, endIndex);
  47. minPair = minPair0[0].getDistance(minPair0[1]) < minPair1[0].getDistance(minPair1[1]) ? minPair0 : minPair1;
  48. minDis = minPair[0].getDistance(minPair[1]);
  49. int midLeft, midRight;
  50. for(midLeft = mid; points[mid].x - points[midLeft].x < minDis && midLeft > startIndex; midLeft --){}
  51. for(midRight = mid; points[midRight].x - points[mid].x < minDis && midRight < endIndex; midRight ++){}
  52. int midNum = midRight - midLeft + 1;
  53. Point[] midAreaPoints = new Point[midNum];
  54. double [] arrayY = new double[midNum];
  55. System.arraycopy(points, midLeft, midAreaPoints, 0, midNum);
  56. for(int i = 0; i < midNum ; i ++){
  57. arrayY[i] = points[i].y;
  58. }
  59. quickSort(midAreaPoints, arrayY, 0, midNum - 1);
  60. for(int i = 0 ; i < midNum ;i ++){
  61. for(int j = i+1 ; j < midNum && j< i + 11; j ++){
  62. if(midAreaPoints[i].getDistance(midAreaPoints[j]) < minDis){
  63. minPair[0] = midAreaPoints[i];
  64. minPair[1] = midAreaPoints[j];
  65. minDis = midAreaPoints[i].getDistance(midAreaPoints[j]);
  66. }
  67. }
  68. }
  69. return minPair;
  70. }
  71. /**
  72. *
  73. * @param maxValue
  74. * @param len
  75. * @return
  76. */
  77. private static Point[] getRandomPoints(int maxValue, int len){
  78. Point [] points = new Point[len];
  79. java.util.Random r = new Random();
  80. for(int i = 0; i < len; i++){
  81. points[i] = new Point();
  82. points[i].setx(r.nextDouble() * maxValue);
  83. points[i].sety(r.nextDouble() * maxValue);
  84. }
  85. return points;
  86. }
  87. /**
  88. *
  89. * @param pointPair
  90. */
  91. private static void printMinPair(Point[] minPair){
  92. if(minPair.length != 2){
  93. System.err.println("传入数据错误");
  94. }
  95. System.out.println("两点:" + minPair[0].toString() + "," + minPair[1].toString());
  96. System.out.println("距离:" + minPair[0].getDistance(minPair[1]));
  97. }
  98. /**
  99. *
  100. * @param points
  101. * @param array
  102. * @param startIndex
  103. * @param endIndex
  104. */
  105. static void quickSort(Point[] points, double[]array, int startIndex, int endIndex){
  106. if(startIndex < endIndex)
  107. {
  108. int mid = partition(points, array, startIndex, endIndex);
  109. quickSort(points, array, startIndex, mid);
  110. quickSort(points, array, mid+1, endIndex);
  111. }
  112. }
  113. /**
  114. *
  115. * @param points
  116. * @param array
  117. * @param startIndex
  118. * @param endIndex
  119. * @return
  120. */
  121. static int partition(Point[] points, double []array, int startIndex, int endIndex){
  122. int i = startIndex;
  123. int j = endIndex;
  124. double pivot = array[startIndex];
  125. Point pivotP = points[startIndex];
  126. while(i < j){
  127. while(array[j] > pivot && i < j){
  128. j--;
  129. }
  130. if(i < j){
  131. points[i] = points[j];
  132. array[i++] = array[j];
  133. }
  134. while(array[i] < pivot && i < j){
  135. i++;
  136. }
  137. if(i < j){
  138. points[j] = points[i];
  139. array[j--] = array[i];
  140. }
  141. }
  142. array[i] = pivot;
  143. points[i] = pivotP;
  144. return j;
  145. }
  146. }
  147. class Point{
  148. double x;
  149. double y;
  150. Point(){
  151. this.x = 0;
  152. this.y = 0;
  153. }
  154. Point(double x, double y){
  155. this.x = x;
  156. this.y = y;
  157. }
  158. void setx(double x){
  159. this.x = x;
  160. }
  161. void sety(double y){
  162. this.y = y;
  163. }
  164. double getDistance(Point p){
  165. if(p == null){
  166. return Double.MAX_VALUE;
  167. }
  168. return Math.sqrt((p.x - this.x) * (p.x - this.x) + (p.y - this.y) * (p.y - this.y));
  169. }
  170. @Override
  171. public String toString() {
  172. // TODO Auto-generated method stub
  173. return "(" + this.x + "," +this.y + ")";
  174. }
  175. }

2.寻找最邻近的点对

  1. //二维最邻近点对问题
  2. //#include "stdafx.h"
  3. #include<time.h>
  4. #include<iostream>
  5. #include<cmath>
  6. using namespace std;
  7. const int M = 50;
  8. //用类PointX和PointY表示依x坐标和y坐标排好序的点
  9. class PointX {
  10. public:
  11. int operator<=(PointX a)const
  12. {
  13. return (x <= a.x);
  14. }
  15. int ID; //点编号
  16. float x, y; //点坐标
  17. };
  18. class PointY {
  19. public:
  20. int operator<=(PointY a)const
  21. {
  22. return(y <= a.y);
  23. }
  24. int p; //同一点在数组x中的坐标
  25. float x, y; //点坐标
  26. };
  27. float Random();
  28. template <class Type>
  29. float dis(const Type&u, const Type&v);
  30. bool Cpair2(PointX X[], int n, PointX& a, PointX& b, float& d);
  31. void closest(PointX X[], PointY Y[], PointY Z[], int l, int r, PointX& a, PointX& b, float& d);
  32. template <typename Type>
  33. void Copy(Type a[], Type b[], int left, int right);
  34. template <class Type>
  35. void Merge(Type c[], Type d[], int l, int m, int r);
  36. template <class Type>
  37. void MergeSort(Type a[], Type b[], int left, int right);
  38. int main()
  39. {
  40. srand((unsigned)time(NULL));
  41. int length;
  42. cout << "请输入点对数:";
  43. cin >> length;
  44. PointX X[M];
  45. cout << "随机生成的二维点对为:" << endl;
  46. for (int i = 0; i<length; i++)
  47. {
  48. X[i].ID = i;
  49. X[i].x = Random();
  50. X[i].y = Random();
  51. cout << "(" << X[i].x << "," << X[i].y << ") ";
  52. }
  53. PointX a;
  54. PointX b;
  55. float d;
  56. Cpair2(X, length, a, b, d);
  57. cout << endl;
  58. cout << "最邻近点对为:(" << a.x << "," << a.y << ")和(" << b.x << "," << b.y << ") " << endl;
  59. cout << "最邻近距离为: " << d << endl;
  60. return 0;
  61. }
  62. float Random()
  63. {
  64. float result = rand() % 10000;
  65. return result*0.01;
  66. }
  67. //平面上任意两点u和v之间的距离可计算如下
  68. template <class Type>
  69. inline float dis(const Type& u, const Type& v)
  70. {
  71. float dx = u.x - v.x;
  72. float dy = u.y - v.y;
  73. return sqrt(dx*dx + dy*dy);
  74. }
  75. bool Cpair2(PointX X[], int n, PointX& a, PointX& b, float& d)
  76. {
  77. if (n<2) return false;
  78. PointX* tmpX = new PointX[n];
  79. MergeSort(X, tmpX, 0, n - 1);
  80. PointY* Y = new PointY[n];
  81. for (int i = 0; i<n; i++) //将数组X中的点复制到数组Y中
  82. {
  83. Y[i].p = i;
  84. Y[i].x = X[i].x;
  85. Y[i].y = X[i].y;
  86. }
  87. PointY* tmpY = new PointY[n];
  88. MergeSort(Y, tmpY, 0, n - 1);
  89. PointY* Z = new PointY[n];
  90. closest(X, Y, Z, 0, n - 1, a, b, d);
  91. delete[]Y;
  92. delete[]Z;
  93. delete[]tmpX;
  94. delete[]tmpY;
  95. return true;
  96. }
  97. void closest(PointX X[], PointY Y[], PointY Z[], int l, int r, PointX& a, PointX& b, float& d)
  98. {
  99. if (r - l == 1) //两点的情形
  100. {
  101. a = X[l];
  102. b = X[r];
  103. d = dis(X[l], X[r]);
  104. return;
  105. }
  106. if (r - l == 2) //3点的情形
  107. {
  108. float d1 = dis(X[l], X[l + 1]);
  109. float d2 = dis(X[l + 1], X[r]);
  110. float d3 = dis(X[l], X[r]);
  111. if (d1 <= d2 && d1 <= d3)
  112. {
  113. a = X[l];
  114. b = X[l + 1];
  115. d = d1;
  116. return;
  117. }
  118. if (d2 <= d3)
  119. {
  120. a = X[l + 1];
  121. b = X[r];
  122. d = d2;
  123. }
  124. else {
  125. a = X[l];
  126. b = X[r];
  127. d = d3;
  128. }
  129. return;
  130. }
  131. //多于3点的情形,用分治法
  132. int m = (l + r) / 2;
  133. int f = l, g = m + 1;
  134. //在算法预处理阶段,将数组X中的点依x坐标排序,将数组Y中的点依y坐标排序
  135. //算法分割阶段,将子数组X[l:r]均匀划分成两个不想交的子集,取m=(l+r)/2
  136. //X[l:m]和X[m+1:r]就是满足要求的分割。
  137. for (int i = l; i <= r; i++)
  138. {
  139. if (Y[i].p>m) Z[g++] = Y[i];
  140. else Z[f++] = Y[i];
  141. }
  142. closest(X, Z, Y, l, m, a, b, d);
  143. float dr;
  144. PointX ar, br;
  145. closest(X, Z, Y, m + 1, r, ar, br, dr);
  146. if (dr<d)
  147. {
  148. a = ar;
  149. b = br;
  150. d = dr;
  151. }
  152. Merge(Z, Y, l, m, r);//重构数组Y
  153. //d矩形条内的点置于Z中
  154. int k = l;
  155. for ( i = l; i <= r; i++)
  156. {
  157. if (fabs(X[m].x - Y[i].x)<d)
  158. {
  159. Z[k++] = Y[i];
  160. }
  161. }
  162. //搜索Z[l:k-1]
  163. for ( i = l; i<k; i++)
  164. {
  165. for (int j = i + 1; j<k && Z[j].y - Z[i].y<d; j++)
  166. {
  167. float dp = dis(Z[i], Z[j]);
  168. if (dp<d)
  169. {
  170. d = dp;
  171. a = X[Z[i].p];
  172. b = X[Z[j].p];
  173. }
  174. }
  175. }
  176. }
  177. template <class Type>
  178. void Merge(Type c[], Type d[], int l, int m, int r)
  179. {
  180. int i = l, j = m + 1, k = l;
  181. while ((i <= m) && (j <= r))
  182. {
  183. if (c[i] <= c[j])
  184. {
  185. d[k++] = c[i++];
  186. }
  187. else
  188. {
  189. d[k++] = c[j++];
  190. }
  191. }
  192. if (i>m)
  193. {
  194. for (int q = j; q <= r; q++)
  195. {
  196. d[k++] = c[q];
  197. }
  198. }
  199. else
  200. {
  201. for (int q = i; q <= m; q++)
  202. {
  203. d[k++] = c[q];
  204. }
  205. }
  206. }
  207. template <class Type>
  208. void MergeSort(Type a[], Type b[], int left, int right)
  209. {
  210. if (left<right)
  211. {
  212. int i = (left + right) / 2;
  213. MergeSort(a, b, left, i);
  214. MergeSort(a, b, i + 1, right);
  215. Merge(a, b, left, i, right);//合并到数组b
  216. Copy(a, b, left, right);//复制回数组a
  217. }
  218. }
  219. template <typename Type>
  220. void Copy(Type a[], Type b[], int left, int right)
  221. {
  222. for (int i = left; i <= right; i++)
  223. a[i] = b[i];
  224. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注