java算法事例:连通性

java算法事例:连通性

假设现在一个整数对序列,每个整数代表某种类型的对象,用p-q对表示“p连接到q”,又假设连接具有传递性,即p连接到q,q连接到r,则p连接到r。

例一:解决连通性问题的快速查找算法

Java代码
  1. publicclassQuickF{
  2. publicstaticvoidmain(String[]args){
  3. intN=10;
  4. intid[]=newint[N];
  5. for(inti=0;i<N;i++){
  6. id[i]=i;
  7. }
  8. int[][]a=newint[][]{
  9. {3,4},{4,9},{8,0},{2,3},{0,2},{5,6},
  10. {2,9},{5,9},{7,3},{4,8},{5,6},{6,1}
  11. };
  12. System.out.println(Arrays.toString(id));
  13. for(int[]s:a){
  14. intp=s[0],q=s[1];
  15. intt=id[p];
  16. if(t==id[q]){
  17. continue;
  18. }
  19. for(inti=0;i<N;i++){
  20. if(id[i]==t){
  21. id[i]=id[q];
  22. System.out.println(""+p+""+q);
  23. System.out.println(Arrays.toString(id));
  24. }
  25. }
  26. }
  27. }
  28. }

在用快速查找算法时,对序列{p,q}每一对进行处理后,id数组中的值为合并操作。把所有与id[p]值相同的元素值变为id[q]值。

例二:快速合并(并不快速的查找)

Java代码
  1. publicclassQuickFU{
  2. publicstaticvoidmain(String[]args){
  3. intN=10;
  4. intid[]=newint[N];
  5. for(inti=0;i<N;i++){
  6. id[i]=i;
  7. }
  8. int[][]a=newint[][]{
  9. {3,4},{4,9},{8,0},{2,3},{5,6},{2,9},
  10. {5,9},{7,3},{4,8},{5,6},{0,2},{6,1},{5,8}
  11. };
  12. System.out.println(Arrays.toString(id));
  13. for(int[]s:a){
  14. inti,j,p=s[0],q=s[1];
  15. for(i=p;i!=id[i];i=id[i]);
  16. for(j=q;j!=id[j];j=id[j]);
  17. if(i==j){
  18. continue;
  19. }
  20. id[i]=j;
  21. System.out.println(""+p+""+q);
  22. System.out.println(Arrays.toString(id));
  23. }
  24. }
  25. }

在快速查找算法中,只需经过一个连接就可以找到节点;而在快速合并中中,可能需要多个节点才能找到。

例三:快速合并的加权版本

Java代码
  1. publicclassQuickFW{
  2. publicstaticvoidmain(String[]args){
  3. intN=10;
  4. intid[]=newint[N];
  5. intsz[]=newint[N];
  6. for(inti=0;i<N;i++){
  7. id[i]=i;
  8. sz[i]=1;
  9. }
  10. int[][]a=newint[][]{
  11. {3,4},{4,9},{8,0},{2,3},{5,6},{2,9},
  12. {5,9},{7,3},{4,8},{5,6},{0,2},{6,1}
  13. };
  14. System.out.println(Arrays.toString(id));
  15. for(int[]s:a){
  16. inti,j,p=s[0],q=s[1];
  17. for(i=p;i!=id[i];i=id[i]);
  18. for(j=q;j!=id[j];j=id[j]);
  19. if(i==j){
  20. continue;
  21. }
  22. if(sz[i]<sz[j]){
  23. id[i]=j;
  24. sz[j]+=sz[i];
  25. }else{
  26. id[j]=i;
  27. sz[i]+=sz[j];
  28. }
  29. System.out.println(""+p+""+q);
  30. System.out.println(Arrays.toString(id));
  31. System.out.println(Arrays.toString(sz));
  32. }
  33. }
  34. }

加权快速合并算法在典型情况下,可以在线性时间内解决实际问题。

路径压缩,在合并操作中,经过每条路径就加一条连线,把一路上遇到的对应的每个顶点的id数组值都设为到树根上,逼近了快速查找算法的理想状态。

例四:压缩方法:使在通向树根的路中的每条连线都指向路劲中的下一个节点,即折半路径压缩的加权快速合并

Java代码
  1. publicclassQuickFH{
  2. publicstaticvoidmain(String[]args){
  3. intN=10;
  4. intid[]=newint[N];
  5. intsz[]=newint[N];
  6. for(inti=0;i<N;i++){
  7. id[i]=i;
  8. sz[i]=1;
  9. }
  10. int[][]a=newint[][]{
  11. {3,4},{4,9},{8,0},{2,3},{5,6},{2,9},
  12. {5,9},{7,3},{4,8},{5,6},{0,2},{6,1}
  13. };
  14. System.out.println(Arrays.toString(id));
  15. for(int[]s:a){
  16. inti,j,p=s[0],q=s[1];
  17. for(i=p;i!=id[i];i=id[i]){
  18. id[i]=id[id[i]];
  19. }
  20. for(j=q;j!=id[j];j=id[j]){
  21. id[j]=id[id[j]];
  22. }
  23. if(i==j){
  24. continue;
  25. }
  26. if(sz[i]<sz[j]){
  27. id[i]=j;
  28. sz[j]+=sz[i];
  29. }else{
  30. id[j]=i;
  31. sz[i]+=sz[j];
  32. }
  33. System.out.println(""+p+""+q);
  34. System.out.println(Arrays.toString(id));
  35. System.out.println(Arrays.toString(sz));
  36. }
  37. }
  38. }

得到的与例三一样的净结果,比全路径压缩算法更简单。

通过一系列的算法:找到了解决实际问题的好算法,它比较容易实现,且运行实际保证在收集数据项所花费时间的常数因子范围内。在这些算法中需要仔细和复杂的分析,才能找到最优算法。

你可能感兴趣的:(java算法)