測試環境: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次函式呼叫,這將極大地增加程式執行時間。這時,應該採取非遞迴便利二叉...