├── README.md
├── chapter8-disjoint-set.cpp
├── chapter6-bubble-sort.cpp
├── chapter6-selection-sort.cpp
├── chapter6-insertion-sort.cpp
├── chapter6-shell-sort.cpp
├── chapter6-bucket-sort.cpp
├── chapter3-stack.cpp
├── chapter3-queue.cpp
├── chapter10-primality-testing.cpp
├── chapter6-merge-sort.cpp
├── chapter6-radix-sort.cpp
├── chapter10-ordering-matrix-multiplication.cpp
├── chapter9-topological-sort.cpp
├── chapter6-heap-sort.cpp
├── chapter9-unweighted-shortest-path.cpp
├── chapter9-all-pairs-shortest-path.cpp
├── chapter6-quick-sort.cpp
├── chapter9-weighted-shortest-path.cpp
├── chapter10-a-simple-nim.cpp
├── chapter4-binary-tree.cpp
├── chapter9-prims-algorithm.cpp
├── chapter9-cut-vertices.cpp
├── chapter9-kruskals-algorithm.cpp
├── chapter3-singly-linked-list.cpp
├── chapter10-turnpike-reconstrution.cpp
├── chapter10-closest-pair-of-points.cpp
├── chapter10-huffman-encoding.cpp
├── chapter3-doubly-linked-list.cpp
├── chapter7-hash-map.cpp
├── chapter5-priority-queue.cpp
├── chapter9-maximum-flow.cpp
├── chapter10-minimax-game-strategy.cpp
├── chapter7-hash-set.cpp
├── chapter10-strassen-algorithm.cpp
├── chapter10-skip-list.cpp
├── chapter10-alpha-beta-pruning.cpp
├── chapter4-binary-search-tree.cpp
├── chapter4-splay-tree.cpp
└── chapter4-avl-tree.cpp
/README.md:
--------------------------------------------------------------------------------
1 | Data-Structures-and-Algorithm-Analysis-in-C
2 | ===========================================
3 |
4 | A good textbook by Mark Allen Weiss.
5 | -------------------------------------------
6 | I decide to make a review on this book and implement the data structures myself.
7 | Reinventing a wheel is important training, especially for those who design a car.
8 | Digesting CLRS might be too time-consuming, and inappropriate for a job-seeker like me.
9 | This book will be a proper substitute.
10 | Timestamp: 1399952708
11 |
--------------------------------------------------------------------------------
/chapter8-disjoint-set.cpp:
--------------------------------------------------------------------------------
1 | // My implementation for disjoint set.
2 | #include
3 | using namespace std;
4 |
5 | int findRoot(const vector &dj, int x)
6 | {
7 | int k, r;
8 |
9 | r = x;
10 | while (r != dj[r]) {
11 | r = dj[r];
12 | }
13 |
14 | k = x;
15 | while (k != r) {
16 | x = dj[x];
17 | dj[k] = r;
18 | k = x;
19 | }
20 |
21 | return r;
22 | }
23 |
24 | void unionSet(vector &dj, int x, int y)
25 | {
26 | int n = (int)dj.size();
27 |
28 | if (x == y) {
29 | return;
30 | }
31 |
32 | dj[x] = y;
33 | findRoot(x);
34 | }
35 |
36 | int main()
37 | {
38 | return 0;
39 | }
--------------------------------------------------------------------------------
/chapter6-bubble-sort.cpp:
--------------------------------------------------------------------------------
1 | // My implementation for bubble sort.
2 | #include
3 | #include
4 | using namespace std;
5 |
6 | void bubbleSort(vector &v)
7 | {
8 | int n, i, j;
9 | int val;
10 |
11 | n = (int)v.size();
12 | for (i = 0; i < n; ++i) {
13 | for (j = n - 1; j > i; --j) {
14 | if (v[j - 1] > v[j]) {
15 | val = v[j - 1];
16 | v[j - 1] = v[j];
17 | v[j] = val;
18 | }
19 | }
20 | }
21 | }
22 |
23 | int main()
24 | {
25 | vector v;
26 | int n, i;
27 |
28 | while (cin >> n && n > 0) {
29 | v.resize(n);
30 | for (i = 0; i < n; ++i) {
31 | cin >> v[i];
32 | }
33 | bubbleSort(v);
34 | for (i = 0; i < n; ++i) {
35 | cout << v[i] << ' ';
36 | }
37 | cout << endl;
38 | }
39 |
40 | return 0;
41 | }
--------------------------------------------------------------------------------
/chapter6-selection-sort.cpp:
--------------------------------------------------------------------------------
1 | // My implementation for selection sort.
2 | #include
3 | #include
4 | using namespace std;
5 |
6 | void selectionSort(vector &v)
7 | {
8 | int n, i, j;
9 | int val;
10 |
11 | n = (int)v.size();
12 | for (i = 0; i < n; ++i) {
13 | for (j = i + 1; j < n; ++j) {
14 | if (v[i] > v[j]) {
15 | val = v[i];
16 | v[i] = v[j];
17 | v[j] = val;
18 | }
19 | }
20 | }
21 | }
22 |
23 | int main()
24 | {
25 | vector v;
26 | int n, i;
27 |
28 | while (cin >> n && n > 0) {
29 | v.resize(n);
30 | for (i = 0; i < n; ++i) {
31 | cin >> v[i];
32 | }
33 | selectionSort(v);
34 | for (i = 0; i < n; ++i) {
35 | cout << v[i] << ' ';
36 | }
37 | cout << endl;
38 | }
39 |
40 | return 0;
41 | }
--------------------------------------------------------------------------------
/chapter6-insertion-sort.cpp:
--------------------------------------------------------------------------------
1 | // My implementation for insertion sort.
2 | #include
3 | #include
4 | using namespace std;
5 |
6 | void insertionSort(vector &v)
7 | {
8 | int i, j, n;
9 | int val;
10 |
11 | n = (int)v.size();
12 | if (n <= 1) {
13 | return;
14 | }
15 |
16 | for (i = 1; i < n; ++i) {
17 | val = v[i];
18 | for (j = i - 1; j >= 0 && v[j] > val; --j) {
19 | v[j + 1] = v[j];
20 | }
21 | v[j + 1] = val;
22 | }
23 | }
24 |
25 | int main()
26 | {
27 | vector v;
28 | int n, i;
29 |
30 | while (cin >> n && n > 0) {
31 | v.resize(n);
32 | for (i = 0; i < n; ++i) {
33 | cin >> v[i];
34 | }
35 | insertionSort(v);
36 | for (i = 0; i < n; ++i) {
37 | cout << v[i] << ' ';
38 | }
39 | cout << endl;
40 | }
41 |
42 | return 0;
43 | }
--------------------------------------------------------------------------------
/chapter6-shell-sort.cpp:
--------------------------------------------------------------------------------
1 | // My implementation for shell sort.
2 | #include
3 | #include
4 | using namespace std;
5 |
6 | void shellSort(vector &v)
7 | {
8 | int n, i, j;
9 | int tmp;
10 | int increment;
11 |
12 | n = (int)v.size();
13 | for (increment = n / 2; increment > 0; increment /= 2) {
14 | for (i = increment; i < n; ++i) {
15 | tmp = v[i];
16 | for (j = i; j >= increment && v[j - increment] > tmp; j -= increment) {
17 | v[j] = v[j - increment];
18 | }
19 | v[j] = tmp;
20 | }
21 | }
22 | }
23 |
24 | int main()
25 | {
26 | vector v;
27 | int n, i;
28 |
29 | while (cin >> n && n > 0) {
30 | v.resize(n);
31 | for (i = 0; i < n; ++i) {
32 | cin >> v[i];
33 | }
34 | shellSort(v);
35 | for (i = 0; i < n; ++i) {
36 | cout << v[i] << ' ';
37 | }
38 | cout << endl;
39 | }
40 |
41 | return 0;
42 | }
--------------------------------------------------------------------------------
/chapter6-bucket-sort.cpp:
--------------------------------------------------------------------------------
1 | // My implementation for radix sort.
2 | #include
3 | #include
4 | #include
5 | using namespace std;
6 |
7 | void bucketSort(vector &v)
8 | {
9 | const int BUCKET_SIZE = 1000;
10 | const int BUCKET_NUM = 1000;
11 | vector buckets[BUCKET_NUM];
12 |
13 | int n, i, j, k;
14 |
15 | n = (int)v.size();
16 | for (i = 0; i < n; ++i) {
17 | buckets[v[i] / BUCKET_SIZE % BUCKET_NUM].push_back(v[i]);
18 | }
19 |
20 | k = 0;
21 | for (i = 0; i < BUCKET_NUM; ++i) {
22 | if (buckets[i].size() > 1) {
23 | sort(buckets[i].begin(), buckets[i].end());
24 | }
25 | for (j = 0; j < (int)buckets[i].size(); ++j) {
26 | v[k++] = buckets[i][j];
27 | }
28 | buckets[i].clear();
29 | }
30 | }
31 |
32 | int main()
33 | {
34 | vector v;
35 | int n, i;
36 |
37 | while (cin >> n && n > 0) {
38 | v.resize(n);
39 | for (i = 0; i < n; ++i) {
40 | cin >> v[i];
41 | }
42 | bucketSort(v);
43 | for (i = 0; i < n; ++i) {
44 | cout << v[i] << ' ';
45 | }
46 | cout << endl;
47 | }
48 |
49 | return 0;
50 | }
--------------------------------------------------------------------------------
/chapter3-stack.cpp:
--------------------------------------------------------------------------------
1 | // My implementation of stack.
2 | class Stack {
3 | public:
4 | Stack() {
5 | m_capacity = 1;
6 | m_size = 0;
7 | m_data = new int[m_capacity];
8 | }
9 |
10 | void push(int val) {
11 | if (m_size + 1 >= m_capacity) {
12 | resize(2 * m_capacity);
13 | }
14 | m_data[m_size++] = val;
15 | }
16 |
17 | void pop() {
18 | if (m_size > 0) {
19 | --m_size;
20 | }
21 | }
22 |
23 | int top() {
24 | return m_data[m_size - 1];
25 | }
26 |
27 | int size() {
28 | return m_size;
29 | }
30 |
31 | bool empty() {
32 | return m_size == 0;
33 | }
34 |
35 | ~Stack() {
36 | delete m_data;
37 | }
38 | private:
39 | int *m_data;
40 | int m_capacity;
41 | int m_size;
42 |
43 | void resize(int new_capacity) {
44 | if (new_capacity <= m_capacity) {
45 | return;
46 | }
47 | int *new_data = new int[new_capacity];
48 |
49 | for (int i = 0; i < m_size; ++i) {
50 | new_data[i] = m_data[i];
51 | }
52 | delete[] m_data;
53 | m_data = new_data;
54 | m_capacity = new_capacity;
55 | }
56 | };
57 |
58 | int main()
59 | {
60 | return 0;
61 | }
--------------------------------------------------------------------------------
/chapter3-queue.cpp:
--------------------------------------------------------------------------------
1 | // My implementation of queue with two stacks.
2 | #include
3 | using namespace std;
4 |
5 | class Queue {
6 | public:
7 | Queue() {}
8 |
9 | void push(int val) {
10 | s1.push(val);
11 | }
12 |
13 | void pop() {
14 | if (s2.empty()) {
15 | while (!s1.empty()) {
16 | s2.push(s1.top());
17 | s1.pop();
18 | }
19 | }
20 | s2.pop();
21 | }
22 |
23 | int size() {
24 | return s1.size() + s2.size();
25 | }
26 |
27 | bool empty() {
28 | return size() == 0;
29 | }
30 |
31 | int front() {
32 | if (s2.empty()) {
33 | while (!s1.empty()) {
34 | s2.push(s1.top());
35 | s1.pop();
36 | }
37 | }
38 |
39 | return s2.top();
40 | }
41 |
42 | int back() {
43 | if (s1.empty()) {
44 | while (!s2.empty()) {
45 | s1.push(s2.top());
46 | s2.pop();
47 | }
48 | }
49 |
50 | return s1.top();
51 | }
52 |
53 | ~Queue() {
54 | while (!s1.empty()) {
55 | s1.pop();
56 | }
57 | while (!s2.empty()) {
58 | s2.pop();
59 | }
60 | }
61 | private:
62 | stack s1, s2;
63 | };
64 |
65 | int main()
66 | {
67 | return 0;
68 | }
--------------------------------------------------------------------------------
/chapter10-primality-testing.cpp:
--------------------------------------------------------------------------------
1 | // Primality testing using Fermat's Lesser Theorem.
2 | #include
3 | #include
4 | #include
5 | using namespace std;
6 |
7 | int primalityTest(int a, int i, int n)
8 | {
9 | // a is randomly chosen between (1, n) to test the primality of n.
10 | int x, y;
11 |
12 | if (i == 0) {
13 | return 1;
14 | }
15 |
16 | x = primalityTest(a, i / 2, n);
17 | if (x == 0) {
18 | // x == 0 means n is composite.
19 | // recursively return false
20 | return 0;
21 | }
22 |
23 | y = (x * x) % n;
24 | if (i % 2 != 0) {
25 | y = (y * a) % n;
26 | }
27 |
28 | return y;
29 | }
30 |
31 | bool isPrime(const int n)
32 | {
33 | if (n < 2) {
34 | return false;
35 | } else if (n < 4) {
36 | return true;
37 | }
38 |
39 | const int NUM_OF_TRIALS = 10;
40 | int i = 0;
41 | while (i < NUM_OF_TRIALS) {
42 | if (primalityTest(2 + rand() % (n - 3), n - 1, n) != 1) {
43 | return false;
44 | }
45 | ++i;
46 | }
47 |
48 | return true;
49 | }
50 |
51 | int main()
52 | {
53 | srand((unsigned int)time(nullptr));
54 | int n;
55 |
56 | while (cin>> n && n > 0) {
57 | cout << (isPrime(n) ? "Yes": "No") << endl;
58 | }
59 |
60 | return 0;
61 | }
--------------------------------------------------------------------------------
/chapter6-merge-sort.cpp:
--------------------------------------------------------------------------------
1 | // My implementation for merge sort.
2 | #include
3 | #include
4 | using namespace std;
5 |
6 | void mergeSortRecursive(vector &v, vector &temp, int left, int right)
7 | {
8 | if (right - left < 1) {
9 | return;
10 | }
11 | int mid = left + (right - left) / 2;
12 | mergeSortRecursive(v, temp, left, mid);
13 | mergeSortRecursive(v, temp, mid + 1, right);
14 |
15 | int i, j, k;
16 | i = left;
17 | j = mid + 1;
18 | k = left;
19 | while (i <= mid && j <= right) {
20 | if (v[i] < v[j]) {
21 | temp[k++] = v[i++];
22 | } else {
23 | temp[k++] = v[j++];
24 | }
25 | }
26 | while (i <= mid) {
27 | temp[k++] = v[i++];
28 | }
29 | while (j <= right) {
30 | temp[k++] = v[j++];
31 | }
32 | for (i = left; i <= right; ++i) {
33 | v[i] = temp[i];
34 | }
35 | }
36 |
37 | void mergeSort(vector &v)
38 | {
39 | int n;
40 | vector temp;
41 |
42 | n = (int)v.size();
43 | temp.resize(n);
44 | mergeSortRecursive(v, temp, 0, n - 1);
45 | temp.clear();
46 | }
47 |
48 | int main()
49 | {
50 | vector v;
51 | int n, i;
52 |
53 | while (cin >> n && n > 0) {
54 | v.resize(n);
55 | for (i = 0; i < n; ++i) {
56 | cin >> v[i];
57 | }
58 | mergeSort(v);
59 | for (i = 0; i < n; ++i) {
60 | cout << v[i] << ' ';
61 | }
62 | cout << endl;
63 | }
64 |
65 | return 0;
66 | }
--------------------------------------------------------------------------------
/chapter6-radix-sort.cpp:
--------------------------------------------------------------------------------
1 | // My implementation for radix sort.
2 | #include
3 | #include
4 | #include
5 | using namespace std;
6 |
7 | void radixSort(vector &v)
8 | {
9 | int n, i, j, k;
10 | int max_val;
11 | vector > rad;
12 |
13 | n = (int)v.size();
14 | if (n <= 1) {
15 | return;
16 | }
17 |
18 | // This algorithm works for negative integers.
19 | max_val = abs(v[0]);
20 | for (i = 1; i < n; ++i) {
21 | max_val = max(abs(v[i]), max_val);
22 | }
23 |
24 | int exp = 1;
25 | while (max_val / exp >= 10) {
26 | exp *= 10;
27 | }
28 |
29 | rad.resize(19);
30 | int iexp = 1;
31 | while (true) {
32 | for (i = 0; i < n; ++i) {
33 | rad[v[i] / iexp % 10 + 9].push_back(v[i]);
34 | }
35 |
36 | k = 0;
37 | for (i = 0; i < 19; ++i) {
38 | int n2 = (int)rad[i].size();
39 | for (j = 0; j < n2; ++j) {
40 | v[k++] = rad[i][j];
41 | }
42 | rad[i].clear();
43 | }
44 |
45 | if (iexp == exp) {
46 | break;
47 | } else {
48 | iexp *= 10;
49 | }
50 | }
51 | rad.clear();
52 | }
53 |
54 | int main()
55 | {
56 | vector v;
57 | int n, i;
58 |
59 | while (cin >> n && n > 0) {
60 | v.resize(n);
61 | for (i = 0; i < n; ++i) {
62 | cin >> v[i];
63 | }
64 | radixSort(v);
65 | for (i = 0; i < n; ++i) {
66 | cout << v[i] << ' ';
67 | }
68 | cout << endl;
69 | }
70 |
71 | return 0;
72 | }
--------------------------------------------------------------------------------
/chapter10-ordering-matrix-multiplication.cpp:
--------------------------------------------------------------------------------
1 | // Ordering matrix multiplication, a typical dynamic programming problem.
2 | // Description:
3 | // You have a list of matrices M1, M2, ..., Mn to multiply.
4 | // Each with dimension (X1, Y1), (X2, Y2), ..., (Xn, Yn)
5 | // Of course, Yi == X(i + 1)
6 | // You can arrange the order of matrix multiplications,
7 | // to achieve minimal number of multiplications.
8 | // For example: A * B * C can be A * (B * C) or (A * B) * C,
9 | // they might require different number of multiplications.
10 | #include
11 | #include
12 | using namespace std;
13 |
14 | const int INF = 1000000000;
15 |
16 | int orderingMatrixMultiplication(const vector &dimension)
17 | {
18 | int n = (int)dimension.size() - 1;
19 | vector > dp;
20 |
21 | dp.resize(n, vector(n, INF));
22 |
23 | int i, j, k;
24 |
25 | for (i = 0; i < n; ++i) {
26 | dp[i][i] = 0;
27 | }
28 |
29 | for (i = 1; i < n; ++i) {
30 | for (j = 0; j + i < n; ++j) {
31 | for (k = j; k < j + i; ++k) {
32 | dp[j][j + i] = min(dp[j][j + i], dp[j][k] + dp[k + 1][j + i]
33 | + dimension[j] * dimension[k + 1] * dimension[j + i + 1]);
34 | }
35 | }
36 | }
37 |
38 | int result = dp[0][n - 1];
39 | dp.clear();
40 |
41 | return result;
42 | }
43 |
44 | int main()
45 | {
46 | int i;
47 | int n;
48 | vector v;
49 |
50 | while (cin >> n && n > 0) {
51 | v.resize(n + 1);
52 | for (i = 0; i < n + 1; ++i) {
53 | cin >> v[i];
54 | }
55 | cout << orderingMatrixMultiplication(v) << endl;
56 | }
57 |
58 | return 0;
59 | }
--------------------------------------------------------------------------------
/chapter9-topological-sort.cpp:
--------------------------------------------------------------------------------
1 | // A simple illustration for topological sort. Graph represented by adjacency matrix.
2 | #include
3 | #include
4 | #include
5 | using namespace std;
6 |
7 | void topologicalSort(const vector > &graph, vector &order)
8 | {
9 | int n;
10 | int i, j;
11 | vector indegree;
12 | queue q;
13 |
14 | n = (int)graph.size();
15 | indegree.resize(n, 0);
16 |
17 | for (i = 0; i < n; ++i) {
18 | for (j = 0; j < n; ++j) {
19 | if (graph[i][j]) {
20 | ++indegree[j];
21 | }
22 | }
23 | }
24 |
25 | for (i = 0; i < n; ++i) {
26 | if (indegree[i] == 0) {
27 | q.push(i);
28 | break;
29 | }
30 | }
31 |
32 | while (!q.empty()) {
33 | i = q.front();
34 | q.pop();
35 | order.push_back(i);
36 | for (j = 0; j < n; ++j) {
37 | if (graph[i][j] && (--indegree[j] == 0)) {
38 | q.push(j);
39 | }
40 | }
41 | }
42 |
43 | indegree.clear();
44 | }
45 |
46 | int main()
47 | {
48 | vector > graph;
49 | vector order;
50 | int n;
51 | int nk;
52 | int i, j;
53 | int tmp;
54 |
55 | while (cin >> n && n > 0) {
56 | graph.resize(n);
57 | for (i = 0; i < n; ++i) {
58 | graph[i].resize(n, false);
59 | }
60 |
61 | for (i = 0; i < n; ++i) {
62 | cin >> nk;
63 | for (j = 0; j < nk; ++j) {
64 | cin >> tmp;
65 | graph[i][tmp] = true;
66 | }
67 | }
68 |
69 | topologicalSort(graph, order);
70 |
71 | if ((int)order.size() == n) {
72 | for (i = 0; i < n; ++i) {
73 | cout << order[i] << ' ';
74 | }
75 | cout << endl;
76 | } else {
77 | cout << "The graph has a cycle." << endl;
78 | }
79 |
80 | for (i = 0; i < n; ++i) {
81 | graph[i].clear();
82 | }
83 | graph.clear();
84 | order.clear();
85 | }
86 |
87 | return 0;
88 | }
--------------------------------------------------------------------------------
/chapter6-heap-sort.cpp:
--------------------------------------------------------------------------------
1 | // My implementation for selection sort.
2 | #include
3 | #include
4 | using namespace std;
5 |
6 | static inline int leftChild(int n)
7 | {
8 | return n * 2 + 1;
9 | }
10 |
11 | static inline int rightChild(int n)
12 | {
13 | return n * 2 + 2;
14 | }
15 |
16 | static inline void swap(int &x, int &y)
17 | {
18 | int tmp;
19 |
20 | tmp = x;
21 | x = y;
22 | y = tmp;
23 | }
24 |
25 | static inline int max(const int &x, const int &y)
26 | {
27 | return x > y ? x : y;
28 | }
29 |
30 | static void percolateDown(vector &v, int i, int n)
31 | {
32 | if (n <= 1 || i < 0 || i >= n) {
33 | return;
34 | }
35 | int max_val;
36 |
37 | while (leftChild(i) < n) {
38 | if (leftChild(i) == n - 1) {
39 | max_val = v[leftChild(i)];
40 | } else {
41 | max_val = max(v[leftChild(i)], v[rightChild(i)]);
42 | }
43 | if (v[i] < max_val) {
44 | if (max_val == v[leftChild(i)]) {
45 | swap(v[i], v[leftChild(i)]);
46 | i = leftChild(i);
47 | } else {
48 | swap(v[i], v[rightChild(i)]);
49 | i = rightChild(i);
50 | }
51 | } else {
52 | break;
53 | }
54 | }
55 | }
56 |
57 | void heapSort(vector &v)
58 | {
59 | int n;
60 | int i;
61 |
62 | n = (int)v.size();
63 | for (i = (n - 1) / 2; i >= 0; --i) {
64 | percolateDown(v, i, n);
65 | }
66 |
67 | int val;
68 | for (i = 0; i < n - 1; ++i) {
69 | val = v[0];
70 | v[0] = v[n - 1 - i];
71 | percolateDown(v, 0, n - 1 - i);
72 | v[n - 1 - i] = val;
73 | }
74 | }
75 |
76 | int main()
77 | {
78 | vector v;
79 | int n, i;
80 |
81 | while (cin >> n && n > 0) {
82 | v.resize(n);
83 | for (i = 0; i < n; ++i) {
84 | cin >> v[i];
85 | }
86 | heapSort(v);
87 | for (i = 0; i < n; ++i) {
88 | cout << v[i] << ' ';
89 | }
90 | cout << endl;
91 | }
92 |
93 | return 0;
94 | }
--------------------------------------------------------------------------------
/chapter9-unweighted-shortest-path.cpp:
--------------------------------------------------------------------------------
1 | // A simple illustration for unweighted shortest path. Graph represented by adjacency matrix.
2 | #include
3 | #include
4 | #include
5 | using namespace std;
6 |
7 | void unweightedShortestPath(const vector > &graph,
8 | vector &dist, vector &reachable)
9 | {
10 | // The minimal distances from 0th vertex to others.
11 | int n;
12 | int i, j;
13 |
14 | n = (int)graph.size();
15 | dist.resize(n);
16 | reachable.resize(n);
17 |
18 | if (n < 1) {
19 | return;
20 | }
21 |
22 | for (i = 0; i < n; ++i) {
23 | reachable[i] = false;
24 | }
25 |
26 | queue q;
27 |
28 | dist[0] = 0;
29 | reachable[0] = true;
30 |
31 | q.push(0);
32 | while (!q.empty()) {
33 | i = q.front();
34 | q.pop();
35 | for (j = 0; j < n; ++j) {
36 | if (!graph[i][j] || reachable[j]) {
37 | continue;
38 | }
39 | dist[j] = dist[i] + 1;
40 | reachable[j] = true;
41 | q.push(j);
42 | }
43 | }
44 | }
45 |
46 | int main()
47 | {
48 | vector > graph;
49 | vector dist;
50 | vector reachable;
51 | int n;
52 | int nk;
53 | int i, j;
54 | int tmp;
55 |
56 | while (cin >> n && n > 0) {
57 | graph.resize(n);
58 | for (i = 0; i < n; ++i) {
59 | graph[i].resize(n, false);
60 | }
61 |
62 | for (i = 0; i < n; ++i) {
63 | cin >> nk;
64 | for (j = 0; j < nk; ++j) {
65 | cin >> tmp;
66 | graph[i][tmp] = true;
67 | }
68 | }
69 |
70 | unweightedShortestPath(graph, dist, reachable);
71 |
72 | for (i = 0; i < n; ++i) {
73 | cout << i << ": ";
74 | if (reachable[i]) {
75 | cout << dist[i] << endl;
76 | } else {
77 | cout << "Unreachable" << endl;
78 | }
79 | }
80 |
81 | for (i = 0; i < n; ++i) {
82 | graph[i].clear();
83 | }
84 | graph.clear();
85 | }
86 |
87 | return 0;
88 | }
--------------------------------------------------------------------------------
/chapter9-all-pairs-shortest-path.cpp:
--------------------------------------------------------------------------------
1 | // A simple illustration for all pairs shortest path using Floyd Algorithm.
2 | #include
3 | #include
4 | using namespace std;
5 |
6 | const int INFINITY = 1000000000;
7 |
8 | void floydAlgorithm(const vector > &graph,
9 | vector > &dist)
10 | {
11 | int n;
12 | int i, j, k;
13 |
14 | n = (int)graph.size();
15 | dist.resize(n);
16 | for (i = 0; i < n; ++i) {
17 | dist[i].resize(n, INFINITY);
18 | }
19 |
20 | for (i = 0; i < n; ++i) {
21 | for (j = 0; j < n; ++j) {
22 | dist[i][j] = graph[i][j];
23 | }
24 | }
25 |
26 | for (k = 0; k < n; ++k) {
27 | for (i = 0; i < n; ++i) {
28 | for (j = 0; j < n; ++j) {
29 | if (dist[i][k] + dist[k][j] >= dist[i][j]) {
30 | continue;
31 | }
32 | dist[i][j] = dist[i][k] + dist[k][j];
33 | }
34 | }
35 | }
36 | }
37 |
38 | int main()
39 | {
40 | vector > graph;
41 | vector > dist;
42 | int n;
43 | int nk;
44 | int i, j;
45 | int tmp, tmp_dist;
46 |
47 | while (cin >> n && n > 0) {
48 | graph.resize(n);
49 | for (i = 0; i < n; ++i) {
50 | graph[i].resize(n, INFINITY);
51 | }
52 |
53 | for (i = 0; i < n; ++i) {
54 | cin >> nk;
55 | for (j = 0; j < nk; ++j) {
56 | cin >> tmp >> tmp_dist;
57 | graph[i][tmp] = tmp_dist;
58 | }
59 | }
60 |
61 | floydAlgorithm(graph, dist);
62 |
63 | for (i = 0; i < n; ++i) {
64 | for (j = 0; j < n; ++j) {
65 | cout << "[" << i << "][" << j << "]: ";
66 | if (dist[i][j] < INFINITY) {
67 | cout << dist[i][j] << endl;
68 | } else {
69 | cout << "Unreachable" << endl;
70 | }
71 | }
72 | }
73 |
74 | for (i = 0; i < n; ++i) {
75 | graph[i].clear();
76 | }
77 | graph.clear();
78 |
79 | for (i = 0; i < n; ++i) {
80 | dist[i].clear();
81 | }
82 | dist.clear();
83 | }
84 |
85 | return 0;
86 | }
--------------------------------------------------------------------------------
/chapter6-quick-sort.cpp:
--------------------------------------------------------------------------------
1 | // My implementation for quick sort.
2 | #include
3 | #include
4 | using namespace std;
5 |
6 | const int CUT_OFF = 4;
7 |
8 | static void swap(int &x, int &y)
9 | {
10 | int tmp;
11 |
12 | tmp = x;
13 | x = y;
14 | y = tmp;
15 | }
16 |
17 | static int medianThree(vector &v, int left, int right)
18 | {
19 | int center = (left + right) / 2;
20 |
21 | if (v[left] > v[right]) {
22 | swap(v[left], v[right]);
23 | }
24 | if (v[left] > v[center]) {
25 | swap(v[left], v[center]);
26 | }
27 | if (v[center] > v[right]) {
28 | swap(v[center], v[right]);
29 | }
30 | swap(v[center], v[right - 1]);
31 |
32 | return v[right - 1];
33 | }
34 |
35 | static void quickSortRecursive(vector &v, int left, int right)
36 | {
37 | if (right - left + 1 >= CUT_OFF) {
38 | int i, j;
39 | int pivot = medianThree(v, left, right);
40 |
41 | i = left;
42 | j = right - 1;
43 | while (true) {
44 | while (v[++i] < pivot) {}
45 | while (v[--j] > pivot) {}
46 | if (i < j) {
47 | swap(v[i], v[j]);
48 | } else {
49 | break;
50 | }
51 | }
52 | swap(v[i], v[right - 1]);
53 | quickSortRecursive(v, left, i - 1);
54 | quickSortRecursive(v, i + 1, right);
55 | } else {
56 | int i, j;
57 | int tmp;
58 |
59 | for (i = left + 1; i <= right; ++i) {
60 | tmp = v[i];
61 | for (j = i; j > left && v[j - 1] > tmp; --j) {
62 | v[j] = v[j - 1];
63 | }
64 | v[j] = tmp;
65 | }
66 | }
67 | }
68 |
69 | void quickSort(vector &v)
70 | {
71 | int n = (int)v.size();
72 | quickSortRecursive(v, 0, n - 1);
73 | }
74 |
75 | int main()
76 | {
77 | vector v;
78 | int n, i;
79 |
80 | while (cin >> n && n > 0) {
81 | v.resize(n);
82 | for (i = 0; i < n; ++i) {
83 | cin >> v[i];
84 | }
85 | quickSort(v);
86 | for (i = 0; i < n; ++i) {
87 | cout << v[i] << ' ';
88 | }
89 | cout << endl;
90 | }
91 |
92 | return 0;
93 | }
--------------------------------------------------------------------------------
/chapter9-weighted-shortest-path.cpp:
--------------------------------------------------------------------------------
1 | // A simple illustration for weighted shortest path. Graph represented by adjacency matrix.
2 | #include
3 | #include
4 | #include
5 | using namespace std;
6 |
7 | const int INFINITY = 1000000000;
8 |
9 | void weightedShortestPath(const vector > &graph,
10 | vector &dist, vector &reachable)
11 | {
12 | // The minimal distances from 0th vertice to others.
13 | int n;
14 | int i, j;
15 |
16 | n = (int)graph.size();
17 | dist.resize(n);
18 | reachable.resize(n);
19 |
20 | if (n < 1) {
21 | return;
22 | }
23 |
24 | for (i = 0; i < n; ++i) {
25 | reachable[i] = false;
26 | }
27 |
28 | queue q;
29 |
30 | dist[0] = 0;
31 | reachable[0] = true;
32 |
33 | q.push(0);
34 | while (!q.empty()) {
35 | i = q.front();
36 | q.pop();
37 | for (j = 0; j < n; ++j) {
38 | if (graph[i][j] == INFINITY || (reachable[j] &&
39 | dist[i] + graph[i][j] >= dist[j])) {
40 | continue;
41 | }
42 | dist[j] = dist[i] + graph[i][j];
43 | if (!reachable[j]) {
44 | q.push(j);
45 | }
46 | reachable[j] = true;
47 | }
48 | }
49 | }
50 |
51 | int main()
52 | {
53 | vector > graph;
54 | vector dist;
55 | vector reachable;
56 | int n;
57 | int nk;
58 | int i, j;
59 | int tmp, tmp_dist;
60 |
61 | while (cin >> n && n > 0) {
62 | graph.resize(n);
63 | for (i = 0; i < n; ++i) {
64 | graph[i].resize(n, INFINITY);
65 | }
66 |
67 | for (i = 0; i < n; ++i) {
68 | cin >> nk;
69 | for (j = 0; j < nk; ++j) {
70 | cin >> tmp >> tmp_dist;
71 | graph[i][tmp] = tmp_dist;
72 | }
73 | }
74 |
75 | weightedShortestPath(graph, dist, reachable);
76 |
77 | for (i = 0; i < n; ++i) {
78 | cout << i << ": ";
79 | if (reachable[i]) {
80 | cout << dist[i] << endl;
81 | } else {
82 | cout << "Unreachable" << endl;
83 | }
84 | }
85 |
86 | for (i = 0; i < n; ++i) {
87 | graph[i].clear();
88 | }
89 | graph.clear();
90 | }
91 |
92 | return 0;
93 | }
--------------------------------------------------------------------------------
/chapter10-a-simple-nim.cpp:
--------------------------------------------------------------------------------
1 | // This is said to be an interview question about game.
2 | // This solution is by dynamic programming.
3 | // Description:
4 | // If there're 50 stones at the beginning, you and your component take turns to take away 1, 2, 4 or 8 stones.
5 | // Whoever takes away the last stone loses the game.
6 | // Does this game has a winning strategy for any side?
7 | #include
8 | #include
9 | #include
10 | using namespace std;
11 |
12 | void game(const int n, const vector &move, vector &dp)
13 | {
14 | int i;
15 | // dp[i] means the game result when the total number of stones is i.
16 | // 1 for offensive win, -1 for defensive win, 0 for uncertain(fair play).
17 | dp.resize(n + 1, 0);
18 |
19 | int n_move = (int)move.size();
20 | int n_win;
21 | dp[move[0]] = -1;
22 |
23 | int j;
24 | for (i = move[0] + 1; i <= n; ++i) {
25 | n_win = 0;
26 | for (j = 0; j < n_move; ++j) {
27 | if (i - move[j] <= 0) {
28 | ++n_win;
29 | continue;
30 | }
31 | if (dp[i - move[j]] == -1) {
32 | // one of the parent node in the game tree is lose,
33 | // then you win.
34 | dp[i] = 1;
35 | break;
36 | } else if (dp[i - move[j]] == 1) {
37 | ++n_win;
38 | }
39 | }
40 | if (j == n_move && n_win == n_move) {
41 | // all parent nodes in the game tree are wins, then you lose
42 | dp[i] = -1;
43 | }
44 | }
45 | }
46 |
47 | int main()
48 | {
49 | vector dp;
50 | vector move;
51 | int n;
52 | int i;
53 | int tmp;
54 |
55 | while (cin >> n && n > 0) {
56 | while (cin >> tmp && tmp > 0) {
57 | move.push_back(tmp);
58 | }
59 | game(n, move, dp);
60 | sort(move.begin(), move.end());
61 | for (i = 1; i <= n; ++i) {
62 | cout << i << ':';
63 | switch(dp[i]) {
64 | case -1:
65 | cout << "Defensive win." << endl;
66 | break;
67 | case 0:
68 | cout << "Fair play." << endl;
69 | break;
70 | case 1:
71 | cout << "Offensive win." << endl;
72 | break;
73 | }
74 | }
75 |
76 | dp.clear();
77 | move.clear();
78 | }
79 |
80 | return 0;
81 | }
--------------------------------------------------------------------------------
/chapter4-binary-tree.cpp:
--------------------------------------------------------------------------------
1 | // My implementation for binary tree.
2 | #include
3 | #include
4 | using namespace std;
5 |
6 | struct TreeNode {
7 | int val;
8 | TreeNode *left;
9 | TreeNode *right;
10 | TreeNode(int _val): val(_val), left(nullptr), right(nullptr) {};
11 | };
12 |
13 | // One of the (de)serialization method I wrote.
14 | // Here is a serialization sample for this piece of code: {3,1,#,#,10,6,#,#,11,#,14,#,#}
15 | // 3
16 | // / \
17 | // 1 10
18 | // / \
19 | // 6 11
20 | // \
21 | // 14
22 | class BinaryTreeSerializer {
23 | public:
24 | string serialize(TreeNode *root) {
25 | string res = "{";
26 |
27 | // preorder traversal
28 | serializeTraversal(root, res);
29 | res[res.length() - 1] = '}';
30 |
31 | return res;
32 | };
33 |
34 | TreeNode *deserialize(string s) {
35 | vector data;
36 | int i, j, len;
37 |
38 | len = (int)s.length();
39 | i = 1;
40 | while (true) {
41 | j = i + 1;
42 | while (s[j] != ',' && s[j] != '}') {
43 | ++j;
44 | }
45 | data.push_back(s.substr(i, j - i));
46 | i = j + 1;
47 | if (i >= len) {
48 | break;
49 | }
50 | }
51 |
52 | int iter = 0;
53 | TreeNode *root = nullptr;
54 |
55 | // preorder traversal
56 | deserializeTraversal(data, root, iter);
57 |
58 | return root;
59 | };
60 | private:
61 | static char ss[10];
62 |
63 | void serializeTraversal(TreeNode *root, string &res) {
64 | if (root == nullptr) {
65 | res += "#,";
66 | } else {
67 | sprintf(ss, "%d", root->val);
68 | res += string(ss);
69 | res.push_back(',');
70 | serializeTraversal(root->left, res);
71 | serializeTraversal(root->right, res);
72 | }
73 | };
74 |
75 | void deserializeTraversal(vector &data, TreeNode *&root, int &iter) {
76 | ++iter;
77 | if (data[iter - 1] == "#") {
78 | root = nullptr;
79 | } else {
80 | int val;
81 |
82 | sscanf(data[iter - 1].c_str(), "%d", &val);
83 | root = new TreeNode(val);
84 | deserializeTraversal(data, root->left, iter);
85 | deserializeTraversal(data, root->right, iter);
86 | }
87 | };
88 | };
89 |
90 | int main()
91 | {
92 | return 0;
93 | }
--------------------------------------------------------------------------------
/chapter9-prims-algorithm.cpp:
--------------------------------------------------------------------------------
1 | // My implementation for Prim's Algorithm, for minimum spanning tree problem.
2 | #include
3 | #include
4 | #include
5 | #include
6 | using namespace std;
7 |
8 | const int INFINITY = 1000000000;
9 |
10 | struct Edge {
11 | int x;
12 | int y;
13 | int cost;
14 | Edge(int _x = 0, int _y = 0, int _cost = 0): x(_x), y(_y), cost(_cost) {};
15 | };
16 |
17 | struct GreaterFunctor {
18 | bool operator () (const Edge &e1, const Edge &e2) {
19 | return e1.cost > e2.cost;
20 | }
21 | };
22 |
23 | int primsAlgorithm(const vector > &graph)
24 | {
25 | // Prim's Algorithm for weighted undirected graph.
26 |
27 | int n;
28 | n = (int)graph.size();
29 | if (n < 2) {
30 | return 0;
31 | }
32 |
33 | int i;
34 | // Minimal heap, the top is smallest.
35 | priority_queue, GreaterFunctor> pq;
36 | vector visited;
37 | int visited_count;
38 | int min_cost;
39 |
40 | visited.resize(n, false);
41 |
42 | // Start constructing the tree from 0th vertex.
43 | min_cost = 0;
44 | visited[0] = true;
45 | for (i = 1; i < n; ++i) {
46 | if (graph[0][i] == INFINITY) {
47 | continue;
48 | }
49 | pq.push(Edge(0, i, graph[0][i]));
50 | }
51 | visited_count = n - 1;
52 |
53 | Edge e;
54 | while (!pq.empty()) {
55 | e = pq.top();
56 | pq.pop();
57 | if (visited[e.y]) {
58 | continue;
59 | }
60 | min_cost += e.cost;
61 | visited[e.y] = true;
62 | --visited_count;
63 | if (visited_count == 0) {
64 | break;
65 | }
66 |
67 | for (i = 0; i < n; ++i) {
68 | if (i == e.y || graph[e.y][i] == INFINITY || visited[i]) {
69 | continue;
70 | }
71 | pq.push(Edge(e.y, i, graph[e.y][i]));
72 | }
73 | }
74 |
75 | while (!pq.empty()) {
76 | pq.pop();
77 | }
78 |
79 | return min_cost;
80 | }
81 |
82 | int main()
83 | {
84 | vector > graph;
85 | int n;
86 | int nk;
87 | int i, j;
88 | int tmp, tmp_dist;
89 | int min_cost;
90 |
91 | while (cin >> n && n > 0) {
92 | graph.resize(n);
93 | for (i = 0; i < n; ++i) {
94 | graph[i].resize(n, INFINITY);
95 | }
96 |
97 | for (i = 0; i < n; ++i) {
98 | cin >> nk;
99 | for (j = 0; j < nk; ++j) {
100 | cin >> tmp >> tmp_dist;
101 | graph[i][tmp] = graph[tmp][i] = tmp_dist;
102 | }
103 | }
104 |
105 | min_cost = primsAlgorithm(graph);
106 |
107 | cout << "The weighted sum of minimum spanning tree is " << min_cost << "." << endl;
108 |
109 | for (i = 0; i < n; ++i) {
110 | graph[i].clear();
111 | }
112 | graph.clear();
113 | }
114 |
115 | return 0;
116 | }
--------------------------------------------------------------------------------
/chapter9-cut-vertices.cpp:
--------------------------------------------------------------------------------
1 | // My implementation for cut vertex detection on undirected graph.
2 | #include
3 | #include
4 | #include
5 | using namespace std;
6 |
7 | void findCutVertex(const vector > &graph, int idx, const int n,
8 | int &counter, vector &num, vector &low, vector &parent,
9 | vector &result)
10 | {
11 | int i;
12 |
13 | low[idx] = num[idx] = counter++;
14 | for (i = 0; i < n; ++i) {
15 | if (!graph[idx][i]) {
16 | continue;
17 | }
18 |
19 | if (num[i] < 0) {
20 | // Unvisited vertex
21 | parent[i] = idx;
22 | findCutVertex(graph, i, n, counter, num, low, parent, result);
23 | if (low[i] >= num[idx]) {
24 | result[idx] = true;
25 | }
26 | low[idx] = min(low[idx], low[i]);
27 | } else if (parent[idx] != i) {
28 | // Visited vertex
29 | low[idx] = min(low[idx], num[i]);
30 | }
31 | }
32 | }
33 |
34 | void cutVertexDetection(const vector > &graph,
35 | vector &is_cut_vertex)
36 | {
37 | // Cut vertex detection for undirected graph.
38 | int n;
39 |
40 | n = (int)graph.size();
41 | is_cut_vertex.resize(n, false);
42 |
43 | if (n == 1) {
44 | is_cut_vertex[0] = true;
45 | return;
46 | }
47 |
48 | vector parent;
49 | vector num;
50 | vector low;
51 | int counter;
52 |
53 | parent.resize(n, -1);
54 | num.resize(n, -1);
55 | low.resize(n, -1);
56 | counter = 0;
57 | findCutVertex(graph, 0, n, counter, num, low, parent, is_cut_vertex);
58 |
59 | // The root node must be checked separately.
60 | counter = 0;
61 | for (int i = 1; i < n; ++i) {
62 | if (parent[i] == 0) {
63 | ++counter;
64 | }
65 | }
66 | is_cut_vertex[0] = (counter > 1);
67 |
68 | parent.clear();
69 | num.clear();
70 | low.clear();
71 | }
72 |
73 | int main()
74 | {
75 | vector > graph;
76 | vector is_cut_vertex;
77 | int n;
78 | int nk;
79 | int i, j;
80 | int tmp;
81 |
82 | while (cin >> n && n > 0) {
83 | graph.resize(n);
84 | for (i = 0; i < n; ++i) {
85 | graph[i].resize(n, false);
86 | }
87 |
88 | for (i = 0; i < n; ++i) {
89 | cin >> nk;
90 | for (j = 0; j < nk; ++j) {
91 | cin >> tmp;
92 | graph[i][tmp] = graph[tmp][i] = true;
93 | }
94 | }
95 |
96 | cutVertexDetection(graph, is_cut_vertex);
97 | cout << "The following vertices are cut vertices:" << endl;
98 | cout << '{';
99 | for (i = 0; i < n; ++i) {
100 | if (is_cut_vertex[i]) {
101 | cout << i << ' ';
102 | }
103 | }
104 | cout << '}' << endl;
105 |
106 | for (i = 0; i < n; ++i) {
107 | graph[i].clear();
108 | }
109 | graph.clear();
110 | is_cut_vertex.clear();
111 | }
112 |
113 | return 0;
114 | }
--------------------------------------------------------------------------------
/chapter9-kruskals-algorithm.cpp:
--------------------------------------------------------------------------------
1 | // My implementation for Prim's Algorithm, for minimum spanning tree problem.
2 | #include
3 | #include
4 | #include
5 | using namespace std;
6 |
7 | const int INFINITY = 1000000000;
8 |
9 | struct Edge {
10 | int x;
11 | int y;
12 | int cost;
13 | Edge(int _x = 0, int _y = 0, int _cost = 0): x(_x), y(_y), cost(_cost) {};
14 | };
15 |
16 | bool comparator(const Edge &e1, const Edge &e2) {
17 | return e1.cost < e2.cost;
18 | }
19 |
20 | int findRoot(vector &dj, int x)
21 | {
22 | int r, k;
23 |
24 | r = x;
25 | while (r != dj[r]) {
26 | r = dj[r];
27 | }
28 |
29 | // Path compression speeds up the disjoint set.
30 | k = x;
31 | while (x != r) {
32 | x = dj[x];
33 | dj[k] = r;
34 | k = x;
35 | }
36 |
37 | return r;
38 | }
39 |
40 | int kruskalsAlgorithm(const vector > &graph)
41 | {
42 | // Kruskal's Algorithm for weighted undirected graph.
43 | int n;
44 | n = (int)graph.size();
45 | if (n < 2) {
46 | return 0;
47 | }
48 |
49 | // Disjoint set
50 | vector dj;
51 | vector edges;
52 | int rx, ry;
53 | int i, j;
54 |
55 | for (i = 0; i < n; ++i) {
56 | for (j = i + 1; j < n; ++j) {
57 | if (graph[i][j] == INFINITY) {
58 | continue;
59 | }
60 | edges.push_back(Edge(i, j, graph[i][j]));
61 | }
62 | }
63 | sort(edges.begin(), edges.end(), comparator);
64 |
65 | dj.resize(n);
66 | for (i = 0; i < n; ++i) {
67 | dj[i] = i;
68 | }
69 |
70 | int edge_count = n - 1;
71 | int min_cost = 0;
72 | int ec = (int)edges.size();
73 | for (i = 0; i < ec; ++i) {
74 | rx = findRoot(dj, edges[i].x);
75 | ry = findRoot(dj, edges[i].y);
76 | if (rx == ry) {
77 | continue;
78 | }
79 | dj[rx] = ry;
80 | findRoot(dj, edges[i].x);
81 |
82 | min_cost += edges[i].cost;
83 | --edge_count;
84 | if (edge_count == 0) {
85 | break;
86 | }
87 | }
88 | edges.clear();
89 |
90 | return min_cost;
91 | }
92 |
93 | int main()
94 | {
95 | vector > graph;
96 | int n;
97 | int nk;
98 | int i, j;
99 | int tmp, tmp_dist;
100 | int min_cost;
101 |
102 | while (cin >> n && n > 0) {
103 | graph.resize(n);
104 | for (i = 0; i < n; ++i) {
105 | graph[i].resize(n, INFINITY);
106 | }
107 |
108 | for (i = 0; i < n; ++i) {
109 | cin >> nk;
110 | for (j = 0; j < nk; ++j) {
111 | cin >> tmp >> tmp_dist;
112 | graph[i][tmp] = graph[tmp][i] = tmp_dist;
113 | }
114 | }
115 |
116 | min_cost = kruskalsAlgorithm(graph);
117 |
118 | cout << "The weighted sum of minimum spanning tree is " << min_cost << "." << endl;
119 |
120 | for (i = 0; i < n; ++i) {
121 | graph[i].clear();
122 | }
123 | graph.clear();
124 | }
125 |
126 | return 0;
127 | }
--------------------------------------------------------------------------------
/chapter3-singly-linked-list.cpp:
--------------------------------------------------------------------------------
1 | // My implementation for singly linked list.
2 | struct ListNode {
3 | int val;
4 | ListNode *next;
5 | ListNode(int _val = 0): val(_val), next(nullptr) {};
6 | };
7 |
8 | class SinglyLinkedList {
9 | public:
10 | SinglyLinkedList() {
11 | m_size = 0;
12 | m_head = nullptr;
13 | m_tail = nullptr;
14 | }
15 |
16 | void insertFront(int val) {
17 | if (m_size == 0) {
18 | m_head = m_tail = new ListNode(val);
19 | } else {
20 | ListNode *ptr = new ListNode(val);
21 | ptr->next = m_head;
22 | m_head = ptr;
23 | }
24 | ++m_size;
25 | }
26 |
27 | void insertBack(int val) {
28 | if (m_size == 0) {
29 | m_head = m_tail = new ListNode(val);
30 | } else {
31 | m_tail->next = new ListNode(val);
32 | m_tail = m_tail->next;
33 | }
34 | ++m_size;
35 | }
36 |
37 | void insertNode(int pos, int val) {
38 | int i;
39 |
40 | if (i <= 0) {
41 | insertFront(val);
42 | } else if (i >= m_size) {
43 | insertBack(val);
44 | } else {
45 | ListNode *ptr1, *ptr2;
46 |
47 | ptr1 = m_head;
48 | for (i = 0; i < pos - 1; ++i) {
49 | ptr1 = ptr1->next;
50 | }
51 | ptr2 = new ListNode(val);
52 | ptr2->next = ptr1->next;
53 | ptr1->next = ptr2;
54 | ++m_size;
55 | }
56 | }
57 |
58 | void deleteNode(int pos) {
59 | if (pos < 0 || pos > m_size - 1) {
60 | return;
61 | }
62 |
63 | ListNode *ptr1, *ptr2;
64 | if (pos == 0) {
65 | ptr1 = m_head;
66 | if (m_size == 1) {
67 | m_head = m_tail = nullptr;
68 | } else {
69 | m_head = m_head->next;
70 | }
71 | delete ptr1;
72 | } else {
73 | ptr1 = m_head;
74 | for (int i = 0; i < pos - 1; ++i) {
75 | ptr1 = ptr1->next;
76 | }
77 | ptr2 = ptr1->next;
78 | ptr1->next = ptr2->next;
79 | if (ptr2->next == nullptr) {
80 | m_tail = ptr1;
81 | }
82 | delete ptr2;
83 | }
84 | --m_size;
85 | }
86 |
87 | void updateNode(int pos, int val) {
88 | if (pos < 0 || pos > m_size - 1) {
89 | return;
90 | }
91 |
92 | ListNode *ptr = m_head;
93 | for (int i = 0; i < pos; ++i) {
94 | ptr = ptr->next;
95 | }
96 | ptr->val = val;
97 | }
98 |
99 | ListNode *findNode(int val) {
100 | ListNode *ptr = m_head;
101 | while (ptr != nullptr) {
102 | if (ptr->val == val) {
103 | return ptr;
104 | }
105 | ptr = ptr->next;
106 | }
107 |
108 | return nullptr;
109 | }
110 |
111 | ~SinglyLinkedList() {
112 | ListNode *ptr = m_head;
113 | while (m_head != nullptr) {
114 | m_head = m_head->next;
115 | delete ptr;
116 | ptr = m_head;
117 | }
118 | m_head = m_tail = nullptr;
119 | }
120 | private:
121 | int m_size;
122 | ListNode *m_head;
123 | ListNode *m_tail;
124 | };
125 |
126 | int main()
127 | {
128 | return 0;
129 | }
--------------------------------------------------------------------------------
/chapter10-turnpike-reconstrution.cpp:
--------------------------------------------------------------------------------
1 | // Turnpike reconstruction problem.
2 | // Description:
3 | // Given n * (n - 1) / 2 distances, find out if you can determine the
4 | // relative coordinates of n points.
5 | #include
6 | #include
7 | #include
8 | #include