二叉链表与三叉链表应用

设计不同的结点结构可构成不同形式的链式存储结构。由二叉树的定义得知,二叉树的结点由一个数据元素和分别指向其左、右子树的两个分支构成,则表示二叉树的链表中的结点至少包含3个域:数据域和左、右指针域。有时,为了便于找到结点的双亲,则还可在结点结构中增加一个指向其双亲结点的指针域,利用这两种结点结构所得二叉树的存储结构分别称之为二叉链表和三叉链表。

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#define STACK_INIT_SIZE 100//栈存储空间初始分配量
#define STACKINCREMENT 10//栈存储空间分配增量
#define   MAXSIZE   100      //最大队列长度
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -1
typedef int Status;//定义Status函数类型为int
typedef char TElemType;//定义二叉树TElemType元素类型为char
typedef struct BiTNode1//二叉树二叉链表结构
{
    TElemType  data;
    struct BiTNode1  *lchild,*rchild;//左右孩子指针
    int weight; //标记是否遍历右孩子
} BiTNode1, *BiTree1;
typedef  BiTree1 SElemType;//定义栈元素类型为二叉树二叉链表结点
typedef struct
{
    SElemType  *base;   //栈的起始地址,当栈为空时,base的值为0
    SElemType  *top;    //栈顶指针,始终指向栈顶元素的下一位置
    int  stacksize;       //当前分配的栈的存储空间大小,以元素为单位
} SqStack; //SqStack顺序栈类型
typedef struct BiTNode2//二叉树三叉链表结构
{
    TElemType  data;
    struct BiTNode2  *parent,*lchild,*rchild;//双亲及左右孩子指针
    int weight;//标记是否遍历输出过该结点
} BiTNode2, *BiTree2;
typedef BiTree2 QElemType;//定义队列元素类型为二叉树三叉链表结点
typedef  struct
{
    QElemType  *base; //初始化动态分配存储空间
    int  front;  //头指针,若队列不空,指向队列元素
    int  rear; //尾指针,若队列不空,指向队列尾元素的下一个位置
} SqQueue; //SqQueue循环队列类型
char str[16]="abc000de0f00g00";//二叉树先序序列
int cnt1,cnt2;//二叉树先序序列计数器
Status InitStack(SqStack *S);//初始化栈S
Status Push(SqStack *S,SElemType e);//将元素e放入栈顶
Status Pop(SqStack *S,SElemType *e);//移走栈顶的元素,同时并由e返回该元素的值
Status StackEmpty(SqStack S); //判断栈是否为空
Status GetTop(SqStack S, SElemType *e);//获取栈顶的元素,但不从栈中移走
Status DestoryStack(SqStack *S);//销毁栈S,S不再存在
Status InitQueue(SqQueue *Q);//初始化队列Q
Status EnQueue(SqQueue *Q,QElemType e); //将元素e放入队尾
Status DeQueue(SqQueue *Q,QElemType *e);//移走队头元素,由e返回该元素的值
Status QueueEmpty(SqQueue Q);//判断队列是否为空
BiTree1 CreateBiTree1(BiTree1 T);//构造二叉链表表示的二叉树T1
BiTree2 CreateBiTree2(BiTree2 T);//构造三叉链表表示的二叉树T2
Status BiTreeThreading(BiTree2 T);//构造三叉链表二叉树双亲指针
Status PreorderTraverse(BiTree1 T, Status(*Visit)(TElemType e));//前序遍历二叉树T的非递归算法
Status InorderTraverse(BiTree1 T, Status(*Visit)(TElemType e));//中序遍历二叉树T的非递归算法
Status PostorderTraverse1(BiTree1 T, Status(*Visit)(TElemType e));//后序遍历二叉树T的非递归算法
Status PostorderTraverse2(BiTree2 T, Status(*Visit)(TElemType e));//无栈非递归后序遍历二叉树T
Status PrintfElement(TElemType e);//输出树元素
BiTree1 T1;//定义全局变量生成二叉链表根结点
BiTree2 T2;//定义全局变量生成三叉链表根结点
int main()
{
    printf("二叉树按先序输入的结点序列为:\nabc000de0f00g00");
    printf("\n\n二叉树二叉链表表示:");
    T1=CreateBiTree1(T1); //构造二叉链表表示的二叉树T1
    printf("\n先序遍历(非递归):");
    PreorderTraverse(T1,PrintfElement); //前序遍历二叉树T1的非递归算法
    printf("\n中序遍历(非递归):");
    InorderTraverse(T1,PrintfElement); //中序遍历二叉树T1的非递归算法
    printf("\n后序遍历(非递归):");
    PostorderTraverse1(T1,PrintfElement); //后序遍历二叉树T的非递归算法
    printf("\n\n二叉树三叉链表表示:");
    T2=CreateBiTree2(T2); //构造三叉链表表示的二叉树T2
    BiTreeThreading(T2); //构造三叉链表二叉树双亲指针
    printf("\n后序遍历(无栈非递归):");
    PostorderTraverse2(T2,PrintfElement); //无栈非递归后序遍历二叉树T2
    return 0;
}
Status InitStack(SqStack *S)//初始化栈S
{
    /* 构造一个空栈S */
    S->base=(SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));
    if(!S->base) return OVERFLOW;/*存储分配失败*/
    S->top=S->base;
    S->stacksize=STACK_INIT_SIZE;
    return OK;
}/*InitStack*/
Status Push(SqStack *S,SElemType e) //将元素e放入栈顶
{
    /* 插入元素e为新的栈顶元素 */
    if(S->top-S->base>=S->stacksize)/* 栈已满,追加空间*/
    {
        S->base=(SElemType*)realloc(S->base,(S->stacksize+STACKINCREMENT)*sizeof(SElemType));
        if(!S->base) return OVERFLOW;/*存储分配失败*/
        S->top=S->base+S->stacksize;/*求新空间的栈顶指针*/
        S->stacksize+=STACKINCREMENT;/*新空间的容量*/
    }
    *S->top=e;/*在栈顶插入元素x*/
    S->top++;/*修改栈顶指针*/
    return OK;
}/*Push*/
Status Pop(SqStack *S,SElemType *e)  //移走栈顶的元素,同时并由e返回该元素的值
{
    /*若栈不空,则删除S的栈顶元素,并用x返回其值,并返回OK,否则返回ERROR*/
    if(S->top==S->base) return ERROR;/*栈为空,返回ERROR*/
    S->top--;/*修改栈顶指针,使其指向栈顶元素*/
    *e=*S->top;
    return OK;
}
Status StackEmpty(SqStack S)   //判断栈是否为空
{
    if(S.base==S.top) return TRUE;   //若栈为空,返回TRUE
    else return FALSE;             //否则返回FALSE
}
Status GetTop(SqStack S, SElemType *e)//获取栈顶的元素,但不从栈中移走
{
    // 若栈不空,则用e返回S的栈顶元素,并返回OK;
    //否则返回ERROR
    if (S.top==S.base)  return ERROR; //若栈为空
    *e =*(S.top-1);
    return OK;
}//GetTop
Status DestoryStack(SqStack *S)//销毁栈S,S不再存在
{
    //释放栈空间,栈顶栈底指针置为NULL,长度置为0
    free(S->base);
    S->base=S->top=NULL;
    S->stacksize=0;
    return OK;
}
Status InitQueue(SqQueue *Q)//初始化队列Q
{
    //构造一个空队列Q
    Q->base=(QElemType* )malloc(MAXSIZE*sizeof(QElemType));
    if (!Q->base) exit (OVERFLOW);//存储分配失败
    Q->front = Q->rear = 0;
    return  OK;
}
Status EnQueue(SqQueue *Q,QElemType e) //将元素e放入队尾
{
    //插入元素e为Q的新的队尾元素
    if ((Q->rear+1) % MAXSIZE == Q->front) return ERROR;//队列满
    Q->base[Q->rear] = e;
    Q->rear = (Q->rear+1) % MAXSIZE;
    return OK;
}
Status DeQueue(SqQueue *Q,QElemType *e)//移走队头元素,由e返回该元素的值
{
    //若队列不空,则删除Q的队头元素,用e返回其值,并返回OK;
    //否则返回ERROR
    if (Q->front == Q->rear) return ERROR;
    *e=Q->base[Q->front];
    Q->front = (Q->front+1) % MAXSIZE;
    return OK;
}
Status QueueEmpty(SqQueue Q)//判断队列是否为空
{
    if(Q.front==Q.rear) return OK;
    return ERROR;
}
BiTree1 CreateBiTree1(BiTree1 T)//构造二叉链表表示的二叉树T1
{
    char ch=str[cnt1++];
    if(ch=='0')  T=NULL;
    else
    {
        if(!(T=(BiTree1)malloc(sizeof(BiTNode1)))) exit(OVERFLOW); /*申请一个结点空间*/
        T->data=ch;//生成根结点
        T->lchild=CreateBiTree1(T); //构造左子树
        T->rchild=CreateBiTree1(T);//构造右子树
    }
    return T; /*返回指向根结点的指针*/
}/* CreateBiTree1*/
BiTree2 CreateBiTree2(BiTree2 T)//构造三叉链表表示的二叉树T2
{
    char ch=str[cnt2++];
    if(ch=='0')  T=NULL;
    else
    {
        if(!(T=(BiTree2)malloc(sizeof(BiTNode2)))) exit(OVERFLOW); /*申请一个结点空间*/
        T->data=ch;//生成根结点
        T->weight=0;//标记清零
        T->lchild=CreateBiTree2(T); //构造左子树
        T->rchild=CreateBiTree2(T);//构造右子树
    }
    return T; /*返回指向根结点的指针*/
}/* CreateBiTree2*/
Status BiTreeThreading(BiTree2 T)//构造三叉链表二叉树双亲指针
{
    SqQueue  q;
    QElemType e;
    if (T) /* 非空树 */
    {
        T->parent = NULL; /* 根结点的双亲为"空" */
        InitQueue(&q); /* 初始化队列 */
        EnQueue(&q, T); /* 根指针入队 */
        while (!QueueEmpty(q)) /* 队不空 */
        {
            DeQueue(&q, &e); /* 出队,队列元素赋给e */
            if (e->lchild) /* 有左孩子 */
            {
                e->lchild->parent =e; /* 给左孩子的双亲指针赋值 */
                EnQueue(&q, e->lchild); /* 左孩子入队 */
            }
            if (e->rchild) /* 有右孩子 */
            {
                e->rchild->parent = e; /* 给右孩子的双亲指针赋值 */
                EnQueue(&q, e->rchild); /* 右孩子入队 */
            }
        }
    }
    return OK;
}
Status PrintfElement(TElemType e)//输出树元素
{
    printf("%c",e);
    return OK;
}
Status PreorderTraverse(BiTree1 T, Status(*Visit)(TElemType e)) //前序遍历二叉树T的非递归算法
{
    SElemType p;/*构造栈元素*/
    SqStack S;
    InitStack(&S);
    p=T;
    while(p||!StackEmpty(S))
    {
        if(p)
        {
            if(!Visit(p->data)) return ERROR;
            Push(&S, p);
            p=p->lchild;
        }  //访问根结点,根指针进栈,遍历左子树
        else   //根指针退栈,遍历右子树;
        {
            Pop(&S, &p);
            p=p->rchild;
        }
    }
    return OK;
}
Status InorderTraverse(BiTree1 T, Status(*Visit)(TElemType e)) //中序遍历二叉树T的非递归算法
{
    //采用二叉链表存储结构,visit是对数据元素操作的应用函数。
    //中序遍历二叉树T的非递归算法,对每个数据元素调用函数visit.
    SElemType p;/*构造栈元素*/
    SqStack S;/*构造顺序栈*/
    InitStack(&S);
    p=T;
    while(p||!StackEmpty(S))
    {
        if(p)
        {
            Push(&S,p);    //根指针进栈,遍历左子树
            p=p->lchild;
        }
        else   //根指针退栈,访问根结点,遍历右子树;
        {
            Pop(&S,&p);
            if(!Visit(p->data)) return ERROR;
            p=p->rchild;
        }
    }
    return OK;
}
Status PostorderTraverse1(BiTree1 T, Status(*Visit)(TElemType e))//后序遍历二叉树T的非递归算法
{
//采用二叉链表存储结构,visit是对数据元素操作的应用函数。
//中序遍历二叉树T的非递归算法,对每个数据元素调用函数visit.
    SqStack S;
    SElemType p;/*构造栈元素*/
    InitStack(&S);

    p=T;
    p->weight=0;
    while(p||!StackEmpty(S))
    {
        if(p)
        {
            Push(&S,p);    //根指针进栈,遍历左子树
            p->weight=0;//当前结点未寻找过右子树
            p=p->lchild;
        }
        else
        {
            GetTop(S,&p);
            if(p->weight==0)   //遍历右子树
            {
                p->weight=1;//标记已经寻找过右子树
                p=p->rchild;
            }
            else     //根指针退栈,访问根结点,返回上一层
            {
                Pop(&S,&p);
                if(!Visit(p->data)) return ERROR;
                p=NULL;
            }
        } //else
    } //while
    return OK;
}
Status PostorderTraverse2(BiTree2 T, Status(*Visit)(TElemType e))//无栈非递归后序遍历二叉树T
{
    while(T)
    {
        while(T->lchild && !T->lchild->weight)//如果左子树未访问,沿着树向左下方移动,
        {
            //直到不能再走为止
            T=T->lchild;
        }
        if(T->rchild && !T->rchild->weight)//如果右子树未访问,更新指针访问右子树
        {
            T=T->rchild;
        }
        else//左子树已访问或左子树不存在且右子树已访问或右子树不存在
        {
            if(!Visit(T->data)) return ERROR;//输出结点信息,标记已经访问
            T->weight=1;
            T=T->parent;                //指针返回上一层指向双亲结点
        }
    }
    return OK;
}