参阅资料:http://blog.csdn.net/ns_code/article/details/12977901
二叉树是很常见的数据结构, 它的遍历方式有递归和非递归两种,其中递归方式易于实现,而非递归的方式往往效率更高,耗资源更少,各有千秋,下面就来介绍下具体的实现方法。
节点结构:
typedef struct Node{
int val;
Node* left;
Node* right;
Node(int val) : val(val), left(NULL), right(NULL) {}
} *pNode;
先序遍历:
递归方式:
首先遍历其根结点,然后遍历左子树,最后遍历右子树,对于其子树的遍历方式同上。
void BST::Recursion_preOrder_Traverse(pNode node){
if(node){
printf("%d ", node->val);
Recursion_preOrder_Traverse(node->left);
Recursion_preOrder_Traverse(node->right);
}
}
非递归方式:
无非就是模拟递归,这里我们用栈模拟。
首先设置一个当前指针curNode,用于指向当前需要操作的节点。
1:对于一个节点,我们输出它的值,将其入栈,并判断左子树是否为空
2:如果不为空,那么curNode指向它,重复1
3:如果为空,说明此时左子树已经遍历完毕,并令当前节点出栈,因为已经遍历过了,令curNode指向当前节点的右节点,判断curNode是否为空。
4:如果不为空,重复1
5:如果为空,说明其没有右子树,继续出栈,重复4、5
6:如果当前curNode为空并且栈为空,则遍历完毕。
void BST::Non_Recursion_preOrder_Traverse(pNode root){
stack<pNode> pNode_stack;
pNode curNode = root;
while(curNode != NULL || !pNode_stack.empty()){
printf("%d ", curNode->val);
pNode_stack.push(curNode);
curNode = curNode->left;
while(!curNode && !pNode_stack.empty()){//当指针为空并且栈内有元素时,就可以取出来遍历右子树了
curNode = pNode_stack.top();
pNode_stack.pop();
curNode = curNode->right;
}
}
}
中序遍历:
递归方式:
首先遍历其左子树,然后输出自己的值,最后遍历右子树,对于其子树的遍历方式同上。
void BST::Recursion_inOrder_Traverse(pNode node){
if(node){
Recursion_inOrder_Traverse(node->left);
printf("%d ", node->val);
Recursion_inOrder_Traverse(node->right);
}
}
非递归方式:
1:若当前节点左子树不为空,则将该节点入栈,重复1
2:若当前节点左子树为空,则输出其值(注意这里并没有将该节点入栈),curNode指向它的右子树,判断是否为空
3:若不为空,则重复1、2
4:若为空,则将栈顶元素取出,输出其值,curNode指向它的右子树,判断其是否为空,重复3、4
5:如果当前curNode为空并且栈为空,则遍历完毕。
void BST::Non_Recursion_inOrder_Traverse(pNode root){
stack<pNode> pNode_stack;
pNode curNode = root;
while(curNode != NULL || !pNode_stack.empty()){
if(curNode->left != NULL){
pNode_stack.push(curNode);
curNode = curNode->left;
}
else{
printf("%d ", curNode->val);
curNode = curNode->right;
while(!curNode && !pNode_stack.empty()){
//此时curNode的左子树全部遍历完毕,输出自己
curNode = pNode_stack.top();
printf("%d ", curNode->val);
pNode_stack.pop();
curNode = curNode->right;
}
}
}
}
后序遍历:
递归方式:
首先遍历左子树,然后遍历右子树,最后输出自己,对于其子树的遍历方式同上。
void BST::Recursion_postOrder_Traverse(pNode node){
if(node){
Recursion_postOrder_Traverse(node->left);
Recursion_postOrder_Traverse(node->right);
printf("%d ", node->val);
}
}
非递归方式:
这里要多加一个记录上一个访问节点的preNode
1:首先将节点入栈
2:如果单签节点是叶子节点或者它的左右孩子已经有输出的了,则将其直接输出并出栈,将栈顶节点设为curNode并将出栈节点设为preNode
3:若2不满足,则将该节点的右孩子和左孩子依次入栈,重复2
4:若栈为空,则遍历结束。
void BST::Non_Recursion_postOrder_Traverse(pNode root){
stack<pNode> pNode_stack;
pNode curNode = root;
pNode preNode = NULL;
pNode_stack.push(curNode);
while(!pNode_stack.empty()){
curNode = pNode_stack.top();
if((curNode->left == NULL && curNode->right == NULL) ||
(preNode != NULL && (curNode->left == preNode || curNode->right == preNode))){
printf("%d ", curNode->val);
pNode_stack.pop();
preNode = curNode;
}
else{
if(curNode->right != NULL)
pNode_stack.push(curNode->right);
if(curNode->left != NULL)
pNode_stack.push(curNode->left);
}
}
}
程序总览:
#include <cstdio>
#include <stack>
using namespace std;
typedef struct Node{
int val;
Node* left;
Node* right;
Node(int val) : val(val), left(NULL), right(NULL) {}
} *pNode;
class BST{
private:
pNode root;
void Non_Recursion_Insert_Node(pNode *root, int x);
void Non_Recursion_postOrder_Traverse(pNode root);
void Recursion_postOrder_Traverse(pNode node);
void Non_Recursion_inOrder_Traverse(pNode root);
void Recursion_inOrder_Traverse(pNode root);
void Recursion_Delete_BST(pNode node);
void Non_Recursion_preOrder_Traverse(pNode root);
void Recursion_preOrder_Traverse(pNode node);
public:
void Non_Recursion_Insert_Node(int x);
void Non_Recursion_postOrder_Traverse();
void Recursion_postOrder_Traverse();
void Non_Recursion_inOrder_Traverse();
void Recursion_inOrder_Traverse();
void Non_Recursion_preOrder_Traverse();
void Recursion_preOrder_Traverse();
void Build_BST(int *num, int n);
BST();
~BST();
};
void BST::Build_BST(int *num, int n){
for(int i = 0; i < n; i++){
Non_Recursion_Insert_Node(&this->root, num[i]);
}
}
void BST::Non_Recursion_Insert_Node(int x){
Non_Recursion_Insert_Node(&this->root, x);
}
void BST::Non_Recursion_Insert_Node(pNode *root, int x){
pNode child = *root;
pNode parent = NULL;
while(child != NULL){
parent = child;
if(child->val > x){
child = child->left;
}
else{
child = child->right;
}
}
if(parent == NULL){
*root = new Node(x);
}
else if(parent->val > x){
parent->left = new Node(x);
}
else{
parent->right = new Node(x);
}
}
void BST::Non_Recursion_preOrder_Traverse(){
Non_Recursion_preOrder_Traverse(this->root);
}
void BST::Non_Recursion_preOrder_Traverse(pNode root){
stack<pNode> pNode_stack;
pNode curNode = root;
while(curNode != NULL || !pNode_stack.empty()){
printf("%d ", curNode->val);
pNode_stack.push(curNode);
curNode = curNode->left;
while(!curNode && !pNode_stack.empty()){//当指针为空并且栈内有元素时,就可以取出来遍历右子树了
curNode = pNode_stack.top();
pNode_stack.pop();
curNode = curNode->right;
}
}
}
void BST::Recursion_preOrder_Traverse(pNode node){
if(node){
printf("%d ", node->val);
Recursion_preOrder_Traverse(node->left);
Recursion_preOrder_Traverse(node->right);
}
}
void BST::Recursion_preOrder_Traverse(){
Recursion_preOrder_Traverse(this->root);
}
void BST::Non_Recursion_inOrder_Traverse(){
Non_Recursion_inOrder_Traverse(this->root);
}
void BST::Non_Recursion_inOrder_Traverse(pNode root){
stack<pNode> pNode_stack;
pNode curNode = root;
while(curNode != NULL || !pNode_stack.empty()){
if(curNode->left != NULL){
pNode_stack.push(curNode);
curNode = curNode->left;
}
else{
printf("%d ", curNode->val);
curNode = curNode->right;
while(!curNode && !pNode_stack.empty()){
//此时curNode的左子树全部遍历完毕,输出自己
curNode = pNode_stack.top();
printf("%d ", curNode->val);
pNode_stack.pop();
curNode = curNode->right;
}
}
}
}
void BST::Recursion_inOrder_Traverse(pNode node){
if(node){
Recursion_inOrder_Traverse(node->left);
printf("%d ", node->val);
Recursion_inOrder_Traverse(node->right);
}
}
void BST::Recursion_inOrder_Traverse(){
Recursion_inOrder_Traverse(this->root);
}
void BST::Non_Recursion_postOrder_Traverse(){
Non_Recursion_postOrder_Traverse(this->root);
}
void BST::Non_Recursion_postOrder_Traverse(pNode root){
stack<pNode> pNode_stack;
pNode curNode = root;
pNode preNode = NULL;
pNode_stack.push(curNode);
while(!pNode_stack.empty()){
curNode = pNode_stack.top();
if((curNode->left == NULL && curNode->right == NULL) ||
(preNode != NULL && (curNode->left == preNode || curNode->right == preNode))){
//如果当前节点为叶子节点或者它的子节点有已经输出的 那么就输出这个节点
//为什么任意左右节点只要有输出的,该节点就会输出呢?这是因为底下的else决定的
//访问该节点之前一定会访问它的左右子节点,如果preNode保存的是它的左节点,那么
//一定不存在右节点,当然下一个会访问他自己,如果perNode保存的是右节点,则说明
//左节点已经被访问完毕,这是由入栈顺序决定的。
printf("%d ", curNode->val);
pNode_stack.pop();
preNode = curNode;
}
else{
if(curNode->right != NULL)
pNode_stack.push(curNode->right);
if(curNode->left != NULL)
pNode_stack.push(curNode->left);
}
}
}
void BST::Recursion_postOrder_Traverse(pNode node){
if(node){
Recursion_postOrder_Traverse(node->left);
Recursion_postOrder_Traverse(node->right);
printf("%d ", node->val);
}
}
void BST::Recursion_postOrder_Traverse(){
Recursion_postOrder_Traverse(this->root);
}
void BST::Recursion_Delete_BST(pNode node){
if(node == NULL)
return;
if(node->left != NULL)
Recursion_Delete_BST(node->left);
if(node->right != NULL)
Recursion_Delete_BST(node->right);
delete node;
}
BST::BST(){
root = NULL;
}
BST::~BST(){
Recursion_Delete_BST(this->root);
}
int main()
{
return 0;
}