二叉树(1)

二叉树节点的结构

class Node{
    int value;
    Node left;
    Node right;
    Node(int data){
        this.valve=data;
        }      
}

要求掌握内容
1.能结合队列、栈、链表、字符串等很多数据结构。
2.需掌握图的遍历方式,比如BFS和DFS。
3.需掌握递归函数的使用,并自己设计出递归过程。
先序、中序和后序遍历
先序遍历:中、左、右
中序遍历:左、中、右
后序遍历:左、右、中
1
23
4567
先序:1 2 4 5 3 6 7
中序:4 2 5 1 6 3 7
后序:4 5 2 6 7 3 1

递归方式实现先序遍历

public void preOrderRecur(Node head){
     if(head==null){
     return;
     }
     System.out.print(head.valve + " ");
     preOrdeRecur(head.left);
     preOrdeRecur(head.right);
     }

思想:若树为空,返回。若不为空,先打印当前头结点的值,然后遍历左子树,最后遍历右子树。

非递归方式实现先序遍历
具体过程:
1.先申请一个新的栈,记为stack。
2.然后将头结点head压入stack中。
3.每次从stack中弹出栈顶节点,记为cur,然后打印cur节点的值。若cur右孩子不为空的话,将cur的右孩子先压入stack中。最后如果cur的左孩子不为空的话,将cur的左孩子压入stack中。
4.不断重复步骤3,直到stack为空,全部过程结束。

递归方式实现中序遍历

public void preOrderRecur(Node head){
     if(head==null){
     return;
     }
     preOrdeRecur(head.left);
     System.out.print(head.valve + " ");
     preOrdeRecur(head.right);
     }

非递归方式实现中序遍历
具体过程:
1.先申请一个新的栈,记为stack,申请一个变量cur,初始时令cur等于头节点。
2.先把cur节点压入栈中,对以cur节点为头的整棵子树来说,依次把整棵树的左边界压入栈中,即不断令cur=cur.left,然后重复步骤2。
3.不断重复步骤2,直到发现cur为空,此时从stack中弹出一个节点,记为node。打印node的值,并让cur=node.right,然后重复步骤2。
4.当stack为空并且cur为空时,整个过程结束。

递归方式实现后序遍历

public void preOrderRecur(Node head){
     if(head==null){
     return;
     }
     preOrdeRecur(head.left);
     preOrdeRecur(head.right);
     System.out.print(head.valve + " ");
     }

非递归方式实现后序遍历
方法一:使用两个栈实现
具体过程:
1.先申请一个新的栈,记为s1,然后将头结点压入s1中。
2.从s1中弹出的节点记为cur,然后先把cur的左孩子压入s1中,然后把cur1的右孩子压入s1中。
3.在整个过程中,每一个从s1中弹出的节点都放进第二个栈s2中。
4.不断重复步骤2和步骤3,直到s1为空,过程停止。
5.从s2中以此弹出节点并打印,打印的顺序就是后序遍历的顺序了。

方法二:使用一个栈实现
具体过程:
1.先申请一个新的栈,记为stack。将头节点压入stack,同时设置两个变量h和c。在整个流程中,h代表最近一次弹出并打印的节点,c代表当前stack的栈顶节点,初始时令h为头节点,c为null。
2.每次令c等于当前stack的栈顶节点,但是不从stack中弹出节点,此时分以下三种情况。
(1)如果c的左孩子不为空,并且h不等于c的左孩子,也不等于c的右孩子,则把c的左孩子压入stack中。
(2)如果情况1不成立,并且c的右孩子不为空,并且h不等于c的右孩子,则把c的右孩子压入stack中。
(3)如果情况1和情况2都不成立,那么从stack中弹出c并打印,然后令h等于c。
3.不断重复步骤2,直到stack为空,全部过程结束。

递归方式实现深度遍历

#include<iostream>
#include<string>
using namespace std;

class BinaryTreeNode  
{
public:
    char data;  
    BinaryTreeNode *Left;  
    BinaryTreeNode *Right;  
}; 

//创建二叉树,顺序依次为中间节点->左子树->右子树
void createBiTree(BinaryTreeNode* &T)   //这里加上&意思是传递的参数为指针的引用,括号里面等价于 BiTreeNode* &T
 {                                 //这样的意义在于在函数执行过后,传递进来的指针会发生改变(引用的作用),不可以去掉&
     char c;
     cin >> c;
     if('#' == c)               //当遇到#时,令树的根节点为NULL,从而结束该分支的递归
         T = NULL;
     else
     {
         T = new BinaryTreeNode;
         T->data=c;
         createBiTree(T->Left);
         createBiTree(T->Right);
     }
 }

void preorder(BinaryTreeNode* &T){
     if(T){
         cout<<T->data<<" ";
         preorder(T->Left);
         preorder(T->Right);
     }
 }

void midorder(BinaryTreeNode* &T){
     if(T){      
         midorder(T->Left);
         cout<<T->data<<" ";
         midorder(T->Right);
     }
 }

void postorder(BinaryTreeNode* &T){
     if(T){  
         postorder(T->Left);
         postorder(T->Right);
         cout<<T->data<<" ";
     }
 }

int main(){
     BinaryTreeNode* T;               //声明一个指向二叉树根节点的指针               
     createBiTree(T);
     cout<<"二叉树创建完成!"<<endl;
     cout<<"前序遍历二叉树:"<<endl;
     preorder(T);
     cout<<endl;
     cout<<"中序遍历二叉树:"<<endl;
     midorder(T);
     cout<<endl;
     cout<<"后序遍历二叉树:"<<endl;
     postorder(T);
     return 0;
}

非递归方式实现深度遍历

#include<iostream>
#include<string>
#include<stack>
using namespace std;


class BinaryTreeNode  
{
public:
    char data;  
    BinaryTreeNode *Left;  
    BinaryTreeNode *Right;  
}; 

//创建二叉树,顺序依次为中间节点->左子树->右子树

void createBiTree(BinaryTreeNode* &T)   //这里加上&意思是传递的参数为指针的引用,括号里面等价于 BiTreeNode* &T
 {                                 //这样的意义在于在函数执行过后,传递进来的指针会发生改变(引用的作用),不可以去掉&
     char c;
     cin >> c;
     if('#' == c)               //当遇到#时,令树的根节点为NULL,从而结束该分支的递归
         T = NULL;
     else
     {
         T = new BinaryTreeNode;
         T->data=c;
         createBiTree(T->Left);
         createBiTree(T->Right);
     }
 }

void preorder(BinaryTreeNode* &T){
    stack<BinaryTreeNode*> s; 
    s.push(T);
    while(!s.empty()){
        BinaryTreeNode* cur=s.top();
        s.pop();
        cout<<cur->data;
        if(cur->Right!=NULL){
           s.push(cur->Right);
        }
        if(cur->Left!=NULL){
           s.push(cur->Left);
        }
     }
 }

void midorder(BinaryTreeNode* &T){
    stack<BinaryTreeNode*> s;
    BinaryTreeNode* cur=T;
    while(cur!=NULL||!s.empty()){
        while(cur!=NULL){
            s.push(cur);
            cur=cur->Left;
         }
        BinaryTreeNode* node=s.top();
        s.pop();
        cout<<node->data;
        cur=node->Right;
    }
 }

void postorder(BinaryTreeNode* &T){
    stack<BinaryTreeNode*> s1;
    stack<BinaryTreeNode*> s2;
    s1.push(T);
    while(!s1.empty()){
        BinaryTreeNode* cur=s1.top();
        s1.pop();
        s2.push(cur);
        if(cur->Left!=NULL){
            s1.push(cur->Left);
        }
        if(cur->Right!=NULL){
            s1.push(cur->Right);
        }
    }
    while(!s2.empty()){
        BinaryTreeNode* node=s2.top();
        s2.pop();
        cout<<node->data;
    }
 }

int main(){
     BinaryTreeNode* T;               //声明一个指向二叉树根节点的指针               
     createBiTree(T);               //abd###ce##fg###
     cout<<"二叉树创建完成!"<<endl; 
     cout<<"前序遍历二叉树:"<<endl;
     preorder(T);
     cout<<endl;
     cout<<"中序遍历二叉树:"<<endl;
     midorder(T);
     cout<<endl;
     cout<<"后序遍历二叉树:"<<endl;
     postorder(T);
     cout<<endl;
     return 0;
}

总结
不管是递归方法还是非递归方法,遍历整棵树的时间复杂度都是O(N),N为二叉树节点数,额外空间复杂度为O(L),L为二叉树的层数。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值