樹的非遞歸遍歷


一、二叉樹的非遞歸遍歷

先序遍歷:

  1、根節點p不為空,打印,根節點入棧,並將左孩子作為當前節點,左孩子即當前節點不為空,打印。。。一個while搞定

  2、若左孩子為空,跳出while循環;if stack 不為空,top棧頂作為當前節點,pop棧頂,將當前節點的右孩子作為當前節點

void preOrder(binaryTree* root) {   stack<binaryTree*> s;   binaryTree* current = root;   while(NULL != current || false == s.empty())   {     while(NULL != current)     {       cout << current->data << " ";  //打印當前節點
      s.push(current);       current = current->leftChild;     }     if( false == s.empty())     {       current = s.top();  //保存棧頂節點
      s.pop();       current = current->rightChild;     }   } }

中序遍歷:(跟前序遍歷很像,利用棧結構達到鏈表從后向前打印的效果)

void midOrder(binaryTree* root) {   stack<binaryTree*> s;   binaryTree* current = root;   while(NULL != current || false == s.empty())   {     while(NULL != current)     {       s.push(current);       current = current->leftChild;     }     if( false == s.empty())     {       current = s.top();  //保存棧頂節點
       cout << current->data << " ";  //打印當前節點
      s.pop();       current = current->rightChild;     }   } }

后續遍歷:

要保證根結點在左孩子和右孩子訪問之后才能訪問根節點;

因此對於任一結點P,先將其入棧。if P不存在左孩子和右孩子,或者P存在左孩子或者右孩子都已被訪問過了,則同樣可以直接訪問該結點。

否則,則將P的右孩子和左孩子依次入棧,這樣就保證了每次取棧頂元素的時候按照左右根的順序訪問。

void postOrder(BinTree *root)     //非遞歸后序遍歷
{ stack<BinatyTree*> s; BinatyTree *current;                      //當前結點 
    BinatyTree *pre = NULL;                 //前一次訪問的結點 
s.push(root); while(false == s.empty()) { current = s.top(); if((NULL == current->leftChild && NULL == current->rightChild) || (NULL != pre && ( pre==current->leftChild || pre==current->rightChild))) { cout<<current->data<<" "; //如果當前結點沒有孩子結點或者孩子節點都已被訪問過 s.pop(); pre = current; } else { if(NULL != current->rightChild) s.push(current->rightChild); if(NULL != current->leftChild) s.push(current->leftChild); } } }

 

二、多叉樹的遍歷

                                                                                            原文鏈接

多叉樹的節點包括當前節點pNode和以鏈表list<Node*>存儲的孩子節點

struct Node{ Node *pNode; list<Node *> childsNode; }; 

遞歸:

//前序遍歷(正序遍歷):   
void EnumNode(Node *root) { if(NULL == root)
  return;
Node* current = root;
 if(NULL != current->pNode){
 cout << root->pNode->data << " ";
}
if(NULL != current->childsNode.size){   list
<Node *>::iterator iter; //正向遍歷器   for(iter=pNode->childsNode.begin(); iter!=pNode->childsNode.end(); ++iter)   {   EnumNode(*iter);    }
  } }
//后序遍歷(反序遍歷): void REnumNode(Node *root) //考慮異常輸入,同上即可 { list<Node *>::reverse_iterator iter; //反向遍歷器 for(iter=pNode->childsNode.rbegin();iter!=pNode->childsNode.rend();++iter) { REnumNode(*iter); } cout << root->pNode->data << " "; }

非遞歸:(棧)

//多叉樹堆棧遍歷 //前序遍歷(正序遍歷):   
void EnumNode(Node *root) { if(NULL == root)
return;
stack
<Node *> stack; stack.push(root); Node *current; while(!stack.empty()) { current = stack.top(); stack.pop(); cout << current->pNode->data << " ";
    if(NULL != current->childsNode.size()){   list
<Node *>::reverse_iterator iter; //反向遍歷器   for(iter=current->childsNode.rbegin();iter!=pNode->childsNode.rend();++iter) //逆序插入棧中   {    stack.push(*
iter);   }
    } } }

 

//后序遍歷(反序遍歷): 
void REnumNode(Node *root) { if(NULL != root)    return;  stack<Node *> stack; stack.push(root); Node *current; Node *keyNode = NULL; //保存最近一次處理的節點,或者說某個節點的第一個子節點 
  while(!stack.empty()) { current = stack.top(); //keyNode是 最后一個兒子節點 到 第一個兒子節點 
//當一個兒子節點遍歷過后,再將該兒子節點賦給keyNode
//當keyNode ==
*current->childsNode.begin()
,表示第一個兒子節點已經遍歷完畢,並從棧中彈出。
    //此時當前節點為其父節點,防止current->childsNode.size()為真,繼續遍歷兒子節點,
// 所以加入keyNode != *current->childsNode.begin()避免二次遍歷兒子節點

    if (NULL != current->childsNode.size() && keyNode != *current->childsNode.begin()) //size不為0,說明current有孩子
 { list<Node *>::iterator iter; //正向遍歷器 
         for(iter = childsNode.begin();iter! = current->childsNode.end();++iter) { stack.push(*iter); } }
    
else{ cout << current->pNode->data << " "; keyNode
= current;
      stack.pop();
    }
  }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM