《算法》第五章部分程序 part 4

? 书中第五章部分程序,包括在加上自己补充的代码,Trie 树类,Trie 集合,三值搜索树(Ternary Search Trie)

● Trie 树类

  1 package package01;
  2
  3 import edu.princeton.cs.algs4.StdIn;
  4 import edu.princeton.cs.algs4.StdOut;
  5 import edu.princeton.cs.algs4.Queue;
  6
  7 public class class01<Value>
  8 {
  9     private static final int R = 256;   // 扩展 ASCII
 10
 11     private Node root;
 12     private int n;                      // 总节点数
 13
 14     private static class Node           // 节点类,含当前节点代表的值,以及 R 路支链
 15     {
 16         private Object val;
 17         private Node[] next = new Node[R];
 18     }
 19
 20     public class01() {}
 21
 22     public boolean contains(String key)
 23     {
 24         if (key == null)
 25             throw new IllegalArgumentException("\n<contains> key == null.\n");
 26         return get(key) != null;
 27     }
 28
 29     public Value get(String key)
 30     {
 31         if (key == null)
 32             throw new IllegalArgumentException("\n<get> key == null.\n");
 33         Node x = getKernel(root, key, 0);
 34         return (x == null) ? null : (Value)x.val;       // 找到了就返回,没找到返回 null
 35     }
 36
 37     private Node getKernel(Node x, String key, int d)   // 注意返回的是节点,与 get 不同
 38     {
 39         if (x == null)                                  // 先判断当前节点是否为空,再判断是否到达搜索终点,然后考虑递归
 40             return null;
 41         if (d == key.length())
 42             return x;
 43         return getKernel(x.next[key.charAt(d)], key, d + 1);
 44     }
 45
 46     public void put(String key, Value val)
 47     {
 48         if (key == null)
 49             throw new IllegalArgumentException("\n<put> key == null.\n");
 50         if (val == null)
 51             delete(key);
 52         else
 53             root = putKernel(root, key, val, 0);
 54     }
 55
 56     private Node putKernel(Node x, String key, Value val, int d)
 57     {
 58         if (x == null)                  // 先判断当前节点是否为空,再判断是否到达搜索终点,然后考虑递归
 59             x = new Node();
 60         if (d == key.length())
 61         {
 62             if (x.val == null)          // 节点为空,节点数 +1
 63                 n++;
 64             x.val = val;                // 赋上新值
 65         }
 66         else
 67         {
 68             char c = key.charAt(d);
 69             x.next[c] = putKernel(x.next[c], key, val, d + 1);
 70         }
 71         return x;
 72     }
 73
 74     public int size()
 75     {
 76         return n;
 77     }
 78
 79     public boolean isEmpty()
 80     {
 81         return size() == 0;
 82     }
 83
 84     public Iterable<String> keys()                              // 生成所有键的迭代器(遍历)
 85     {
 86         return keyPrefix("");
 87     }
 88
 89     public Iterable<String> keyPrefix(String prefix)            // 生成具有给定前缀的所有键的迭代器
 90     {
 91         Queue<String> results = new Queue<String>();
 92         Node x = getKernel(root, prefix, 0);                    // 先抵达前缀结束时的搜索节点
 93         collectPrefix(x, new StringBuilder(prefix), results);   // 在此基础上遍历并放入迭代器
 94         return results;
 95     }
 96
 97     private void collectPrefix(Node x, StringBuilder prefix, Queue<String> results)   // 遍历 x 为根节点的表,prefix 用来生成结果的,不参与遍历
 98     {
 99         if (x == null)
100             return;
101         if (x.val != null)
102             results.enqueue(prefix.toString());                 // 除了给定前缀,没有多余字符的情况
103         for (char c = 0; c < R; c++)                            // 每次循环尝试添加一个字符,遍历子节点,然后删掉
104         {
105             prefix.append(c);
106             collectPrefix(x.next[c], prefix, results);
107             prefix.deleteCharAt(prefix.length() - 1);
108         }
109     }
110
111     public Iterable<String> keyPattern(String pattern)          // 生成具有给定模式的所有键的迭代器
112     {
113         Queue<String> results = new Queue<String>();
114         collectPattern(root, new StringBuilder(), pattern, results);
115         return results;
116     }
117
118     private void collectPattern(Node x, StringBuilder prefix, String pattern, Queue<String> results)
119     {
120         if (x == null)
121             return;
122         int d = prefix.length();
123         if (d == pattern.length())                              // 已经到了模式的尽头
124         {
125             if (x.val != null)
126                 results.enqueue(prefix.toString());
127             return;
128         }
129         char c = pattern.charAt(d);
130         if (c == ‘.‘)
131         {
132             for (char ch = 0; ch < R; ch++)                     // 模式是 ‘.‘,像 collectPrefix 那样尝试添加每一个字符来遍历子节点,然后删掉
133             {
134                 prefix.append(ch);
135                 collectPattern(x.next[ch], prefix, pattern, results);
136                 prefix.deleteCharAt(prefix.length() - 1);
137             }
138         }
139         else                                                    // 否则只添加确定的字符,遍历其子节点,之后也要删掉
140         {
141             prefix.append(c);
142             collectPattern(x.next[c], prefix, pattern, results);
143             prefix.deleteCharAt(prefix.length() - 1);
144         }
145     }
146
147     public String longestPrefixOf(String query)                 // 找出与给定串有相同前缀的键的最大长度
148     {
149         if (query == null)
150             throw new IllegalArgumentException("\n<longestPrefixOf> query == null.\n");
151         int length = longestPrefixOfKernel(root, query, 0, -1);
152         if (length == -1)
153             return null;
154         return query.substring(0, length);
155     }
156
157     private int longestPrefixOfKernel(Node x, String query, int d, int length)
158     {
159         if (x == null)
160             return length;
161         if (x.val != null)
162             length = d;
163         if (d == query.length())
164             return length;
165         return longestPrefixOfKernel(x.next[query.charAt(d)], query, d + 1, length);
166     }
167
168     public void delete(String key)
169     {
170         if (key == null)
171             throw new IllegalArgumentException("\n<delete> key == null.\n");
172         root = deleteKernel(root, key, 0);
173     }
174
175     private Node deleteKernel(Node x, String key, int d)        // 删除节点
176     {
177         if (x == null)
178             return null;
179         if (d == key.length())                                  // 到达对应深度
180         {
181             if (x.val != null)                                  // 目标节点存在,总结点数 -1
182                 n--;
183             x.val = null;
184         }
185         else                                                    // 还没达到对应深度,继续下潜
186         {
187             char c = key.charAt(d);
188             x.next[c] = deleteKernel(x.next[c], key, d + 1);
189         }
190         if (x.val != null)                                      // 返回途中,发现盖层 x 还没有被删,返回 x
191             return x;
192         for (int c = 0; c < R; c++)                             // x 已经被删,但是 x 还有子节点
193         {
194             if (x.next[c] != null)
195                 return x;
196         }
197         return null;                                            // x 已经被删,且没有子节点,返回 null
198     }
199
200     public static void main(String[] args)
201     {
202         class01<Integer> st = new class01<Integer>();
203         for (int i = 0; !StdIn.isEmpty(); i++)                  // 输入键
204             st.put(StdIn.readString(), i);
205         if (st.size() < 100)                                    // 输出保存的键
206         {
207             StdOut.println("keys(\"\"):");
208             for (String key : st.keys())
209                 StdOut.println(key + " " + st.get(key));
210             StdOut.println();
211         }
212
213         StdOut.println("longestPrefixOf(\"shellsort\"):");
214         StdOut.println(st.longestPrefixOf("shellsort"));
215         StdOut.println();
216
217         StdOut.println("longestPrefixOf(\"quicksort\"):");
218         StdOut.println(st.longestPrefixOf("quicksort"));
219         StdOut.println();
220
221         StdOut.println("keyPrefix(\"shor\"):");
222         for (String s : st.keyPrefix("shor"))
223             StdOut.println(s);
224         StdOut.println();
225
226         StdOut.println("keyPattern(\".he.l.\"):");
227         for (String s : st.keyPattern(".he.l."))
228             StdOut.println(s);
229     }
230 }

● Trie 集合

  1 package package01;
  2
  3 import java.util.Iterator;
  4 import edu.princeton.cs.algs4.StdIn;
  5 import edu.princeton.cs.algs4.StdOut;
  6 import edu.princeton.cs.algs4.Queue;
  7
  8 public class class01 implements Iterable<String>// 需要 string 的迭代器
  9 {
 10     private static final int R = 256;
 11
 12     private Node root;
 13     private int n;
 14
 15     private static class Node
 16     {
 17         private boolean isString;          // 是否存在以当前节点为结尾的键
 18         private Node[] next = new Node[R];
 19     }
 20
 21     public class01() {}
 22
 23     public boolean contains(String key)
 24     {
 25         if (key == null)
 26             throw new IllegalArgumentException("\n<contains> key == null.\n");
 27         Node x = get(root, key, 0);
 28         return (x == null) ? false : x.isString;// 是否为空的判断方式不同
 29     }
 30
 31     private Node get(Node x, String key, int d) // 没有 get 和 getKernel 的区分
 32     {
 33         if (x == null)
 34             return null;
 35         if (d == key.length())
 36             return x;
 37         return get(x.next[key.charAt(d)], key, d + 1);
 38     }
 39
 40     public void put(String key)// 少了 val 参数
 41     {
 42         if (key == null)
 43             throw new IllegalArgumentException("\n<put> key == null.\n");
 44         root = putKernel(root, key, 0);
 45     }
 46
 47     private Node putKernel(Node x, String key, int d)
 48     {
 49         if (x == null)
 50             x = new Node();
 51         if (d == key.length())
 52         {
 53             if (!x.isString) // 是否为空的判断条件不同
 54                 n++;
 55             x.isString = true;
 56         }
 57         else
 58         {
 59             char c = key.charAt(d);
 60             x.next[c] = putKernel(x.next[c], key, d + 1);
 61         }
 62         return x;
 63     }
 64
 65     public int size()
 66     {
 67         return n;
 68     }
 69
 70     public boolean isEmpty()
 71     {
 72         return size() == 0;
 73     }
 74
 75     public Iterator<String> iterator() // 不是 Iterable,Iterator
 76     {
 77         return keyPrefix("").iterator();
 78     }
 79
 80     public Iterable<String> keyPrefix(String prefix)
 81     {
 82         Queue<String> results = new Queue<String>();
 83         Node x = get(root, prefix, 0);
 84         collectPrefix(x, new StringBuilder(prefix), results);
 85         return results;
 86     }
 87
 88     private void collectPrefix(Node x, StringBuilder prefix, Queue<String> results)
 89     {
 90         if (x == null)
 91             return;
 92         if (x.isString)
 93             results.enqueue(prefix.toString());
 94         for (char c = 0; c < R; c++)
 95         {
 96             prefix.append(c);
 97             collectPrefix(x.next[c], prefix, results);
 98             prefix.deleteCharAt(prefix.length() - 1);
 99         }
100     }
101
102     public Iterable<String> keyPattern(String pattern)
103     {
104         Queue<String> results = new Queue<String>();
105         collectPattern(root, new StringBuilder(), pattern, results);
106         return results;
107     }
108
109     private void collectPattern(Node x, StringBuilder prefix, String pattern, Queue<String> results)
110     {
111         if (x == null)
112             return;
113         int d = prefix.length();
114         if (d == pattern.length())
115         {
116             if (x.isString)
117                 results.enqueue(prefix.toString());
118             return;
119         }
120         char c = pattern.charAt(d);
121         if (c == ‘.‘)
122         {
123             for (char ch = 0; ch < R; ch++)
124             {
125                 prefix.append(ch);
126                 collectPattern(x.next[ch], prefix, pattern, results);
127                 prefix.deleteCharAt(prefix.length() - 1);
128             }
129         }
130         else
131         {
132             prefix.append(c);
133             collectPattern(x.next[c], prefix, pattern, results);
134             prefix.deleteCharAt(prefix.length() - 1);
135         }
136     }
137
138     public String longestPrefixOf(String query)
139     {
140         if (query == null)
141             throw new IllegalArgumentException("\n<longestPrefixOf> query == null.\n");
142         int length = longestPrefixOfKernel(root, query, 0, -1);
143         if (length == -1)
144             return null;
145         return query.substring(0, length);
146     }
147
148     private int longestPrefixOfKernel(Node x, String query, int d, int length)
149     {
150         if (x == null)
151             return length;
152         if (x.isString)
153             length = d;
154         if (d == query.length())
155             return length;
156         return longestPrefixOfKernel(x.next[query.charAt(d)], query, d+1, length);
157     }
158
159     public void delete(String key)
160     {
161         if (key == null)
162             throw new IllegalArgumentException("\n<delete> key == null.\n");
163         root = deleteKernel(root, key, 0);
164     }
165
166     private Node deleteKernel(Node x, String key, int d)
167     {
168         if (x == null)
169             return null;
170         if (d == key.length())
171         {
172             if (x.isString)
173                 n--;
174             x.isString = false;
175         }
176         else
177         {
178             char c = key.charAt(d);
179             x.next[c] = deleteKernel(x.next[c], key, d+1);
180         }
181         if (x.isString)
182             return x;
183         for (int c = 0; c < R; c++)
184         {
185             if (x.next[c] != null)
186                 return x;
187         }
188         return null;
189     }
190
191     public static void main(String[] args)
192     {
193         class01 st = new class01();
194         for (; !StdIn.isEmpty(); st.put(StdIn.readString()));
195         if (st.size() < 100)
196         {
197             StdOut.println("keys(\"\"):");
198             for (String key : st)
199                 StdOut.println(key);
200             StdOut.println();
201         }
202
203         StdOut.println("longestPrefixOf(\"shellsort\"):");
204         StdOut.println(st.longestPrefixOf("shellsort"));
205         StdOut.println();
206
207         StdOut.println("longestPrefixOf(\"xshellsort\"):");
208         StdOut.println(st.longestPrefixOf("xshellsort"));
209         StdOut.println();
210
211         StdOut.println("keyPrefix(\"shor\"):");
212         for (String s : st.keyPrefix("shor"))
213             StdOut.println(s);
214         StdOut.println();
215
216         StdOut.println("keyPrefix(\"shortening\"):");
217         for (String s : st.keyPrefix("shortening"))
218             StdOut.println(s);
219         StdOut.println();
220
221         StdOut.println("keyPattern(\".he.l.\"):");
222         for (String s : st.keyPattern(".he.l."))
223             StdOut.println(s);
224     }
225 }

● 三值搜索树

  1 package package01;
  2
  3 import edu.princeton.cs.algs4.StdIn;
  4 import edu.princeton.cs.algs4.StdOut;
  5 import edu.princeton.cs.algs4.Queue;
  6
  7 public class class01<Value>
  8 {
  9     private Node<Value> root;
 10     private int n;
 11
 12     private static class Node<Value>
 13     {
 14         private char c;
 15         private Node<Value> left, mid, right;
 16         private Value val;
 17     }
 18
 19     public class01() {}
 20
 21     public boolean contains(String key)
 22     {
 23         if (key == null)
 24             throw new IllegalArgumentException("\n<contains> key == null.\n");
 25         return get(key) != null;
 26     }
 27
 28     public Value get(String key)
 29     {
 30         if (key == null || key.length() == 0)
 31             throw new IllegalArgumentException("\n<get> key == null || key.length() == 0.\n");
 32         Node<Value> x = getKernel(root, key, 0);
 33         return (x == null) ? null : x.val;
 34     }
 35
 36     private Node<Value> getKernel(Node<Value> x, String key, int d)
 37     {
 38         if (x == null)
 39             return null;
 40         char c = key.charAt(d);
 41         if (c < x.c)
 42             return getKernel(x.left, key, d);       // 向左右搜索的时候深度不变
 43         if (c > x.c)
 44             return getKernel(x.right, key, d);
 45         if (d < key.length() - 1)
 46             return getKernel(x.mid, key, d + 1);    // 向中路搜索的时候深度要变化
 47         return x;
 48     }
 49
 50     public void put(String key, Value val)
 51     {
 52         if (key == null)
 53             throw new IllegalArgumentException("\n<put> key == null.\n");
 54         if (!contains(key))
 55             n++;
 56         root = putKernel(root, key, val, 0);
 57     }
 58
 59     private Node<Value> putKernel(Node<Value> x, String key, Value val, int d)
 60     {
 61         char c = key.charAt(d);
 62         if (x == null)
 63         {
 64             x = new Node<Value>();
 65             x.c = c;
 66         }
 67         if (c < x.c)
 68             x.left = putKernel(x.left, key, val, d);
 69         else if (c > x.c)
 70             x.right = putKernel(x.right, key, val, d);
 71         else if (d < key.length() - 1)
 72             x.mid = putKernel(x.mid, key, val, d + 1);
 73         else
 74             x.val = val;
 75         return x;
 76     }
 77
 78     public int size()
 79     {
 80         return n;
 81     }
 82
 83     public boolean isEmpty()
 84     {
 85         return size() == 0;
 86     }
 87
 88     public Iterable<String> keys()  // 需要直接从前缀中去字符参加比较,不能用 keyPrefix("")
 89     {
 90         Queue<String> queue = new Queue<String>();
 91         collectPrefix(root, new StringBuilder(), queue);
 92         return queue;
 93     }
 94
 95     public Iterable<String> keyPrefix(String prefix)
 96     {
 97         Queue<String> queue = new Queue<String>();
 98         Node<Value> x = getKernel(root, prefix, 0);
 99         if (x == null)
100             return queue;
101         if (x.val != null)
102             queue.enqueue(prefix);
103         collectPrefix(x.mid, new StringBuilder(prefix), queue);
104         return queue;
105     }
106
107     private void collectPrefix(Node<Value> x, StringBuilder prefix, Queue<String> queue)
108     {
109         if (x == null)
110             return;
111         collectPrefix(x.left, prefix, queue);
112         if (x.val != null)
113             queue.enqueue(prefix.toString() + x.c);
114         collectPrefix(x.mid, prefix.append(x.c), queue);
115         prefix.deleteCharAt(prefix.length() - 1);
116         collectPrefix(x.right, prefix, queue);
117     }
118
119     public Iterable<String> keyPattern(String pattern)
120     {
121         Queue<String> queue = new Queue<String>();
122         collectPattern(root, new StringBuilder(), 0, pattern, queue);
123         return queue;
124     }
125
126     private void collectPattern(Node<Value> x, StringBuilder prefix, int i, String pattern, Queue<String> queue)
127     {
128         if (x == null)
129             return;
130         char c = pattern.charAt(i);
131         if (c == ‘.‘ || c < x.c)                                // 分解为 c 和 x.c 的三种情况,插上 ‘.‘ 的情况
132             collectPattern(x.left, prefix, i, pattern, queue);
133         if (c == ‘.‘ || c == x.c)
134         {
135             if (i == pattern.length() - 1 && x.val != null)
136                 queue.enqueue(prefix.toString() + x.c);
137             if (i < pattern.length() - 1)
138             {
139                 collectPattern(x.mid, prefix.append(x.c), i + 1, pattern, queue);
140                 prefix.deleteCharAt(prefix.length() - 1);
141             }
142         }
143         if (c == ‘.‘ || c > x.c)
144             collectPattern(x.right, prefix, i, pattern, queue);
145     }
146
147     public String longestPrefixOf(String query)
148     {
149         if (query == null || query.length() == 0)
150             throw new IllegalArgumentException("\n<longestPrefixOf> query == null || query.length() == 0.\n");
151         int length = 0;
152         Node<Value> x = root;
153         for (int i = 0; x != null && i < query.length();)       // i 为当前匹配的长度
154         {
155             char c = query.charAt(i);
156             if (c < x.c)
157                 x = x.left;
158             else if (c > x.c)
159                 x = x.right;
160             else
161             {
162                 i++;
163                 if (x.val != null)
164                     length = i;
165                 x = x.mid;
166             }
167         }
168         return query.substring(0, length);
169     }
170
171     public static void main(String[] args)
172     {
173         class01<Integer> st = new class01<Integer>();
174         for (int i = 0; !StdIn.isEmpty(); i++)
175         {
176             String key = StdIn.readString();
177             st.put(key, i);
178         }
179
180         if (st.size() < 100)
181         {
182             StdOut.println("keys(\"\"):");
183             for (String key : st.keys())
184                 StdOut.println(key + " " + st.get(key));
185             StdOut.println();
186         }
187
188         StdOut.println("longestPrefixOf(\"shellsort\"):");
189         StdOut.println(st.longestPrefixOf("shellsort"));
190         StdOut.println();
191
192         StdOut.println("longestPrefixOf(\"shell\"):");
193         StdOut.println(st.longestPrefixOf("shell"));
194         StdOut.println();
195
196         StdOut.println("keysWithPrefix(\"shor\"):");
197         for (String s : st.keyPrefix("shor"))
198             StdOut.println(s);
199         StdOut.println();
200
201         StdOut.println("keysThatMatch(\".he.l.\"):");
202         for (String s : st.keyPattern(".he.l."))
203             StdOut.println(s);
204     }
205 }

原文地址:https://www.cnblogs.com/cuancuancuanhao/p/9869294.html

时间: 2024-08-22 23:17:56

《算法》第五章部分程序 part 4的相关文章

《算法》第五章部分程序 part 2

? 书中第五章部分程序,包括在加上自己补充的代码,字符串高位优先排序(计数 + 插排),(原地排序),(三路快排,与前面的三路归并排序相同) ● 计数 + 插排 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 static final int BITS_PER_BY

《算法》第五章部分程序 part 1

? 书中第五章部分程序,包括在加上自己补充的代码,字母表类,字符串低位优先排序(桶排) ● 字母表类 1 package package01; 2 3 import edu.princeton.cs.algs4.StdOut; 4 5 public class class01 6 { 7 public static final class01 BINARY = new class01("01"); 8 9 public static final class01 OCTAL = new

《算法》第五章部分程序 part 3

? 书中第五章部分程序,包括在加上自己补充的代码,字符串高位优先排序(美国国旗排序) ● 美国国旗排序 1 package package01; 2 3 import edu.princeton.cs.algs4.StdIn; 4 import edu.princeton.cs.algs4.StdOut; 5 import edu.princeton.cs.algs4.Stack; 6 7 public class class01 8 { 9 private static final int B

Gradle 1.12用户指南翻译——第四十五章. 应用程序插件

文由CSDN博客貌似掉线翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Github上的地址: https://github.com/msdx/gradledoc 本文翻译所在分支: https://github.com/msdx/gradledoc/tree/1.12. 直接浏览双语版的文档请访问: http://gradledoc.qiniudn.com/1.12/usergu

《算法》第一章部分程序

? 书中第一章部分程序,加上自己补充的代码.包括若干种二分搜索和寻找图上连通分量数的两种算法. ● 代码,二分搜索 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

第五章 C程序结构

一.数值类型 1.实数常量的表示:3.5(双精度),3.5f(单精度),3.5L(长双精度) 2.整数常量:char字符常量('a','b','0')当做一个整型常量参加运算 3.数字字符与英文字母字符的编号(Ascll码)都是顺序连接的 二.控制语句 1.while和do while的区别:当while条件不成立时,while()循环不执行循环语句,而do while会循环执行一次循环语句再判断 2.流程控制语句:continue(中断本次循环)    break(跳出整个循环) 3.开关语句

算法第五章小结

一.回溯算法的概念以及理解 概念:回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标. 理解:在回溯法中,每次扩大当前部分解时,都面临一个可选的状态集合,新的部分解就通过在该集合中选择构造而成.这样的状态集合,其结构是一棵多叉树,每个树结点代表一个可能的部分解,它的儿子是在它的基础上生成的其他部分解.树根为初始状态,这样的状态集合称为状态空间树. 二.“子集和”问题的解空间结构和约束函数 1.解空间结构 非负非零的整数集合 S = {x1, x2, …, xn}

算法第五章上机实践报告

一 . 实践题目 7-2 工作分配问题 二 . 问题描述 设有n件工作分配给n个人.将工作i分配给第j个人所需的费用为cij . 设计一个算法,对于给定的工作费用,为每一个人都分配1 件不同的工作,并使总费用达到最小. 输入格式: 输入数据的第一行有1 个正整数n (1≤n≤20).接下来的n行,每行n个数,表示工作费用. 输出格式: 将计算出的最小总费用输出到屏幕. 输入样例: 3 10 2 3 2 3 4 3 4 5 输出样例: 9 三 . 算法描述 1. 解空间 第一个人选择第几个工作,第

算法第五章 | 回溯算法

一. 回溯算法 回溯法有"通用的解题法"之称.可以系统地搜索一个问题的所有解或任一解,是一个既带有系统性又带有跳跃性的搜索算法. 它在问题的解空间树中,按深度优先策略,从根节点出发搜索解空间树.算法搜索至解空间树的任一结点时,先判断该结点是否包含问题的解.如果肯定不包含,则跳过对以该结点为根的子树的搜索,逐层向其祖先结点回溯.否则,进入该子树,继续按深度优先策略搜索.回溯法求问题的所有解时,要回溯到根,且根结点的所有子树都已被搜索遍才结束.回溯法求问题的一个解时,只要搜索到问题的一个解