二叉樹的遞迴與非遞迴遍歷
阿新 • • 發佈:2019-01-11
- 遍歷時對樹的一種基本運算,所為遍歷二叉樹就是按一定的規則和順序走遍二叉樹的所有節點,是每一個節點都被訪問一次,有且只被訪問一次。由於二叉樹是非線性結構,因此,樹的遍歷實質上是將二叉樹的各個節點轉化為一個現行序列來表示。
- 下面的程式碼就是實現樹的遍歷的遞迴與非遞迴遍歷的,還補充了一些常用遞迴求解的常見問題。
#include<iostream> #include<stack> #include<queue> using namespace std; typedef char elemtype; //二叉樹節點形式 typedef struct BTreeNode { elemtype data; struct BTreeNode *left; struct BTreeNode *right; }BtNode; //為二叉樹節點申請空間 BTNode *BuyNode(int val) { BtNode *s = (BtNode*)malloc(sizeof(BtNode)); s->data = val; s->left = NULL; s->right = NULL; return s; } //創造一顆二叉樹 //根據陣列來建立一顆二叉樹 BtNode *CreateTree(char *arr, int len, int i) { BtNode *s = NULL; if(i < n) { s = BuyNode(arr[i]); s->left = CreateTree(arr, len, 2 * i); s->right = CreateTree(arr, len, 2 * i + 1); } return s; } BtNode *CreateTreeArr(char *arr, int len) { if(arr == NULL || len <= 0) { return NULL; } return CreateTree(arr, len, 0); } //根據二叉樹的先序和中序建立樹 BtNode *CreatePI(char *ps, char *is, int len) { BtNode *s = NULL; if(len > 0) { s = BuyNode(ps[0]); int pos = -1; for(int i = 0; i < len; i++) { if(ps[0] == is[i]) { pos = i; break; } } if(pos == -1) { return NULL; } s->left = CreatePI(ps + 1, is, pos); s->right = CreatePI(ps + pos + 1, is + pos + 1, len - pos - 1); } return s; } BtNode *CreateTreePI(char *ps, char *is, int len) { if(ps == NULL || is == NULL || len <= 0) { return NULL; } return CreatePI(ps, is, len); } //根據中序和後序來建立一顆二叉樹 BtNode *CreateLI(char *ls, char *is, int len) { BtNode *s = NULL; if(len > 0) { s = BuyNode(ls[len - 1]); int pos = -1; for(int i = 0; i < len; i++) { if(is[i] == ls[len - 1]) { pos = i; break; } } if(pos == -1) { return NULL; } s->left = CreateLI(ls, is, pos); s->right = CreateLI(ls + pos, is + pos + 1, len - pos - 1); } return s; } BtNode *CreateTreeLI(char *ls, char *is, int len) { if(ls == NULL || is == NULL || len <= 0) { return NULL; } return CreateLI(ls, is, len); } //二叉樹的遍歷 //遞迴的先序遍歷 void PreOrder(BtNode *ptree) { if(ptree == NULL) { return; } cout << ptree->data << " "; PreOrder(ptree->left); PreOrder(ptree->right); } //非遞迴的先序遍歷 void NicePreOrder(BtNode *ptree) { if(ptree == NULL) { return; } stack<BtNode*> st; st.push(ptree); while(!st.empty()) { ptree = st.top(); st.pop(); cout << ptree->data << " "; if(ptree->right != NULL) { st.push(ptree->right); } if(ptree->left != NULL) { st.push(ptree->left); } } cout << endl; } //遞迴的中序遍歷 void InOrder(BtNode *ptree) { if(ptree == NULL) { return; } InOrder(ptree->left); cout << ptree->data << " "; InOrder(ptree->right); } //非遞迴的中序遍歷 void NiceInOrder(BtNode *ptree) { if(ptree == NULL) { return; } stack<BtNode*> st; while(!st.empty() || ptree != NULL) { while(ptree) { st.push(ptree); ptree = ptree->left; } ptree = st.top(); st.pop(); cout << ptree->data << " "; ptree = ptree->right; } cout << endl; } //遞迴的後序遍歷 void PastOrder(BtNode *ptree) { if(ptree == NULL) { return; } PastOrder(ptree->left); PastOrder(ptree->right); cout << ptree->data << " "; } //非遞迴的後序遍歷 void NicePastOrder(BtNode *ptree) { if(ptree == NULL) { return; } stack<BtNode *> st; BtNode *flag = NULL; while(ptree != NULL || st.empty()) { while(ptree != NULL) { st.push(ptree): ptree = ptree->left; } ptree = st.top(); st.pop(); if(ptree->right == NULL || ptree->right == flag) { cout << ptree->data << " "; flag = ptree; ptree = NULL; } else { st.push(ptree); ptree = ptree->right; } } } //二叉樹的層序遍歷並計算出樹的高度 int NiceLevelOrder(BtNode *ptree) { if(ptree == NULL) { return; } queue<BtNode *> que; int high = 0; que.push(ptree); while(!que.empty()) { int len = que.size(); high++; while(len--) { ptree = que.front(); que.pop(); cout << ptree->data << " "; if(ptree->left != NULL) { que.push(ptree->left); } if(ptree->right != NULL) { que.push(ptree->right); } } } return high; } //遞迴法求樹的高度 int GetTreeHigh(BtNode *ptree) { if(ptree == NULL) { return 0; } return GetTreeHigh(ptree->left) > GetTreeHigh(ptree->right) ? GetTreeHigh(ptree->left) + 1 : GetTreeHigh(ptree->right) + 1; }