二叉樹遍歷之遞迴演算法
阿新 • • 發佈:2018-11-01
作者:石鍋拌飯 原文連結
二叉樹的遍歷演算法有多種,典型的有先序遍歷、中序遍歷、後序遍歷以及層序遍歷。而且這些遍歷的遞迴演算法較為簡單,程式碼很少,容易實現,本文就是彙總二叉樹遍歷的遞迴演算法,非遞迴演算法將在下一篇文章中進行總結。本文中用到的二叉樹例項如下:
3
/ \
9 20
/ \
15 7
二叉樹定義和輔助函式如下:
[cpp] view plaincopy
- struct
- int data;
- struct node* left;
- struct node* right;
- };
- void visit(int data)
- {
- printf("%d ", data);
- }
1、先序遍歷
先序遍歷:先訪問二叉樹的根結點,而後遍歷左子樹,最後遍歷右子樹。先序遍歷二叉樹例項結果為:3 9 20 15 7。遞迴演算法程式碼如下:
[cpp] view plaincopy
- void preOrder(
- {
- if (root == NULL)
- return;
- visit(root->data);
- preOrder(root->left);
- preOrder(root->right);
- }
2、中序遍歷
中序遍歷:先遍歷二叉樹的左子樹,然後訪問根結點,最後遍歷右子樹。中序遍歷二叉樹例項結果:9 3 15 20 7。遞迴演算法程式碼如下:
[cpp] view plaincopy
- void inOrder(struct node* root)
- {
- if (root == NULL)
- return;
- inOrder(root->left);
- visit(root->data);
- inOrder(root->right);
- }
3、後序遍歷
後序遍歷:先遍歷二叉樹的左子樹,然後遍歷二叉樹右子樹,最後訪問根結點。後序遍歷二叉樹例項結果:9 15 7 20 3。遞迴演算法程式碼如下:
[cpp] view plaincopy
- void postOrder(struct node* root)
- {
- if (root == NULL)
- return;
- postOrder(root->left);
- postOrder(root->right);
- visit(root->data);
- }
4、層序遍歷
對於先序遍歷、中序遍歷以及後序遍歷的遞迴演算法,沒有什麼好說的,時間複雜度都為O(n)。而層序遍歷的遞迴演算法則稍微複雜一點,因為本身層序遍歷用非遞迴演算法是很容易實現的,不過使用遞迴演算法程式碼更簡潔,雖然遞迴演算法的效率並不高。層序遍歷二叉樹例項結果:
3
9 20
15 7
遞迴程式碼如下:
[cpp] view plaincopy
- 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)