《算法》第一章部分程序
2021-05-15 15:30
标签:ati throw and roo pack port 合并 date connect ? 书中第一章部分程序,加上自己补充的代码。包括若干种二分搜索和寻找图上连通分量数的两种算法。 ● 代码,二分搜索 ● 重复元素二分搜索,包括查找第一次出现、最后一次出现,以及出现多少次 ● 序列乱序输出 ● 计算图连通分量的算法。输入文件第一行是节点数,后面每行是一个连接的两端节点编号,用 java class01
《算法》第一章部分程序 标签:ati throw and roo pack port 合并 date connect 原文地址:https://www.cnblogs.com/cuancuancuanhao/p/9748440.html 1 package package01;
2
3 import java.util.Arrays;
4 import edu.princeton.cs.algs4.StdRandom;
5
6 public class class01
7 {
8 public int binarySearch(int [] a, int target) // 非递归实现
9 {
10 int lp = 0, rp = a.length - 1;
11 for(;lp // 含等号的条件,后面修改 lp 和 rp 是使用强的跳跃条件
12 {
13 int mp = lp + (rp - lp) / 2;
14 if (target a[mp])
15 rp = mp - 1; // 不要使用 mp 作为跳跃条件,会导致死循环
16 else if (target > a[mp])
17 lp = mp + 1;
18 else
19 return mp;
20 }
21 return -1;
22 }
23
24 public int binarySearchRecursion(int [] a, int target)// 递归实现
25 {
26 return binarySearchRecursionKernel(a,target,0,a.length-1);
27 }
28
29 private int binarySearchRecursionKernel(int [] a, int target, int lp, int rp)
30 {
31 for(;lprp;)
32 {
33 int mp = lp + (rp - lp) / 2;
34 if (target a[mp])
35 return binarySearchRecursionKernel(a,target,lp,mp - 1);
36 else if (target > a[mp])
37 return binarySearchRecursionKernel(a,target,mp + 1, rp);
38 else
39 return mp;
40 }
41 return -1;
42 }
43
44 public static void main(String[] args)
45 {
46 int N = 10000;
47 int [] a = new int [N];
48 for(int i=0;i
1 package package01;
2
3 import java.util.Arrays;
4 import edu.princeton.cs.algs4.StdRandom;
5
6 public class class01
7 {
8 public int binarySearchFirst(int [] a, int target) // 寻找第一个等于键值的目标
9 {
10 return binarySearchFirstKernel(a, target, 0, a.length-1);
11 }
12
13 private int binarySearchFirstKernel(int [] a, int target,int lp,int rp) // 添加起点和终点(两端点都包含),为了能与 Count 函数配合
14 {
15 for(;lprp;)
16 {
17 int mp = lp + (rp - lp) / 2;
18 if (target a[mp])
19 rp = mp - 1;
20 else if (target > a[mp])
21 lp = mp + 1;
22 else if(mp == 0 || target > a[mp-1]) // target == a[mp],找第一个
23 return mp; // a[mp] 就是第一个
24 else // a[mp] 前面还有等值的,不能强跳跃,否则可能跨空
25 rp = mp;
26 }
27 return -1;
28 }
29
30 public int binarySearchLast(int [] a, int target) // 寻找最后一个等于键值的目标
31 {
32 return binarySearchLastKernel(a,target, 0, a.length-1);
33 }
34
35 private int binarySearchLastKernel(int [] a, int target,int lp, int rp) // 添加起点和终点(两端点都包含)
36 {
37 for(;lprp;)
38 {
39 int mp = lp + (rp - lp) / 2;
40 if (target a[mp])
41 rp = mp - 1;
42 else if (target > a[mp])
43 lp = mp + 1;
44 else if(mp == a.length-1 || target // target == a[mp],找最后一个
45 return mp; // a[mp] 就是第一个
46 else // a[mp] 后面还有等值的,不能强跳跃,否则可能跨空
47 lp = mp;
48 }
49 return -1;
50 }
51
52 public int binarySearchCount(int [] a, int target) // 寻找等于键值的元素个数
53 {
54 int lp = 0, rp = a.length-1;
55 for(;lprp;)
56 {
57 int mp = lp + (rp - lp) / 2;
58 if (target a[mp])
59 rp = mp - 1;
60 else if (target > a[mp])
61 lp = mp + 1;
62 else // 找到元素后,搜查首个和最后一个进行计数
63 return binarySearchLastKernel(a,target,lp,rp) - binarySearchFirstKernel(a,target,lp,rp) + 1;
64 }
65 return -1;
66 }
67
68 public static void main(String[] args)
69 {
70 int N = 10000;
71 int [] a = new int [N];
72 for(int i=0;i
1 package package01;
2
3 public class class01
4 {
5 public static void shuffle(Object[] a)
6 {
7 int n = a.length;
8 for (int i = 0; i // 每次在 a[0] ~ a[i] 中随机挑一个 a[r],交换 a[i] 与a[r]
9 {
10 int r = (int)(Math.random() * (i + 1));
11 Object swap = a[r];
12 a[r] = a[i];
13 a[i] = swap;
14 }
15 }
16
17 public static void shuffle2(Object[] a)
18 {
19 int n = a.length;
20 for (int i = 0; i // 每次在 a[i] 右边随机挑一个 a[r],交换 a[i] 与a[r]
21 {
22 int r = i + (int)(Math.random() * (n - i));
23 Object swap = a[r];
24 a[r] = a[i];
25 a[i] = swap;
26 }
27 }
28
29 public static void main(String[] args)
30 {
31 String[] a = { "0","1","2","3","4","5","6","7","8","9" };
32 class01.shuffle(a);
33 for (int i = 0; i )
34 System.out.print(a[i]);
35
36 System.out.print("\n");
37
38 String[] b = { "0","1","2","3","4","5","6","7","8","9" };
39 class01.shuffle2(b);
40 for (int i = 0; i )
41 System.out.print(b[i]);
42
43 return;
44 }
45 }
1 package package01;
2
3 import edu.princeton.cs.algs4.StdIn;
4 import edu.princeton.cs.algs4.StdOut;
5
6 public class class01
7 {
8 private int[] parent; // 节点祖先标记
9 private int[] rank; // 树深度,仅根节点有效
10 private int count; // 节点数
11
12 public class01(int n)
13 {
14 count = n;
15 parent = new int[n];
16 rank = new int[n];
17 for (int i = 0; i )
18 {
19 parent[i] = i;
20 rank[i] = 1; // 源代码用的是 0
21 }
22 }
23
24 public int find(int p) // 寻找 p 的根标号
25 {
26 for (validate(p); p != parent[p]; p = parent[p]);
27 return p;
28 }
29
30 public int count() // 节点数
31 {
32 return count;
33 }
34
35 public boolean connected(int p, int q) // 判断 p 与 q 是否连通
36 {
37 return find(p) == find(q);
38 }
39
40 public void union(int p, int q) // 合并 p 和 q
41 {
42 int rootP = find(p);
43 int rootQ = find(q);
44 if (rootP == rootQ)
45 return;
46
47 if (rank[rootP] // 较小树连接到较大树的树根上,树高按最大值计算
48 parent[rootP] = rootQ;
49 else if (rank[rootP] > rank[rootQ])
50 parent[rootQ] = rootP;
51 else // 两树等大,合并后树高增一
52 {
53 parent[rootQ] = rootP;
54 rank[rootP]++;
55 }
56 count--; // 合并后连接分量减少
57 }
58
59 public void union2(int p, int q) // 合并 p 和 q,第二种方法,更快
60 {
61 int rootP = find(p);
62 int rootQ = find(q);
63 if (rootP == rootQ)
64 return;
65
66 if (rank[rootP] rank[rootQ])
67 {
68 parent[rootP] = rootQ;
69 rank[rootQ] += rank[rootP]; // 树高按加和计算
70 }
71 else
72 {
73 parent[rootQ] = rootP;
74 rank[rootP] += rank[rootQ];
75 }
76 count--;
77 }
78
79 private void validate(int p) // 判断输入的 p 是否合法
80 {
81 if (p = parent.length)
82 throw new IllegalArgumentException("\np = " + p + "is illegal\n");
83 }
84
85 public static void main(String[] args)
86 {
87 int n = StdIn.readInt();
88 class01 uf = new class01(n);
89 for (; !StdIn.isEmpty();)
90 {
91 int p = StdIn.readInt();
92 int q = StdIn.readInt();
93 if (uf.connected(p, q))
94 continue;
95 uf.union(p, q);
96 //StdOut.println(p + " " + q);
97 }
98 StdOut.println(uf.count() + " components");
99 }
100 }