1. 程式人生 > >日常編程練習(三)

日常編程練習(三)

style tar code 依次 span 二叉 div 前序遍歷 cin

一、樹的遍歷算法

樹的創建

struct BinaryTreeNode
{
    int val;
    BinaryTreeNode* left;
    BinaryTreeNode* right;
};

void creat_tree(BinaryTreeNode* &T)
{
    char a;
    cin>>a;
    if(a==#)
        T=NULL;
    else
    {
        T=new BinaryTreeNode;
        if(T==NULL)
            return;
        T
->val=a-0; creat_tree(T->left); creat_tree(T->right); } }

前序遍歷

void pre_trave1(BinaryTreeNode* T)
{
    if(T==NULL)
        return;
    else
    {
        cout<<T->val<<" ";
        pre_trave1(T->left);
        pre_trave1(T->right);
    }
}

//非遞歸實現
void pre_trave2(BinaryTreeNode* T) { if(T==NULL) return; stack<BinaryTreeNode*> st_T; while(1) { cout<<T->val; while(T) { if(T->right) st_T.push(T->right); //先遍歷左子樹,遇到右子樹入棧 if(T->left) cout
<<T->left->val; T=T->left; } if(!st_T.empty()) { T=st_T.top(); st_T.pop(); } else break; } }

中序遍歷

void mid_trave1(BinaryTreeNode* T)
{
    if(T==NULL)
        return;
    else
    {
        mid_trave1(T->left);
        cout<<T->val<<" ";
        mid_trave1(T->right);
    }
}

//非遞歸實現
void mid_trave2(BinaryTreeNode* T)
{
    if(T==NULL)
        return;
    stack<BinaryTreeNode*> st_T;
    while(1)
    {
        while(T)
        {
            st_T.push(T);     //逢左子樹入棧
            T=T->left;
        }
        if(!st_T.empty())
        {
            T=st_T.top();
            st_T.pop();
            cout<<T->val<<" ";
            T=T->right;
        }
        else
            break;
    }
}

後序遍歷

//遞歸實現
void post_trave1(BinaryTreeNode* T)
{
    if(T==NULL)
        return;
    else
    {
        post_trave1(T->left);
        post_trave1(T->right);
        cout<<T->val<<" ";
    }
}
//非遞歸實現(破壞樹的原結構)
void post_trave2(BinaryTreeNode* T)
{
    if(T==NULL)
        return;
    stack<BinaryTreeNode*> st_T;
    while(1)
    {
        while(T)
        {
            st_T.push(T);
            T=T->left;
        }
        if(!st_T.empty())
        {
            T=st_T.top();
            if(T->right)      //第一次經過根節點後打斷與右子樹的聯系
            {
                BinaryTreeNode* temp=T->right;     
                T->right=NULL;
                T=temp;
            }
            else
            {
                st_T.pop();
                cout<<T->val<<" ";
                T=NULL;
            }

        }
        else break;
    }
}
//非遞歸實現
void post_trave3(BinaryTreeNode* T)
{
    if(T==NULL)
        return;
    stack<BinaryTreeNode*> st_T;
    BinaryTreeNode* pre;
    while(1)
    {
        while(T)
        {
            st_T.push(T);
            T=T->left;
        }
        if(!st_T.empty())
        {
            T=st_T.top();
            if(T->right&&(pre!=T->right))  //當存在右子樹且右子樹沒被打印時,先打印右子樹
            {
               T=T->right;
            }
            else
            {
                pre=T;
                st_T.pop();
                cout<<T->val<<" ";
                T=NULL;
            }
        }
        else break;
    }
}

層序遍歷

void level_trave(BinaryTreeNode* T)
{
    if(!T)
        return;
    queue<BinaryTreeNode*> qu_T;
    qu_T.push(T);
    while(!qu_T.empty())
    {
        BinaryTreeNode* temp=qu_T.front();
        qu_T.pop();
        if(temp->left!=NULL)
            qu_T.push(temp->left);
        if(temp->right!=NULL)
            qu_T.push(temp->right);
        cout<<temp->val<<" ";
    }
}

二、重建二叉樹

問題描述:輸入二叉樹的前序與中序,輸出重建的二叉樹。

//很明顯前序的首位是根結點,再從中序中查找根結點,就可以分為左右兩個子樹,依次遞歸可得。
//遞歸條件和邊界一定要分析清楚,不然很容易出錯
BinaryTreeNode* core_rebuild(vector<int>&,int,int,vector<int>&,int,int); BinaryTreeNode* rebulid_bT(vector<int>& pre,vector<int>& mid,int length) { if(!pre.size()||!mid.size()||length<=0) { return NULL; } return core_rebuild(pre,0,length-1,mid,0,length-1); } BinaryTreeNode* core_rebuild(vector<int>& pre,int pre_start,int pre_end,vector<int>& mid,int mid_start,int mid_end) { BinaryTreeNode* root=new BinaryTreeNode; root->val=pre[pre_start]; root->left=NULL; root->right=NULL; if(pre_start==pre_end) { return root; } int temp=mid_start; while(temp<=mid_end&&pre[pre_start]!=mid[temp]) temp++; int count=temp - mid_start; if(count>0) //temp不處於開始位置,則有左子樹 root->left=core_rebuild(pre,pre_start+1,pre_start+count,mid,mid_start,temp-1); if(temp!=mid_end) //temp不處於終止位置,則有右子樹 root->right=core_rebuild(pre,pre_start+count+1,pre_end,mid,temp+1,mid_end); return root; }

問題描述:輸入二叉樹的後序與中序,輸出重建的二叉樹。

BinaryTreeNode* core_rebuild2(vector<int>&,int,int,vector<int>&,int,int);
BinaryTreeNode* rebulid_bT(vector<int>& pre,vector<int>& mid,int length)
{
    if(!pre.size()||!mid.size()||length<=0)
    {
        return NULL;
    }
    return core_rebuild2(pre,0,length-1,mid,0,length-1);
}

BinaryTreeNode* core_rebuild2(vector<int>& post,int post_start,int post_end,vector<int>& mid,int mid_start,int mid_end)
{
    BinaryTreeNode* root=new BinaryTreeNode;
    root->val=post[post_end];
    root->left=NULL;
    root->right=NULL;
    if(post_start==post_end)
    {
        return root;
    }
    int temp=mid_start;
    while(post[post_end]!=mid[temp])
        temp++;
    int count=temp-mid_start;
    if(count>0)
        root->left=core_rebuild2(post,post_start,post_start+count-1,mid,mid_start,temp-1);
    if(temp<mid_end)
        root->right=core_rebuild2(post,post_start+count,post_end-1,mid,temp+1,mid_end);
    return root;
}

日常編程練習(三)