二叉樹的非遞迴遍歷

2021-07-25 14:56:07 字數 3671 閱讀 5426

測試環境:vs 2010

上篇文章我們實現了二叉樹:

現在,簡單說下二叉樹的非遞迴遍歷(其他函式也可按照相似的方式用非遞迴實現)。以前我們知道,凡是可用遞迴實現的**我們都可用棧來模擬它,今天就來簡單模擬實現一下二叉樹的非遞迴遍歷,上述鏈結中的其他函式也可通過棧來進行模擬,因為遍歷應用比較廣泛,所以我只對它進行改寫,其他函式有興趣的可自己仿照實現,如若有問題隨時歡迎來打擾我

1、先序遍歷

基本思想:

1>首先定義乙個棧,每遇到乙個節點,就對其資料進行訪問;然後將其入棧,將當前節點的左孩子賦給它,迴圈此過程,直到最左節點被訪問並被壓入棧中。

2>出迴圈後用臨時變數儲存棧頂節點,然後對棧頂節點進行出棧操作,到此說明當前節點以及其左子樹已被訪問過了。

3>將臨時變數的右孩子賦給當前節點,用子問題的方式去訪問其右子樹。

void preorderr(node* root)//先序遍歷列印樹的各個節點

node* top = s.top();//取出棧頂元素,到此說明此節點以及其左子樹已經訪問過了

s.pop();

cur = top->_rchild;//以子問題的方式去訪問右子樹

} cout<

2、中序遍歷

基本思想:

1>首先定義乙個棧,每遇到乙個節點,就將其入棧,將當前節點的左孩子賦給它,迴圈此過程,直到最左節點將其壓入棧中。

2>出迴圈後用臨時變數儲存棧頂節點,訪問棧頂節點的資料,然後對棧頂節點進行出棧操作,到此說明當前節點的左子樹以及當前節點已被訪問過了。

3>將臨時變數的右孩子賦給當前節點,用子問題的方式去訪問其右子樹。

void inorderr(node* root)//中序遍歷列印樹的各個節點

node* top = s.top();//取出棧頂元素,到此說明此節點的左子樹已經訪問過了

cout<_value>

s.pop();

cur = top->_rchild;//以子問題的方式去訪問右子樹

} cout<

3、後序遍歷

1>首先定義乙個棧和乙個記錄上乙個被訪問節點的變數,每遇到乙個節點,就對其資料進行訪問;然後將其入棧,將當前節點的左孩子賦給它,迴圈此過程,直到最左節點被訪問並被壓入棧中。

2>出迴圈後用臨時變數儲存棧頂元素,只有當前節點的右子樹為空或者其右子樹已經訪問過時,才能對當前節點進行訪問,同時將棧頂元素出棧

3>將臨時變數的右孩子賦給當前節點,用子問題的方式去訪問其右子樹。

void postorderr(node* root)//後序遍歷列印樹的各個節點

node* top = s.top();//取棧頂元素,但不一定能訪問

//當節點右子樹為空或已經訪問過時對其直接進行訪問

if (top->_rchild==null || top->_rchild==prev)

else//以子問題的方式去訪問右子樹

}cout<

完整的**及測試:

#include #include #include #include using namespace std;

template struct treenode

t _value;//節點的值

treenode* _lchild;//左孩子

treenode* _rchild;//右孩子

};template class binarytree

binarytree(const t* a,size_t size,const t& invalid)//建構函式

binarytree(const binarytree& b)//拷貝構造

//現**法的賦值運算子過載1

binarytree& operator=(const binarytree& b)

return *this;

} 現**法的賦值運算子過載2

//binarytree& operator=(binarytreeb)

// ~binarytree()//析構 }

void preorder()//先序遍歷列印樹的各個節點

return root;

} //拷貝物件

node* copy(node* root)

return tmp;

} //釋放空間

void destroy(node*& root) }

void preorderr(node* root)//先序遍歷列印樹的各個節點

node* top = s.top();//取出棧頂元素,到此說明此節點以及其左子樹已經訪問過了

s.pop();

cur = top->_rchild;//以子問題的方式去訪問右子樹

} cout

while(!s.empty() || cur)//只要當前節點和棧不同時為空,就說明樹沒遍歷完

node* top = s.top();//取出棧頂元素,到此說明此節點的左子樹已經訪問過了

cout<_value>

s.pop();

cur = top->_rchild;//以子問題的方式去訪問右子樹

} cout

while(!s.empty() || cur)//只要當前節點和棧不同時為空,就說明樹沒遍歷完

node* top = s.top();//取棧頂元素,但不一定能訪問

//當節點右子樹為空或已經訪問過時對其直接進行訪問

if (top->_rchild==null || top->_rchild==prev)

else//以子問題的方式去訪問右子樹

}cout

if (root)

while(!q.empty())

if (front->_rchild)

}} size_t size(node* root)//求樹中的節點個數

else

return count;

} size_t depth(node* root)//求樹的深度

else

}size_t getleafsize(node* root)//求葉節點的個數

if (null == root->_lchild && null == root->_rchild)//左葉節點右節點均為空,即

else//左子樹的葉節點+右子樹的葉節點

}size_t getklevelsize(node* root,size_t k)//樹中第k層的節點個數

if (k == 1)

else

return count;

}protected:

node* _root;//根節點

二叉樹遍歷(遞迴 非遞迴)

二叉樹以及對二叉樹的三種遍歷 先根,中根,後根 的遞迴遍歷演算法實現,以及先根遍歷的非遞迴實現。node public class node public node left public node right public object value 遍歷訪問操作介面 public inte ce ...

二叉樹非遞迴遍歷

二叉樹非遞迴遍歷的幾個要點 1 不管前序 中序還是後序,它們的遍歷路線 或者說是回溯路線,先沿左邊一直走到盡頭,然後回溯到某節點,並跳轉到該節點的右孩子 如果有的話 然後又沿著這個有孩子的左邊一直走到盡頭 都是一樣的。2 明確每次回溯的目的。比如,前序回溯的目的是為了訪問右子樹 中序回溯的目的是為了...

非遞迴遍歷二叉樹

中序遞迴遍歷 void inordertrvdigui node pnode 然而,當樹的深度很大 比如16 時 假設為滿二叉樹 樹的節點數為 2 0 2 1 2 2 2 15 2 16 65536,遍歷整個二叉樹意味著有65536次函式呼叫,這將極大地增加程式執行時間。這時,應該採取非遞迴便利二叉...