数据结构——树的相关算法实现

二叉树的基本算法

包括二叉树的遍历(先、中、后),二叉树的层次,二叉树的深度,二叉树的叶子节点数计算。相关算法思想可以看书,这里只是给出相关算法实现。

代码实现

#include 
#include 
#define MAXSIZE 30

typedef char ElemType;

typedef struct TNode {
    char data;
    TNode * lchild; 
    TNode * rchild;
}TNode, *BiTree;


int IsEmpty_BiTree(BiTree *T) {
    if(*T == NULL)
    return 1;//如果树为空一直进入死循环,直到输入数据为止 
    else
    return 0;
}

void Create_BiTree(BiTree *T){
    char ch;
    ch = getchar();
    //当输入的是"#"时,认为该子树为空
    if(ch == '#')
        *T = NULL;
    //创建树结点
    else{
        *T = (BiTree)malloc(sizeof(struct TNode));
        (*T)->data = ch; //生成树结点
        //生成左子树
        Create_BiTree(&(*T)->lchild);
        //生成右子树
        Create_BiTree(&(*T)->rchild);
    }
}

void TraverseBiTree(BiTree T) { //先序遍历 
    if(T == NULL)//指针为空,说明节点不存在 
    return; 
    else {
        printf("%c ",T->data);
        TraverseBiTree(T->lchild);
        TraverseBiTree(T->rchild);
    }
    
}

void InOrderBiTree(BiTree T) {      //中序遍历 
    if(NULL == T)
    return;
    else {
        InOrderBiTree(T->lchild);
        printf("%c ",T->data);
        InOrderBiTree(T->rchild);   
    }
}

void PostOrderBiTree(BiTree T) {
    if(NULL == T)
    return;
    else {
        InOrderBiTree(T->lchild);
        InOrderBiTree(T->rchild);
        printf("%c ",T->data);
    }
    
} 

int TreeDeep(BiTree T) {
    int deep = 0;
    if(T)
    {
        int leftdeep = TreeDeep(T->lchild);
        int rightdeep = TreeDeep(T->rchild);
        deep = leftdeep+1 > rightdeep+1 ? leftdeep+1 : rightdeep+1; 
    }
    return deep;
}
//树的叶子结点为 
int Leafcount(BiTree T, int &num) {//一般涉及到变化的都会取地址 
    if(T)
    {
        if(T->lchild ==NULL && T->rchild==NULL) 
        {
            num++;
            printf("%c ",T->data);
        }           
        Leafcount(T->lchild,num);
        Leafcount(T->rchild,num);

    }
    return num;
}

//树的层次显示 (利用队列,先进先出的原则可以完美实现) 
void LevelOrder_BiTree(BiTree T){
    //用一个队列保存结点信息,这里的队列采用的是顺序队列中的数组实现
    int front = 0;
    int rear = 0;
    BiTree BiQueue[MAXSIZE];
    BiTree tempNode;
    if(!IsEmpty_BiTree(&T)){
        BiQueue[rear++] = T;
         
        while(front != rear){// 
            //取出队头元素,并使队头指针向后移动一位 
            tempNode = BiQueue[front++];
            //判断左右子树是否为空,若不为空,则加入队列 
            if(!IsEmpty_BiTree(&(tempNode->lchild)))
                BiQueue[rear++] = tempNode->lchild;
             
            if(!IsEmpty_BiTree(&(tempNode->rchild)))
                BiQueue[rear++] = tempNode->rchild;
             
             printf("%c ",tempNode->data);
        }
    }
}

int main(void)
{
    BiTree T;
    BiTree *p = (BiTree*)malloc(sizeof(BiTree));
    int deepth,num=0 ;
    Create_BiTree(&T);//一般涉及到变化的都会取地址 
    printf("先序遍历二叉树:\n");
    TraverseBiTree(T);
    printf("\n");
    printf("中序遍历二叉树:\n");
    InOrderBiTree(T);
    printf("\n");
    printf("后序遍历二叉树:\n");
    PostOrderBiTree(T);
    printf("\n层次遍历结果:");
    LevelOrder_BiTree(T);
    printf("\n");
    deepth=TreeDeep(T);
    printf("树的深度为:%d",deepth);
    printf("\n");
    printf("树的叶子结点为:");
    Leafcount(T,num);
    printf("\n树的叶子结点个数为:%d",num);
    return 0;
}

运行演示

线索二叉树的中序遍历

#include
#include 
using namespace std;

typedef struct BiThrNode
{
    char data;
    struct BiThrNode *lchild,*rchild;      /*左右孩子指针*/
    int LTag,RTag;                          /*左右标志*/
}BiThrNode,*BiThrTree;

BiThrTree pre;



void CreateBiTree(BiThrTree *T){
    char ch;
    ch = getchar();
    //当输入的是"#"时,认为该子树为空
    if(ch == '#')
        *T = NULL;
    //创建树结点
    else{
        *T = (BiThrTree)malloc(sizeof(struct BiThrNode));
        (*T)->data = ch; //生成树结点
        //生成左子树
        CreateBiTree(&(*T)->lchild);
        //生成右子树
        CreateBiTree(&(*T)->rchild);
    }
}

/*以结点p为根的子树中序线索化*/
void InThreading(BiThrTree p)
{
    /*pre是全局变量,初始化时其右孩子指针为空,便于在树的最左点开始建线索*/
    if(p)
    {
        InThreading(p->lchild);            /*左子树递归线索化*/
        if(!(p->lchild) )                      /*p的左孩子为空*/
        {                  
            p->LTag=1;                     /*给p加上左线索*/
            p->lchild=pre;                 /*p的左孩子指针指向pre(前驱)*/
        }
        else
        {
            p->LTag=0;
        }
        if(!(pre->rchild) )                  /*pre的右孩子为空*/
        {
            pre->RTag=1;                  /*给pre加上右线索*/
            pre->rchild=p;                /*pre的右孩子指针指向p(后继)*/
        }
        else
        {
            pre->RTag=0;
        }
        pre=p;                            /*保持pre指向p的前驱*/
        InThreading(p->rchild);           /*右子树递归线索化*/
    }
}
/*带头结点的中序线索化*/
void InOrderThreading(BiThrTree &Thrt,BiThrTree T)
{
    /*中序遍历二叉树T,并将其中序线索化,Thrt指向头结点*/
    Thrt=new BiThrNode;         /*建头结头*/
    Thrt->LTag=0;               /*头结点有左孩子,若树非空,则其左孩子为树根*/       
    Thrt->RTag=1;               /*头结点的右孩子指针为右线索*/
    Thrt->rchild=Thrt;          /*初始化时右指针指向自己*/
    if(!T) Thrt->lchild=Thrt;   /*若树为空,则左指针也指向自己*/
    else
    {
        Thrt->lchild=T; pre=Thrt; /*头结点的左孩子指向根,pre初值指向头结点*/
        InThreading(T);          /*调用上述算法,对以T为根的二叉树进行中序线索化*/
        pre->rchild=Thrt;        /*算法结束后,pre为最右结点,pre的右线索指向头结点*/
        pre->RTag=1;
        Thrt->rchild=pre;        /*头结点的右线索指向pre*/
    } 
}  
/*遍历中序线索二叉树*/
void InOrderTraverse_Thr(BiThrTree T)
{
    /*T指向头结点,头结点的左链lchild指向根结点*/
    /*中序遍历二叉线索树T的非递归算法,对每个数据元素直接输出*/
    BiThrTree p=T->lchild;    /*p指向根结点*/        
    while(p!=T)
    {
        while(p->LTag == 0)      /*沿左孩子向下*/
        {
             p=p->lchild;
        }
        cout<data<<" ";           /*访问其左子树为空的结点*/
        while(p->RTag == 1 && p->rchild!=T)  /*沿右线索访问后继结点*/
        {
            p=p->rchild;
            cout<data<<" ";
        }
        p=p->rchild;
    }
    cout<data;
}
int main()
{
    BiThrTree T;
    BiThrTree Thrt;
    cout<<"Input the Threaded BinaryTree 's node:"<

运行演示

二叉树结构图

参考文献

  • 数据结构-用C语言描述(第二版)[耿国华]

你可能感兴趣的:(数据结构——树的相关算法实现)