您的位置:首页 > 其它

二叉树的递归与非递归遍历实现

2016-03-06 20:44 417 查看
参阅资料:/article/1337341.html

二叉树是很常见的数据结构, 它的遍历方式有递归和非递归两种,其中递归方式易于实现,而非递归的方式往往效率更高,耗资源更少,各有千秋,下面就来介绍下具体的实现方法。

节点结构:

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: