二叉树的那些事

一篇关于二叉树的笔记。

  • 广义表生成二叉树。
  • 二叉树前、中、后序遍历递归实现。
  • 二叉树前、中、后序遍历非递归实现。
  • 二叉树层次遍历
  • 二叉排序树(二叉搜索树)生成
  • 中序线索二叉树声生成、遍历。

 

//
//  main.cpp
//  二叉树前中后缀遍历之递归和非递归、层次遍历、中序线索二叉树建立、遍历
//
//  Created by scnulpc on 2018/10/16.
//  Copyright © 2018年 scnulpc. All rights reserved.
//

#include <iostream>
#include <stack>
#include <queue>
using namespace std;
struct treeNode
{
    char value;
    int ltag;
    int rtag;
    treeNode* left;
    treeNode* right;
    treeNode(char a):value(a),ltag(0),rtag(0),left(NULL),right(NULL){}
};
struct node
{
    int value;
    node *left,*right;
    node(int a):value(a),left(NULL),right(NULL){};
};
//广义表生成二叉树-非递归
treeNode* createTreeByList(char end)
{
    char ch;
    treeNode* root=NULL,* pre = NULL,*temp;
    stack<treeNode*> *s = new stack<treeNode*>();
    cin>>ch;
    int flag=2;
    while (true)
    {
        if (ch==end) break;
        switch (ch) {
            case '(':flag=0;s->push(pre);break;
            case ',':flag=1;break;
            case ')':flag=2;s->pop();break;
            default:
                if (flag==0)//'('
                { temp=s->top(); temp->left=new treeNode(ch);pre=temp->left;}
                else if(flag==1)//','
                {temp=s->top();temp->right=new treeNode(ch);pre=temp->right;}
                else if (flag==2)//')'
                {
                    if (root==NULL) {root=new treeNode(ch);pre=root;}
                }
                break;
        }
        cin>>ch;
    }
    return root;
}

//前序遍历-递归
void preOrder(treeNode*p)
{
    if (p==NULL) return;
    cout<<p->value<<" ";
    preOrder(p->left);
    preOrder(p->right);
}
//前序遍历-非递归
void preOrderND(treeNode*p)
{
    stack<treeNode*> s;
    s.push(p);
    treeNode* temp;
    while (!s.empty())
    {
        temp=s.top();
        s.pop();
        cout<<temp->value<<" ";
        if (temp->right!=NULL) s.push(temp->right);
        if (temp->left!=NULL) s.push(temp->left);
    }
    cout<<endl;
}
//中序遍历-递归
void midOeder(treeNode* p)
{
    if (p==NULL) return;
    midOeder(p->left);
    cout<<p->value<<" ";
    midOeder(p->right);
}
//中序遍历-非递归
//对于每个结点,先将最左子孙(如果存在的话),然后再次最左子孙,再次之
void midOrderND(treeNode*p)
{
    if (p==NULL) return;
    stack<treeNode*> s;
    treeNode* current = p;
    
    while ((!s.empty())||current!=NULL)
    {
        if (current!=NULL) {
            s.push(current);
            current=current->left;
        }
        else
        {
            current=s.top();
            s.pop();
            cout<<current->value<<" ";
            current=current->right;
        }
    }
    cout<<endl;
    
}
//后缀遍历-递归
void sufixOrder(treeNode* p)
{
    if (p==NULL) return;
    sufixOrder(p->left);
    sufixOrder(p->right);
    cout<<p->value<<" ";
}
//后缀遍历-非递归
//对于一个结点,先把它的左子树输出,回到它自己,再把它的右子树输出,再回到它自己,这时可以把它自己输出了
void sufixOrderND(treeNode* p)
{
    stack<treeNode*> s;
    int flag=0;         //flag:0 表示从左子树中返回。 flag:1 表示从右子树中返回
    //int move=1;         //move:1 一棵子树还没生成。 move:0 已经生成一颗子树,说明可以直接出栈回退
    treeNode* current=p;
    while (!s.empty()||current!=NULL)
    {
        if (current!=NULL) {
            s.push(current);
            current=current->left;
            flag=0;
        }
        else
        {
            if (flag)//从右子树中返回
            {
                current=s.top();s.pop();
                cout<<current->value<<" ";  //访问根结点
                
                // 从根结点返回判断current结点是父结点的左孩子还是右孩子
                if (s.empty()) break;
                treeNode* temp = s.top();
                if (current==temp->left) flag=0;
                else if (current==temp->right) flag=1;
                current=NULL;
                
            }
            else    //从左子树中返回
            {
                current=s.top();
                current=current->right;
                flag=1;
                
            }
        }
    }
    cout<<endl;
}
void LayerPrint(treeNode* p)
{
    queue<treeNode*> q;
    q.push(p);
    treeNode* current;
    while (!q.empty())
    {
        current=q.front();
        q.pop();
        cout<<current->value<<" ";
        if (current->left!=NULL) q.push(current->left);
        if (current->right!=NULL) q.push(current->right);
    }
    cout<<endl;
}
void Insert(node*& p,int value) //在以p为根节点的线索二叉树中插入一个数value
{
    if (p==NULL) {p=new node(value);return;}
    if(p->value==value) return ;
    if (value<p->value) Insert(p->left, value);
    if (value>p->value) Insert(p->right, value);
}
node* createSearchBinaryTree(int a[],int length)
{
    node* root =NULL;
    for (int i=0; i<length; i++) {
        Insert(root, a[i]);
    }
    return root;
}
void print(node *p)
{
    if (p==NULL) return;
    print(p->left);
    cout<<p->value<<" ";
    print(p->right);
}

//一般完全二叉树 生成 中序线索二叉树
treeNode*  first(treeNode* p)//找到以结点p为根节点的子树在中序下的第一个结点
{
    if (p==NULL) return p;
    while (p->ltag==0) {
        p=p->left;
    }
    return p;
}
treeNode* last(treeNode* p)//找到以结点p为根节点的树在中序下的最后一个结点
{
    if (p==NULL) return NULL;
    while (p->rtag==0) {
        p=p->right;
    }
    return p;
}
void createMidThreadBinaryTree(treeNode* p,treeNode* &pre) //线索化以p为根的子树  pre: p的在中序遍历下的前驱
{
    if(p==NULL)return;
    createMidThreadBinaryTree(p->left, pre);
    if (p->left==NULL&&p->ltag==0) {p->left=pre;p->ltag=1;}     //线索化p的前驱
    if(pre!=NULL&&pre->right==NULL){pre->right=p;pre->rtag=1;}  //线索化前驱pre的后继
    pre=p;
    createMidThreadBinaryTree(p->right, pre);
}
void createMidThreadBinaryTree(treeNode* p)
{
    treeNode* t = NULL;
    createMidThreadBinaryTree(p, t);
    if (p==NULL) return;
    treeNode* temp = p;     //别忘了最后一个结点的后驱置空
    while (temp->right!=NULL) {
        temp=temp->right;
    }
    temp->rtag=1;
    
}
//遍历中序线索二叉树

treeNode* Next(treeNode* p)//找到结点P的后驱
{
    if (p==NULL) return NULL;
    if (p->rtag==1) return p->right;
    else return first(p->right);
    
}
void printMidThreadBinaryTree(treeNode* p)
{
    treeNode* one = first(p);
    if (one==NULL) return;
    cout<<one->value<<" ";
    treeNode* next = Next(one);
    while (next!=NULL) {
        cout<<next->value<<" ";
        next = Next(next);
    }
    cout<<endl;
    
}
//A(B(C(D,E)),F(G,H))#
int main(int argc, const char * argv[])
{
    treeNode* head = NULL;
    cout<<"输入广义表,以#结束"<<endl;
    head=createTreeByList('#');
    cout<<"前序遍历"<<endl;
    preOrder(head);
    cout<<endl;
    preOrderND(head);
    cout<<"中序遍历"<<endl;
    midOeder(head);
    cout<<endl;
    midOrderND(head);
    cout<<"后缀遍历"<<endl;
    sufixOrder(head);
    cout<<endl;
    sufixOrderND(head);
    cout<<"层次遍历"<<endl;
    LayerPrint(head);
    cout<<"生成二叉搜索树"<<endl;
    int a[] = {2,3,7,8,9,5,1,4,0,13,7,8,9,23};
    node * root = createSearchBinaryTree(a,14);
    print(root);
    cout<<endl;
    
    cout<<"生成中序线索二叉树"<<endl;
    createMidThreadBinaryTree(head);
    cout<<"遍历中序线索二叉树"<<endl;
    printMidThreadBinaryTree(head);
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值