日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

二叉树的遍历 (递归和非递归实现)

發(fā)布時間:2024/4/18 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 二叉树的遍历 (递归和非递归实现) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

二叉樹的遍歷 (遞歸實現(xiàn))

用C++實現(xiàn)二叉樹的“先根遍歷”存儲。

用C++實現(xiàn)二叉樹的“先根遍歷”、“中根遍歷”、“后根遍歷”分別輸出二叉樹中結(jié)點的數(shù)據(jù)。

#include <iostream> using namespace std ;struct BiNode {char data ;BiNode *lchild , *rchild ; } ; BiNode *BiTree ;int NodeID ;BiNode *CreateBiTree (char *c , int n) {BiNode *T ;NodeID ++ ;if (NodeID > n){return (NULL) ;}if (c[NodeID] == '0'){return (NULL) ;}T = new BiNode ;T -> data = c[NodeID] ;T -> lchild = CreateBiTree (c , n) ;T -> rchild = CreateBiTree (c , n) ;return (T) ; }void PreOrderTraverse (BiNode *T) {if (T){cout << T -> data << " ";PreOrderTraverse (T -> lchild) ;PreOrderTraverse (T -> rchild) ;} }void InOrderTraverse (BiNode *T) {if (T){InOrderTraverse (T -> lchild) ;cout << T -> data << " ";InOrderTraverse (T -> rchild) ;} }void PostOrderTraverse (BiNode *T) {if (T){PostOrderTraverse (T -> lchild) ;PostOrderTraverse (T -> rchild) ;cout << T -> data << " ";} }int main () {int i , SampleNum ;char c[100] ;cin >> SampleNum ;for (i = 1 ; i <= SampleNum ; i ++){cin >> c[i] ;}NodeID = 0 ;BiTree = CreateBiTree (c , SampleNum) ;PreOrderTraverse (BiTree) ;cout << endl ;InOrderTraverse (BiTree) ;cout << endl ;PostOrderTraverse (BiTree) ;return 0 ; }

C++實現(xiàn)的非遞歸版本代碼

struct BinaryTreeNode {int val;BinaryTreeNode* leftchild;BinaryTreeNode* rightchild;BinaryTreeNode(int const& _val, BinaryTreeNode* _leftchild=NULL, BinaryTreeNode* _rightchild=NULL) :val(_val), leftchild(_leftchild), rightchild(_rightchild) {}};

??三種遍歷方式? 訪問節(jié)點的順序是一致的,不同之處在于,有的遍歷流程把訪問到的節(jié)點暫存起來,達(dá)成某種條件后再將節(jié)點輸出。約定, 根節(jié)點V, 其左孩子為L, 右孩子為R, 那么遍歷順序可以記為:

Pre-Order Traversal : 到達(dá)一個節(jié)點后,即刻輸出該節(jié)點的值,并繼續(xù)遍歷其左右子樹。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??VLR

In-Order Traversal? :? ?到達(dá)一個節(jié)點后,將其暫存,遍歷完左子樹后,再輸出該節(jié)點的值,然后遍歷右子樹。LVR

Post-Order Traversal:? ?到達(dá)一個節(jié)點后,將其暫存,遍歷完左右子樹后,再輸出該節(jié)點的值。? ? ? ? ? ? ? ? ? ? ? ? ??LRV

?

? ? ? ? ? ? ? ? ? ? ??? ? ? ? ? ? ? ? ? ??

? ? ? ? ? Pre-Order Traversal? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? In-Order Traversal? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Post-Order Traversal

?

先序遍歷

? ? ? ?

? ? ? ? ? ? ? ? ? ? ? ? ???? ? ?

?先序遍歷與中序、后序遍歷都使用了棧結(jié)構(gòu)來暫存節(jié)點

void pre_traversal(BinaryTreeNode* root) {std::stack<BinaryTreeNode*> node_stack; //用來暫存節(jié)點的棧while (root != nullptr || !node_stack.empty()) {if (root != nullptr) { //若當(dāng)前的節(jié)點非空std::cout << root->val << " "; //則輸出該節(jié)點的值node_stack.push(root); //該節(jié)點壓入棧中root = root->leftchild; //繼續(xù)向左子樹前進(jìn)}else {root = node_stack.top(); //取棧頂節(jié)點root = root->rightchild; //繼續(xù)向右子樹前進(jìn)node_stack.pop(); //刪除棧頂節(jié)點}}}

中序遍歷

與先序遍歷類似,唯一區(qū)別是到達(dá)當(dāng)前節(jié)點時? 并不直接輸出該節(jié)點。

void in_traversal(BinaryTreeNode* root) {std::stack<BinaryTreeNode*> stack_node;while (root != nullptr || !stack_node.empty()) {if (root != nullptr) {stack_node.push(root); //節(jié)點入棧root = root->leftchild; //繼續(xù)訪問左子樹直到底}else {root = stack_node.top(); //取棧頂節(jié)點std::cout << root->val << " "; //訪問節(jié)點數(shù)據(jù)root = root->rightchild; //繼續(xù)向右子樹前進(jìn)stack_node.pop(); //刪除棧頂}} }

后序遍歷

? ? ?與先序、中序遍歷有所不同,后序遍歷在決定是否可以輸出當(dāng)前節(jié)點的值的時候,需要考慮其左右子樹是否都已經(jīng)遍歷完成。

? ? ?因此我們需要設(shè)置一個lastvisit游標(biāo)。若lastvisit等于當(dāng)前考查節(jié)點的右子樹,表示該節(jié)點的左右子樹都已經(jīng)遍歷完成,則可以輸出當(dāng)前節(jié)點(否則,繼續(xù)向右子樹進(jìn)發(fā))。并把lastvisit節(jié)點設(shè)置成當(dāng)前節(jié)點,將當(dāng)前游標(biāo)節(jié)點root設(shè)置為空,下一輪就可以訪問棧頂元素。

? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

void post_traversal(BinaryTreeNode* root) {std::stack<BinaryTreeNode*> stack_node;BinaryTreeNode* lastvisit = root;while (root != nullptr || !stack_node.empty()) {if (root != nullptr) {stack_node.push(root);root = root->leftchild;}else {root = stack_node.top();if (root->rightchild == nullptr || root->rightchild == lastvisit) {std::cout << root->val << " ";stack_node.pop();lastvisit = root;root = nullptr;}else {root = root->rightchild;}}}}

下面是測試用的代碼:

int main(int argc, char* argv[]) {BinaryTreeNode* A = new BinaryTreeNode(1);BinaryTreeNode* B = new BinaryTreeNode(2);BinaryTreeNode* C = new BinaryTreeNode(4);BinaryTreeNode* D = new BinaryTreeNode(7);BinaryTreeNode* E = new BinaryTreeNode(3);BinaryTreeNode* F = new BinaryTreeNode(5);BinaryTreeNode* G = new BinaryTreeNode(6);BinaryTreeNode* H = new BinaryTreeNode(8);A->leftchild = B;A->rightchild = E;B->leftchild = C;C->rightchild = D;E->leftchild = F;E->rightchild = G;G->leftchild = H;std::cout << "Pre order traversal:" << std::endl;pre_traversal(A);std::cout << std::endl<< "In order traversal:" << std::endl;in_traversal(A);std::cout << std::endl << "Post order traversal:" << std::endl;post_traversal(A);return 0; }

?

與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的二叉树的遍历 (递归和非递归实现)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。