http://blog.csdn.net/algorithm_only/article/details/6973848
前面幾節講到的結構都是一種線性的數據結構,今天要說到另外一種數據結構——樹,其中二叉樹最為常用。二叉樹的特點是每個結點至多只有兩棵子樹,且二叉樹有左右字子樹之分,次序不能任意顛倒。
二叉樹的存儲結構可以用順序存儲和鏈式存儲來存儲。二叉樹的順序存儲結構由一組連續的存儲單元依次從上到下,從左到右存儲完全二叉樹的結點元素。對於一般二叉樹,應將其與完全二叉樹對應,然后給每個結點從1到i編上號,依次存儲在大小為i-1的數組中。這種方法只適用於完全二叉樹,對非完全二叉樹會浪費較多空間,最壞情況一個深度為k的二叉樹只有k個結點,卻需要長度為2的k次方減一長度的一位數組。事實上,二叉樹一般使用鏈式存儲結構,由二叉樹的定義可知,二叉樹的結點由一個數據元素和分別指向其左右孩子的指針構成,即二叉樹的鏈表結點中包含3個域,這種結點結構的二叉樹存儲結構稱之為二叉鏈表。
- 二叉鏈表的存儲結構
typedef struct tnode {
elemtype data;
struct tnode *lchild;
struct tnode *rchild;
}*bitree, bitnode;
- 創建一棵二叉樹(按先序序列建立)

1 int create_bitree(bitree *bt) 2 { 3 elemtype data; 4 5 scanf("%d", &data); 6 if (0 == data) { 7 *bt = NULL; 8 } else { 9 *bt = (bitree)malloc(sizeof(bitnode)); 10 if (!(*bt)) 11 exit(OVERFLOW); 12 (*bt)->data = data; 13 create_bitree(&(*bt)->lchild); 14 create_bitree(&(*bt)->rchild); 15 } 16 return OK; 17 }
- 二叉樹的遍歷(先序、中序、后序)

1 void preorder(bitree bt, int (*visit)(elemtype e)) 2 { 3 if (bt) { 4 visit(bt->data); 5 preorder(bt->lchild, visit); 6 preorder(bt->rchild, visit); 7 } 8 } 9 10 11 void inorder(bitree bt, int (*visit)(elemtype e)) 12 { 13 if (bt) { 14 inorder(bt->lchild, visit); 15 visit(bt->data); 16 inorder(bt->rchild, visit); 17 } 18 } 19 20 void postorder(bitree bt, int (*visit)(elemtype e)) 21 { 22 if (bt) { 23 postorder(bt->lchild, visit); 24 postorder(bt->rchild, visit); 25 visit(bt->data); 26 } 27 }
二叉樹的遞歸算法較簡單,代碼簡潔清晰,但遞歸算法效率低,執行速度慢,在下一節將說到二叉樹非遞歸遍歷算法。
- 求二叉樹的深度

1 int get_tree_depth(bitree bt) 2 { 3 int ldepth, rdepth; 4 5 if (!bt) 6 return 0; 7 else if (!bt->lchild && !bt->rchild) 8 return 1; 9 else { 10 ldepth = get_tree_depth(bt->lchild); 11 rdepth = get_tree_depth(bt->rchild); 12 13 return (ldepth > rdepth ? ldepth : rdepth) + 1; 14 } 15 }
樹的深度即樹的結點中最大層次,分別遞歸求左右子樹的深度,較大子樹深度為樹的深度。
- 求葉子結點數
1 int get_num_of_leave(bitree bt) 2 { 3 if (!bt) 4 return 0; 5 else if (!bt->lchild && !bt->rchild) 6 return 1; 7 else 8 return (get_num_of_leave(bt->lchild) + get_num_of_leave(bt->rchild)); 9 }
- 釋放二叉樹
1 void free_bitree(bitree *bt) 2 { 3 if (*bt) { 4 if ((*bt)->lchild) 5 free_bitree(&(*bt)->lchild); 6 if ((*bt)->rchild) 7 free_bitree(&(*bt)->rchild); 8 free(*bt); 9 *bt = NULL; 10 } 11 }
全部實現:

1 #include <stdlib.h> 2 #include <stdio.h> 3 #include <string> 4 #include <string.h> 5 #include <iostream> 6 #include <vector> 7 #include <stack> 8 using namespace std; 9 #define debug(x) cout << #x << " at line " << __LINE__ << " is: " << x << endl 10 typedef char elemtype; 11 //二叉鏈表結構 12 typedef struct tnode { 13 elemtype data; 14 struct tnode *lchild; 15 struct tnode *rchild; 16 }*bitree, bitnode; 17 18 int create_bitree(bitree *bt) 19 { 20 elemtype data; 21 scanf("%c", &data); 22 if ('#' == data) { 23 *bt = NULL; 24 } else { 25 *bt = (bitree)malloc(sizeof(bitnode)); 26 if (!(*bt)) 27 perror("bt malloc"); 28 (*bt)->data = data; 29 create_bitree(&(*bt)->lchild); 30 create_bitree(&(*bt)->rchild); 31 } 32 return 1; 33 } 34 35 void preorder(bitree bt, int (*visit)(elemtype e)) 36 { 37 if (bt) { 38 visit(bt->data); 39 preorder(bt->lchild, visit); 40 preorder(bt->rchild, visit); 41 } 42 } 43 44 45 void inorder(bitree bt, int (*visit)(elemtype e)) 46 { 47 if (bt) { 48 inorder(bt->lchild, visit); 49 visit(bt->data); 50 inorder(bt->rchild, visit); 51 } 52 } 53 54 void postorder(bitree bt, int (*visit)(elemtype e)) 55 { 56 if (bt) { 57 postorder(bt->lchild, visit); 58 postorder(bt->rchild, visit); 59 visit(bt->data); 60 } 61 } 62 63 int print(elemtype e){ 64 printf("%c", e); 65 return 1; 66 } 67 68 int get_tree_depth(bitree bt) 69 { 70 int ldepth, rdepth; 71 72 if (!bt) 73 return 0; 74 else if (!bt->lchild && !bt->rchild) 75 return 1; 76 else { 77 ldepth = get_tree_depth(bt->lchild); 78 rdepth = get_tree_depth(bt->rchild); 79 80 return (ldepth > rdepth ? ldepth : rdepth) + 1; 81 } 82 } 83 84 void free_bitree(bitree *bt) 85 { 86 if (*bt) { 87 if ((*bt)->lchild) 88 free_bitree(&(*bt)->lchild); 89 if ((*bt)->rchild) 90 free_bitree(&(*bt)->rchild); 91 free(*bt); 92 *bt = NULL; 93 } 94 } 95 typedef int (*func)(bitree bt); 96 int main(void) { 97 bitree bt; 98 create_bitree(&bt); 99 printf("pre:"); 100 preorder(bt, print); 101 printf("\n"); 102 printf("in:"); 103 inorder(bt, print); 104 printf("\n"); 105 printf("post:"); 106 postorder(bt, print); 107 printf("\n"); 108 free_bitree(&bt); 109 return 0; 110 }
2016-11-16 22:05:10
最低公共祖先節點

1 #include <stdlib.h> 2 #include <stdio.h> 3 #include <error.h> 4 #include <iostream> 5 #include <string> 6 #include <vector> 7 #include <stack> 8 #include <unistd.h> 9 #include <time.h> 10 using namespace std; 11 #define debug(x) cout << #x << " at line " << __LINE__ << " is: " << x << endl 12 typedef char elemtype; 13 typedef struct Bitree{ 14 elemtype data; 15 struct Bitree *lchild; 16 struct Bitree *rchild; 17 }STBitree,*bitree; 18 19 vector<STBitree *>::iterator vbi; 20 vector<elemtype>::iterator vei; 21 22 //前序創建二叉樹 23 STBitree *precreate(); 24 //打印二叉樹 25 int print_bitree(elemtype e); 26 //遞歸-前序,中序,后序遍歷二叉樹 27 void preorder(bitree bt, int (*visit)(elemtype e)); 28 void inorder(bitree bt, int (*visit)(elemtype e)); 29 void postorder(bitree bt, int (*visit)(elemtype e)); 30 //非遞歸-前序,中序,后序遍歷二叉樹 31 void nrpreorder(bitree root); 32 void nrinorder(bitree root); 33 void nrpostorder(bitree root); 34 void nrpostorderfunc(bitree root, int (*visit)(elemtype e)); 35 //根到某個子節點的路徑 36 vector<elemtype> rc_path(bitree root, elemtype ekey); 37 //最低公共祖先節點 38 elemtype lca(STBitree *root, elemtype node1, elemtype node2); 39 //釋放二叉樹 40 void free_bitree(STBitree *bt); 41 42 int main() 43 { 44 STBitree *root; 45 //printf("%lu %lu\n", sizeof(STBitree),sizeof(bitree)); 46 cout << "create biBtree:"; 47 root = precreate(); 48 vector<elemtype> ve; 49 lca(root, 'd','c'); 50 // cout << "preorder:"; 51 // preorder(root, print_bitree); 52 // cout << '\n'; 53 // cout << "inorder:"; 54 // inorder(root, print_bitree); 55 // cout << '\n'; 56 // cout << "postorder:"; 57 // postorder(root, print_bitree); 58 // cout << '\n'; 59 // cout << "nrpostorder:"; 60 // nrpostorderfunc(root, print_bitree); 61 // cout << '\n'; 62 free_bitree(root); 63 } 64 65 STBitree *precreate(){ 66 STBitree *root; 67 char ch; 68 scanf("%c", &ch); 69 if(ch == '#'){ 70 root = NULL; 71 } 72 else { 73 root = (STBitree *)malloc(sizeof(STBitree)); 74 root->data = ch; 75 root->lchild=precreate(); 76 root->rchild=precreate(); 77 } 78 return root; 79 } 80 81 int print_bitree(elemtype e){ 82 cout << e; 83 return 0; 84 } 85 86 void preorder(bitree bt, int (*visit)(elemtype e)) 87 { 88 if (bt) { 89 visit(bt->data); 90 preorder(bt->lchild, visit); 91 preorder(bt->rchild, visit); 92 } 93 } 94 95 void inorder(bitree bt, int (*visit)(elemtype e)) 96 { 97 if (bt) { 98 inorder(bt->lchild, visit); 99 visit(bt->data); 100 inorder(bt->rchild, visit); 101 } 102 } 103 104 void postorder(bitree bt, int (*visit)(elemtype e)) 105 { 106 if (bt) { 107 postorder(bt->lchild, visit); 108 postorder(bt->rchild, visit); 109 visit(bt->data); 110 } 111 } 112 113 vector<elemtype> rc_path(bitree root, elemtype ekey){ 114 stack<bitree> sbt; 115 bitree pCur, pLastVisit; 116 vector<elemtype> ve; 117 pCur = root; 118 pLastVisit = NULL; 119 ve.clear(); 120 while (pCur) { 121 sbt.push(pCur); 122 ve.push_back(pCur->data); 123 pCur = pCur->lchild; 124 } 125 126 while (!sbt.empty()) { 127 pCur = sbt.top(); 128 sbt.pop(); 129 ve.pop_back(); 130 if(pCur->rchild == NULL || pLastVisit == pCur->rchild){ 131 if(pCur->data == ekey){ 132 ve.push_back(pCur->data); 133 // for (vei = ve.begin(); vei != ve.end(); ++vei) { 134 // cout << *vei ; 135 // } 136 return ve; 137 } 138 pLastVisit = pCur; 139 } 140 if(pCur->lchild == pLastVisit){ 141 sbt.push(pCur); 142 ve.push_back(pCur->data); 143 pCur = pCur->rchild; 144 while (pCur) { 145 sbt.push(pCur); 146 ve.push_back(pCur->data); 147 pCur = pCur->lchild; 148 } 149 } 150 } 151 } 152 153 elemtype lca(STBitree *root, elemtype node1, elemtype node2){ 154 vector<STBitree *> vb; 155 vector<elemtype> ve1; 156 vector<elemtype> ve2; 157 vb.clear(); 158 if(root == NULL){ 159 return 0; 160 } 161 ve1 = rc_path(root, node1); 162 ve2 = rc_path(root, node2); 163 int idx = 0,preidx = 0; 164 while (ve1[idx] == ve2[idx]) { 165 ++idx; 166 } 167 --idx; 168 cout << ve1[idx]; 169 return ve1[idx]; 170 } 171 172 void nrpostorder(bitree root){ 173 stack<bitree> sbt;// ab#deg###f#h##c## 174 //pCur當前訪問節點,pLastVisit上次訪問節點 // ab#de##f##c## 175 bitree pCur,pLastVisit; 176 if (root == NULL) { 177 return; 178 } 179 pCur = root; 180 pLastVisit = NULL; 181 while (pCur) { 182 sbt.push(pCur); 183 //vb.push_back(pCur); 184 pCur = pCur->lchild; 185 } 186 // cout << "[從根到最左節點:"; 187 // for (vbi = vb.begin(); vbi != vb.end(); ++vbi) { 188 // cout << (*vbi)->data; 189 // } 190 // cout << "]\n"; 191 while (!sbt.empty()) { 192 pCur = sbt.top(); 193 //debug(pCur); 194 sbt.pop();//ab#d##c## 195 // vb.pop_back(); 196 // cout << "前棧中元素:"; 197 // for (vbi = vb.begin(); vbi != vb.end(); ++vbi) { 198 // cout << (*vbi)->data << endl; 199 // } 200 // cout << '\n'; 201 //當前節點的右孩子是上次訪問的節點pl或者當前節點的右孩子為空,則說明說明可以直接訪問該節點了. 202 if((pLastVisit == pCur->rchild) || (pCur->rchild == NULL)){ 203 cout << pCur->data; 204 pLastVisit = pCur; 205 } 206 if(pCur->lchild == pLastVisit){ 207 sbt.push(pCur); 208 pCur = pCur->rchild; 209 while (pCur) { 210 sbt.push(pCur); 211 pCur = pCur->lchild; 212 } 213 } 214 //N@20161118 215 // if(pCur->rchild != NULL){ 216 // if(pLastVisit != pCur->rchild){ 217 // sbt.push(pCur); 218 // pCur = pCur->rchild; 219 // while (pCur) { 220 // sbt.push(pCur); 221 // pCur = pCur->lchild; 222 // } 223 // } 224 // } 225 // cout << "后棧中元素:"; 226 // for (vbi = vb.begin(); vbi != vb.end(); ++vbi) { 227 // cout << (*vbi)->data << endl; 228 // } 229 // cout << '\n'; 230 } 231 } 232 233 void nrpostorderfunc(bitree root, int (*visit)(elemtype e)){ 234 stack<bitree> sbt;// ab#deg###f#h##c## 235 //pCur當前訪問節點,pLastVisit上次訪問節點 // ab#de##f##c## 236 bitree pCur,pLastVisit; 237 if (root == NULL) { 238 return; 239 } 240 pCur = root; 241 pLastVisit = NULL; 242 while (pCur) { 243 sbt.push(pCur); 244 //vb.push_back(pCur); 245 pCur = pCur->lchild; 246 } 247 // cout << "[從根到最左節點:"; 248 // for (vbi = vb.begin(); vbi != vb.end(); ++vbi) { 249 // cout << (*vbi)->data; 250 // } 251 // cout << "]\n"; 252 while (!sbt.empty()) { 253 pCur = sbt.top(); 254 //debug(pCur); 255 sbt.pop();//ab#d##c## 256 // vb.pop_back(); 257 // cout << "前棧中元素:"; 258 // for (vbi = vb.begin(); vbi != vb.end(); ++vbi) { 259 // cout << (*vbi)->data << endl; 260 // } 261 // cout << '\n'; 262 //當前節點的右孩子是上次訪問的節點pl或者當前節點的右孩子為空,則說明說明可以直接訪問該節點了. 263 if((pLastVisit == pCur->rchild) || (pCur->rchild == NULL)){ 264 //cout << pCur->data; 265 visit(pCur->data); 266 pLastVisit = pCur; 267 } 268 if(pCur->lchild == pLastVisit){ 269 sbt.push(pCur); 270 pCur = pCur->rchild; 271 while (pCur) { 272 sbt.push(pCur); 273 pCur = pCur->lchild; 274 } 275 } 276 //N@20161118 277 // if(pCur->rchild != NULL){ 278 // if(pLastVisit != pCur->rchild){ 279 // sbt.push(pCur); 280 // pCur = pCur->rchild; 281 // while (pCur) { 282 // sbt.push(pCur); 283 // pCur = pCur->lchild; 284 // } 285 // } 286 // } 287 // cout << "后棧中元素:"; 288 // for (vbi = vb.begin(); vbi != vb.end(); ++vbi) { 289 // cout << (*vbi)->data << endl; 290 // } 291 // cout << '\n'; 292 } 293 } 294 295 void free_bitree(STBitree *bt) 296 { 297 if (bt) { 298 if ((*bt).lchild) 299 free_bitree((*bt).lchild); 300 if ((*bt).rchild) 301 free_bitree((*bt).rchild); 302 free(bt); 303 bt = NULL; 304 } 305 }
Method 1 (By Storing root to n1 and root to n2 paths):
Following is simple O(n) algorithm to find LCA of n1 and n2.
1) Find path from root to n1 and store it in a vector or array.
2) Find path from root to n2 and store it in another vector or array.
3) Traverse both paths till the values in arrays are same. Return the common element just before the mismatch.

1 // http://www.geeksforgeeks.org/lowest-common-ancestor-binary-tree-set-1/ 2 // A O(n) solution to find LCA of two given values n1 and n2 3 #include <iostream> 4 #include <vector> 5 #include <algorithm> 6 using namespace std; 7 8 // A Bianry Tree node 9 struct Node 10 { 11 int key; 12 struct Node *left, *right; 13 }; 14 15 struct myclass { // function object type: 16 void operator() (int i) {std::cout << ' ' << i;} 17 } myobject; 18 19 // Utility function creates a new binary tree node with given key 20 Node * newNode(int k) 21 { 22 Node *temp = new Node; 23 temp->key = k; 24 temp->left = temp->right = NULL; 25 return temp; 26 } 27 28 // Finds the path from root node to given root of the tree, Stores the 29 // path in a vector path[], returns true if path exists otherwise false 30 bool findPath(Node *root, vector<int> &path, int k) 31 { 32 // base case 33 if (root == NULL) return false; 34 35 // Store this node in path vector. The node will be removed if 36 // not in path from root to k 37 path.push_back(root->key); 38 39 // See if the k is same as root's key 40 if (root->key == k) 41 return true; 42 43 // Check if k is found in left or right sub-tree 44 if ( (root->left && findPath(root->left, path, k)) || 45 (root->right && findPath(root->right, path, k)) ) 46 return true; 47 48 // If not present in subtree rooted with root, remove root from 49 // path[] and return false 50 path.pop_back(); 51 return false; 52 } 53 54 // Returns LCA if node n1, n2 are present in the given binary tree, 55 // otherwise return -1 56 int findLCA(Node *root, int n1, int n2) 57 { 58 // to store paths to n1 and n2 from the root 59 vector<int> path1, path2; 60 61 // Find paths from root to n1 and root to n1. If either n1 or n2 62 // is not present, return -1 63 if ( !findPath(root, path1, n1) || !findPath(root, path2, n2)) 64 return -1; 65 66 /* Compare the paths to get the first different value */ 67 size_t i; 68 for (i = 0; i < path1.size() && i < path2.size() ; i++) 69 if (path1[i] != path2[i]) 70 break; 71 return path1[i-1]; 72 } 73 74 // Driver program to test above functions 75 int main() 76 { 77 // Let us create the Binary Tree shown in above diagram. 78 Node * root = newNode(1); 79 root->left = newNode(2); 80 root->right = newNode(3); 81 root->left->left = newNode(4); 82 root->left->right = newNode(5); 83 root->right->left = newNode(6); 84 root->right->right = newNode(7); 85 cout << "LCA(4, 5) = " << findLCA(root, 4, 5); 86 cout << "\nLCA(4, 6) = " << findLCA(root, 4, 6); 87 cout << "\nLCA(3, 4) = " << findLCA(root, 3, 4); 88 cout << "\nLCA(2, 4) = " << findLCA(root, 2, 4); 89 return 0; 90 }
只遍歷一遍二叉樹的方法:

/* Program to find LCA of n1 and n2 using one traversal of Binary Tree. It handles all cases even when n1 or n2 is not there in Binary Tree */ #include <iostream> using namespace std; // A Binary Tree Node struct Node { struct Node *left, *right; int key; }; // Utility function to create a new tree Node Node* newNode(int key) { Node *temp = new Node; temp->key = key; temp->left = temp->right = NULL; return temp; } // This function returns pointer to LCA of two given values n1 and n2. // v1 is set as true by this function if n1 is found // v2 is set as true by this function if n2 is found struct Node *findLCAUtil(struct Node* root, int n1, int n2, bool &v1, bool &v2) { // Base case if (root == NULL) return NULL; // If either n1 or n2 matches with root's key, report the presence // by setting v1 or v2 as true and return root (Note that if a key // is ancestor of other, then the ancestor key becomes LCA) if (root->key == n1) { v1 = true; return root; } if (root->key == n2) { v2 = true; return root; } // Look for keys in left and right subtrees Node *left_lca = findLCAUtil(root->left, n1, n2, v1, v2); Node *right_lca = findLCAUtil(root->right, n1, n2, v1, v2); // If both of the above calls return Non-NULL, then one key // is present in once subtree and other is present in other, // So this node is the LCA if (left_lca && right_lca) return root; // Otherwise check if left subtree or right subtree is LCA return (left_lca != NULL)? left_lca: right_lca; } // Returns true if key k is present in tree rooted with root bool find(Node *root, int k) { // Base Case if (root == NULL) return false; // If key is present at root, or in left subtree or right subtree, // return true; if (root->key == k || find(root->left, k) || find(root->right, k)) return true; // Else return false return false; } // This function returns LCA of n1 and n2 only if both n1 and n2 are present // in tree, otherwise returns NULL; Node *findLCA(Node *root, int n1, int n2) { // Initialize n1 and n2 as not visited bool v1 = false, v2 = false; // Find lca of n1 and n2 using the technique discussed above Node *lca = findLCAUtil(root, n1, n2, v1, v2); // Return LCA only if both n1 and n2 are present in tree if (v1 && v2 || v1 && find(lca, n2) || v2 && find(lca, n1)) return lca; // Else return NULL return NULL; } // Driver program to test above functions int main() { // Let us create binary tree given in the above example Node * root = newNode(1); root->left = newNode(2); root->right = newNode(3); root->left->left = newNode(4); root->left->right = newNode(5); root->right->left = newNode(6); root->right->right = newNode(7); Node *lca = findLCA(root, 4, 5); if (lca != NULL) cout << "LCA(4, 5) = " << lca->key; else cout << "Keys are not present "; lca = findLCA(root, 4, 10); if (lca != NULL) cout << "\nLCA(4, 10) = " << lca->key; else cout << "\nKeys are not present "; return 0; }