二叉樹的遍曆演算法有多種,典型的有先序遍曆、中序遍曆、後序遍曆以及層序遍曆。而且這些遍曆的遞迴演算法較為簡單,代碼很少,容易實現,本文就是匯總二叉樹遍曆的遞迴演算法,非遞迴演算法將在下一篇文章中進行總結。本文中用到的二叉樹執行個體如下:
3 / \ 9 20 / \ 15 7
二叉樹定義和輔助函數如下:
struct node { int data; struct node* left; struct node* right;};void visit(int data){ printf("%d ", data);}
1、先序遍曆
先序遍曆:先訪問二叉樹的根結點,而後遍曆左子樹,最後遍曆右子樹。先序遍曆二叉樹執行個體結果為:3 9 20 15 7。遞迴演算法代碼如下:
void preOrder(struct node* root){ if (root == NULL) return; visit(root->data); preOrder(root->left); preOrder(root->right);}
2、中序遍曆
中序遍曆:先遍曆二叉樹的左子樹,然後訪問根結點,最後遍曆右子樹。中序遍曆二叉樹執行個體結果:9 3 15 20 7。遞迴演算法代碼如下:
void inOrder(struct node* root){ if (root == NULL) return; inOrder(root->left); visit(root->data); inOrder(root->right);}
3、後序遍曆
後序遍曆:先遍曆二叉樹的左子樹,然後遍曆二叉樹右子樹,最後訪問根結點。後序遍曆二叉樹執行個體結果:9 15 7 20 3。遞迴演算法代碼如下:
void postOrder(struct node* root){ if (root == NULL) return; postOrder(root->left); postOrder(root->right); visit(root->data);}
4、層序遍曆
對於先序遍曆、中序遍曆以及後序遍曆的遞迴演算法,沒有什麼好說的,時間複雜度都為O(n)。而層序遍曆的遞迴演算法則稍微複雜一點,因為本身層序遍曆用非遞迴演算法是很容易實現的,不過使用遞迴演算法代碼更簡潔,雖然遞迴演算法的效率並不高。層序遍曆二叉樹執行個體結果:
39 2015 7
遞迴代碼如下:
void printLevel(struct node *p, int level) { if (!p) return; if (level == 1) { visit(p->data); } else { printLevel(p->left, level-1); printLevel(p->right, level-1); }} void printLevelOrder(struct node *root) { int height = maxHeight(root); //maxHeight計算二叉樹高度,如二叉樹執行個體高度為3 for (int level = 1; level <= height; level++) { printLevel(root, level); printf("\n"); }}
當二叉樹高度為N時,此時遞迴層序遍曆為最壞情況,時間複雜度為O(N^2)。當二叉樹左右子樹基本平衡時,時間複雜度為O(N),分析如下:
設訪問第K層時間為T(k),則T(k)存在如下的遞迴公式:
T(k) = 2T(k-1) + c = 2k-1 T(1) + c = 2k-1 + c
當二叉樹平衡時,則高度為O(lgN),則總時間為:
T(1) + T(2) + ... + T(lg N)= 1 + 2 + 22 + ... + 2lg N-1 + c= O(N)