SHOW:
|
|
- or go back to the newest paste.
1 | #include<stdio.h> | |
2 | #include<stdlib.h> | |
3 | ||
4 | #define bool int | |
5 | ||
6 | /* A binary tree node has data, pointer to left child | |
7 | and a pointer to right child */ | |
8 | struct node | |
9 | { | |
10 | int data; | |
11 | struct node* left; | |
12 | struct node* right; | |
13 | }; | |
14 | ||
15 | /* | |
16 | Original example code. | |
17 | ||
18 | Given a tree and a sum, return true if there is a path from the root | |
19 | down to a leaf, such that adding up all the values along the path | |
20 | equals the given sum. | |
21 | ||
22 | Strategy: subtract the node value from the sum when recurring down, | |
23 | and check to see if the sum is 0 when you run out of tree. | |
24 | */ | |
25 | bool hasPathSum_original(struct node* node, int sum) | |
26 | { | |
27 | /* return true if we run out of tree and sum==0 */ | |
28 | if (node == NULL) | |
29 | { | |
30 | return (sum == 0); | |
31 | } | |
32 | ||
33 | else | |
34 | { | |
35 | bool ans = 0; | |
36 | ||
37 | /* otherwise check both subtrees */ | |
38 | int subSum = sum - node->data; | |
39 | ||
40 | /* If we reach a leaf node and sum becomes 0 then return true*/ | |
41 | if ( subSum == 0 && node->left == NULL && node->right == NULL ) | |
42 | return 1; | |
43 | ||
44 | if(node->left) | |
45 | ans = ans || hasPathSum_original(node->left, subSum); | |
46 | if(node->right) | |
47 | ans = ans || hasPathSum_original(node->right, subSum); | |
48 | ||
49 | return ans; | |
50 | } | |
51 | } | |
52 | ||
53 | /* | |
54 | - | Here is the original example without optimization. You'll see that the algorithm is much cleaner now. You had a bug in your rewrite as it answered the question "Is there A path with the given sum?" when you had nodes which had a left node without a right one (or vice versa). |
54 | + | Here is the original example without optimization. You'll see that the algorithm is much cleaner now. |
55 | Note that this will short-circuit the calls in the line with the return statement. | |
56 | */ | |
57 | bool hasPathSum_revised(struct node* node, int sum) | |
58 | { | |
59 | /* return true if we run out of tree and sum==0 */ | |
60 | if (node == NULL) | |
61 | return (sum == 0); | |
62 | ||
63 | /* otherwise check both subtrees */ | |
64 | int subSum = sum - node->data; | |
65 | return hasPathSum_revised(node->left, subSum) || hasPathSum_revised(node->right, subSum); | |
66 | } | |
67 | ||
68 | /* | |
69 | Find the minimum in the binary tree - without making any assumptions. | |
70 | Call this with an "impossible" minimum at top level. | |
71 | */ | |
72 | int findMin(struct node* node, int min) { | |
73 | if (!node) return min; | |
74 | if (node->data < min) | |
75 | min = node->data; | |
76 | ||
77 | int leftMin = findMin(node->left, min); | |
78 | if(leftMin < min) | |
79 | min = leftMin; | |
80 | ||
81 | int rightMin = findMin(node->right, min); | |
82 | if(rightMin < min) | |
83 | min = rightMin; | |
84 | ||
85 | return min; | |
86 | } | |
87 | ||
88 | /* UTILITY FUNCTIONS */ | |
89 | /* Helper function that allocates a new node with the | |
90 | given data and NULL left and right pointers. */ | |
91 | struct node* newnode(int data) | |
92 | { | |
93 | struct node* node = (struct node*) | |
94 | malloc(sizeof(struct node)); | |
95 | node->data = data; | |
96 | node->left = NULL; | |
97 | node->right = NULL; | |
98 | ||
99 | return(node); | |
100 | } | |
101 | ||
102 | void freetree(struct node* node) | |
103 | { | |
104 | if(!node) | |
105 | return; | |
106 | freetree(node->left); | |
107 | freetree(node->right); | |
108 | free(node); | |
109 | } | |
110 | ||
111 | /* Generate a random full binary tree where every path to a leaf has the | |
112 | totalsum given */ | |
113 | struct node* generatetree(struct node* node, unsigned depth, int totalsum) { | |
114 | if(depth == 0) { | |
115 | node->data = totalsum; | |
116 | return node; | |
117 | } | |
118 | node->data = (rand() % 100) - 50; | |
119 | node->left = newnode(0); | |
120 | node->right = newnode(0); | |
121 | generatetree(node->left, depth-1, totalsum - node->data); | |
122 | generatetree(node->right, depth-1, totalsum - node->data); | |
123 | return node; | |
124 | } | |
125 | ||
126 | void inspecttree(struct node* root, int expected_sum) { | |
127 | printf("Original:\n"); | |
128 | if(hasPathSum_original(root, expected_sum)) | |
129 | printf("There is a root-to-leaf path with sum %d\n", expected_sum); | |
130 | else | |
131 | printf("There is no root-to-leaf path with sum %d\n", expected_sum); | |
132 | ||
133 | printf("Revised:\n"); | |
134 | if(hasPathSum_revised(root, expected_sum)) | |
135 | printf("There is a root-to-leaf path with sum %d\n", expected_sum); | |
136 | else | |
137 | printf("There is no root-to-leaf path with sum %d\n", expected_sum); | |
138 | /* where was INT_MAX defined again :( */ | |
139 | printf("Minimum: %d\n", findMin(root, 60000)); | |
140 | } | |
141 | ||
142 | /* Driver program to test above functions*/ | |
143 | int main() | |
144 | { | |
145 | srand(time(NULL)); | |
146 | int sum = 21; | |
147 | ||
148 | /* Hand constructed binary tree is | |
149 | 10 | |
150 | / \ | |
151 | 8 2 | |
152 | / \ / | |
153 | 3 5 2 | |
154 | */ | |
155 | struct node *root = newnode(10); | |
156 | root->left = newnode(8); | |
157 | root->right = newnode(2); | |
158 | root->left->left = newnode(3); | |
159 | root->left->right = newnode(5); | |
160 | root->right->left = newnode(2); | |
161 | inspecttree(root, sum); | |
162 | freetree(root); | |
163 | ||
164 | root = generatetree(newnode(0), 8, 1000); | |
165 | inspecttree(root, 1000); | |
166 | freetree(root); | |
167 | ||
168 | getchar(); | |
169 | return 0; | |
170 | } |