[数据结构]树与二叉树

1.4 树和二叉树

1.4.1 获得二叉树的深度和根(顺序结构)

#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<math.h> /* floor(),ceil(),abs() */

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
#if CHAR
typedef char TElemType;
  TElemType Nil=' '; /* 设字符型以空格符为空 */
#else
typedef int TElemType;
TElemType Nil = 0; /* 设整型以0为空 */
#endif
#define MAX_TREE_SIZE 100 /* 二叉树的最大结点数 */
typedef TElemType SqBiTree[MAX_TREE_SIZE]; /* 0号单元存储根结点 */
Status InitBiTree(SqBiTree T) { /* 构造空二叉树T。因为T是固定数组,不会改变,故不需要& */
    int i;
    for (i = 0; i < MAX_TREE_SIZE; i++)
        T[i] = Nil; /* 初值为空 */
    return OK;
}

Status CreateBiTree(SqBiTree T) { /* 按层序次序输入二叉树中结点的值(字符型或整型), 构造顺序存储的二叉树T */
    int i = 0;
#if CHAR
    int l;
  char s[MAX_TREE_SIZE];
  printf("请按层序输入结点的值(字符),空格表示空结点,结点数≤%d:\n",MAX_TREE_SIZE);
  gets(s); /* 输入字符串 */
  l=strlen(s); /* 求字符串的长度 */
  for(;i<l;i++) /* 将字符串赋值给T */
  {
    T[i]=s[i];
    if(i!=0&&T[(i+1)/2-1]==Nil&&T[i]!=Nil) /* 此结点(不空)无双亲且不是根 */
    {
      printf("出现无双亲的非根结点%c\n",T[i]);
      exit(ERROR);
    }
  }
  for(i=l;i<MAX_TREE_SIZE;i++) /* 将空赋值给T的后面的结点 */
    T[i]=Nil;
#else
    printf("请按层序输入结点的值(整型),0表示空结点,输999结束。结点数≤%d:\n", MAX_TREE_SIZE);
    while (1) {
        scanf("%d", &T[i]);
        if (T[i] == 999)
            break;
        if (i != 0 && T[(i + 1) / 2 - 1] == Nil && T[i] != Nil) /* 此结点(不空)无双亲且不是根 */
        {
            printf("出现无双亲的非根结点%d\n", T[i]);
            exit(ERROR);
        }
        i++;
    }
    while (i < MAX_TREE_SIZE) {
        T[i] = Nil; /* 将空赋值给T的后面的结点 */
        i++;
    }
#endif
    return OK;
}

Status BiTreeEmpty(SqBiTree T) { /* 初始条件: 二叉树T存在 */
    /* 操作结果: 若T为空二叉树,则返回TRUE,否则FALSE */
    if (T[0] == Nil) /* 根结点为空,则树空 */
        return TRUE;
    else
        return FALSE;
}

int BiTreeDepth(SqBiTree T) { /* 初始条件: 二叉树T存在。操作结果: 返回T的深度 */
    int i, j = -1;
    for (i = MAX_TREE_SIZE - 1; i >= 0; i--) /* 找到最后一个结点 */
        if (T[i] != Nil)
            break;
    i++; /* 为了便于计算 */
    do
        j++;
    while (i >= pow(2, j));
    return j;
}

Status Root(SqBiTree T, TElemType *e) { /* 初始条件: 二叉树T存在 */
    /* 操作结果:  当T不空,用e返回T的根,返回OK;否则返回ERROR,e无定义 */
    if (BiTreeEmpty(T)) /* T空 */
        return ERROR;
    else {
        *e = T[0];
        return OK;
    }
}

int main() {
    Status i;
    TElemType e;
    SqBiTree T;
    InitBiTree(T);
    CreateBiTree(T);
    printf("建立二叉树后,树空否?%d(1:是 0:否) 树的深度=%d\n", BiTreeEmpty(T), BiTreeDepth(T));
    i = Root(T, &e);
    if (i)
        printf("二叉树的根为:%d\n", e);
    else
        printf("树空,无根\n");
    return 0;
}

运行结果

1.4.2 获得二叉树的深度和根(链表结构)

#define CHAR /* 字符型 */

#include <stdio.h> /* EOF(=^Z或F6),NULL */
#include <math.h> /* floor(),ceil(),abs() */
#include <stdlib.h>

#define TRUE 1
#define FALSE 0
#define OK 1
#define OVERFLOW 3
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
#ifdef CHAR
typedef char TElemType;
TElemType Nil = ' '; /* 字符型以空格符为空 */
#endif
#ifdef INT
typedef int TElemType;
   TElemType Nil=0; /* 整型以0为空 */
#endif
typedef struct BiTNode {
    TElemType data;
    struct BiTNode *lchild, *rchild; /* 左右孩子指针 */
} BiTNode, *BiTree;

Status InitBiTree(BiTree *T) { /* 操作结果: 构造空二叉树T */
    *T = NULL;
    return OK;
}

void CreateBiTree(BiTree *T) {
    TElemType ch;
#ifdef CHAR
    scanf("%c", &ch);
#endif
#ifdef INT
    scanf("%d",&ch);
#endif
    if (ch == Nil) /* 空 */
        *T = NULL;
    else {
        *T = (BiTree) malloc(sizeof(BiTNode));
        if (!*T)
            exit(OVERFLOW);
        (*T)->data = ch; /* 生成根结点 */
        CreateBiTree(&(*T)->lchild); /* 构造左子树 */
        CreateBiTree(&(*T)->rchild); /* 构造右子树 */
    }
}

Status BiTreeEmpty(BiTree T) { /* 初始条件: 二叉树T存在 */
    /* 操作结果: 若T为空二叉树,则返回TRUE,否则FALSE */
    if (T)
        return FALSE;
    else
        return TRUE;
}

int BiTreeDepth(BiTree T) { /* 初始条件: 二叉树T存在。操作结果: 返回T的深度 */
    int i, j;
    if (!T)
        return 0;
    if (T->lchild)
        i = BiTreeDepth(T->lchild);
    else
        i = 0;
    if (T->rchild)
        j = BiTreeDepth(T->rchild);
    else
        j = 0;
    return i > j ? i + 1 : j + 1;
}

TElemType Root(BiTree T) { /* 初始条件: 二叉树T存在。操作结果: 返回T的根 */
    if (BiTreeEmpty(T))
        return Nil;
    else
        return T->data;
}

int main() {
    BiTree T;
    TElemType e1;
    InitBiTree(&T);
    printf("构造空二叉树后,树空否?%d(1:是 0:否) 树的深度=%d\n", BiTreeEmpty(T), BiTreeDepth(T));
    e1 = Root(T);
    if (e1 != Nil)
#ifdef CHAR
        printf("二叉树的根为: %c\n", e1);
#endif
#ifdef INT
        printf("二叉树的根为: %d\n",e1);
#endif
    else
        printf("树空,无根\n");
#ifdef CHAR
    printf("请先序输入二叉树(如:ab三个空格表示a为根结点,b为左子树的二叉树)\n");
#endif
#ifdef INT
    printf("请先序输入二叉树(如:1 2 0 0 0表示1为根结点,2为左子树的二叉树)\n");
#endif
    CreateBiTree(&T);
    printf("建立二叉树后,树空否?%d(1:是 0:否) 树的深度=%d\n", BiTreeEmpty(T), BiTreeDepth(T));
    e1 = Root(T);
    if (e1 != Nil)
#ifdef CHAR
        printf("二叉树的根为: %c\n", e1);
#endif
#ifdef INT
        printf("二叉树的根为: %d\n",e1);
#endif
    else
        printf("树空,无根\n");
}

运行结果

1.4.3 树的插入(顺序结构)

#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<stdlib.h>
#include <math.h>

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
#if CHAR
typedef char TElemType;
  TElemType Nil=' '; /* 设字符型以空格符为空 */
#else
typedef int TElemType;
TElemType Nil=0; /* 设整型以0为空 */
#endif
#define MAX_TREE_SIZE 100 /* 二叉树的最大结点数 */
typedef TElemType SqBiTree[MAX_TREE_SIZE]; /* 0号单元存储根结点 */
typedef struct
{
    int level,order; /* 结点的层,本层序号(按满二叉树计算) */
}position;
Status InitBiTree(SqBiTree T)
{ /* 构造空二叉树T。因为T是固定数组,不会改变,故不需要& */
    int i;
    for(i=0;i<MAX_TREE_SIZE;i++)
        T[i]=Nil; /* 初值为空 */
    return OK;
}
Status CreateBiTree(SqBiTree T)
{ /* 按层序次序输入二叉树中结点的值(字符型或整型), 构造顺序存储的二叉树T */
    int i=0;
#if CHAR
    int l;
  char s[MAX_TREE_SIZE];
  printf("请按层序输入结点的值(字符),空格表示空结点,结点数≤%d:\n",MAX_TREE_SIZE);
  gets(s); /* 输入字符串 */
  l=strlen(s); /* 求字符串的长度 */
  for(;i<l;i++) /* 将字符串赋值给T */
  {
    T[i]=s[i];
    if(i!=0&&T[(i+1)/2-1]==Nil&&T[i]!=Nil) /* 此结点(不空)无双亲且不是根 */
    {
      printf("出现无双亲的非根结点%c\n",T[i]);
      exit(ERROR);
    }
  }
  for(i=l;i<MAX_TREE_SIZE;i++) /* 将空赋值给T的后面的结点 */
    T[i]=Nil;
#else
    printf("请按层序输入结点的值(整型),0表示空结点,输999结束。结点数≤%d:\n",MAX_TREE_SIZE);
    while(1)
    {
        scanf("%d",&T[i]);
        if(T[i]==999)
            break;
        if(i!=0&&T[(i+1)/2-1]==Nil&&T[i]!=Nil) /* 此结点(不空)无双亲且不是根 */
        {
            printf("出现无双亲的非根结点%d\n",T[i]);
            exit(ERROR);
        }
        i++;
    }
    while(i<MAX_TREE_SIZE)
    {
        T[i]=Nil; /* 将空赋值给T的后面的结点 */
        i++;
    }
#endif
    return OK;
}
int BiTreeDepth(SqBiTree T)
{ /* 初始条件: 二叉树T存在。操作结果: 返回T的深度 */
    int i,j=-1;
    for(i=MAX_TREE_SIZE-1;i>=0;i--) /* 找到最后一个结点 */
        if(T[i]!=Nil)
            break;
    i++; /* 为了便于计算 */
    do
        j++;
    while(i>=pow(2,j));
    return j;
}
TElemType Value(SqBiTree T,position e)
{ /* 初始条件: 二叉树T存在,e是T中某个结点(的位置) */
    /* 操作结果: 返回处于位置e(层,本层序号)的结点的值 */
    return T[(int)pow(2,e.level-1)+e.order-2];
}
void Move(SqBiTree q,int j,SqBiTree T,int i) /* InsertChild()用到。加 */
{ /* 把从q的j结点开始的子树移为从T的i结点开始的子树 */
    if(q[2*j+1]!=Nil) /* q的左子树不空 */
        Move(q,(2*j+1),T,(2*i+1)); /* 把q的j结点的左子树移为T的i结点的左子树 */
    if(q[2*j+2]!=Nil) /* q的右子树不空 */
        Move(q,(2*j+2),T,(2*i+2)); /* 把q的j结点的右子树移为T的i结点的右子树 */
    T[i]=q[j]; /* 把q的j结点移为T的i结点 */
    q[j]=Nil; /* 把q的j结点置空 */
}
Status InsertChild(SqBiTree T,TElemType p,Status LR,SqBiTree c)
{ /* 初始条件: 二叉树T存在,p是T中某个结点的值,LR为0或1,非空二叉树c与T */
    /*           不相交且右子树为空 */
    /* 操作结果: 根据LR为0或1,插入c为T中p结点的左或右子树。p结点的原有左或 */
    /*           右子树则成为c的右子树 */
    int j,k,i=0;
    for(j=0;j<(int)pow(2,BiTreeDepth(T))-1;j++) /* 查找p的序号 */
        if(T[j]==p) /* j为p的序号 */
            break;
    k=2*j+1+LR; /* k为p的左或右孩子的序号 */
    if(T[k]!=Nil) /* p原来的左或右孩子不空 */
        Move(T,k,T,2*k+2); /* 把从T的k结点开始的子树移为从k结点的右子树开始的子树 */
    Move(c,i,T,k); /* 把从c的i结点开始的子树移为从T的k结点开始的子树 */
    return OK;
}
void Print(SqBiTree T)
{ /* 逐层、按本层序号输出二叉树 */
    int j,k;
    position p;
    TElemType e;
    for(j=1;j<=BiTreeDepth(T);j++)
    {
        printf("第%d层: ",j);
        for(k=1;k<=pow(2,j-1);k++)
        {
            p.level=j;
            p.order=k;
            e=Value(T,p);
            if(e!=Nil)
                printf("%d:%d ",k,e);
        }
        printf("\n");
    }
}
int main()
{
    int j;
    TElemType e;
    SqBiTree T,s;
    InitBiTree(T);
    CreateBiTree(T);
    printf("建立右子树为空的树s:\n");
    CreateBiTree(s);
    printf("树s插到树T中,请输入树T中树s的双亲结点 s为左(0)或右(1)子树: ");
    scanf("%d%d",&e,&j);
    InsertChild(T,e,j,s);
    Print(T);
    return 0;
}

运行结果

1.4.4 节点的修改(顺序结构)

#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<math.h> /* floor(),ceil(),abs() */

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
#if CHAR
typedef char TElemType;
  TElemType Nil=' '; /* 设字符型以空格符为空 */
#else
typedef int TElemType;
TElemType Nil = 0; /* 设整型以0为空 */
#endif
#define MAX_TREE_SIZE 100 /* 二叉树的最大结点数 */
typedef TElemType SqBiTree[MAX_TREE_SIZE]; /* 0号单元存储根结点 */
typedef struct {
    int level, order; /* 结点的层,本层序号(按满二叉树计算) */
} position;

/* bo6-1.c 二叉树的顺序存储(存储结构由c6-1.h定义)的基本操作(23个) */
Status InitBiTree(SqBiTree T) { /* 构造空二叉树T。因为T是固定数组,不会改变,故不需要& */
    int i;
    for (i = 0; i < MAX_TREE_SIZE; i++)
        T[i] = Nil; /* 初值为空 */
    return OK;
}

Status CreateBiTree(SqBiTree T) { /* 按层序次序输入二叉树中结点的值(字符型或整型), 构造顺序存储的二叉树T */
    int i = 0;
#if CHAR
    int l;
  char s[MAX_TREE_SIZE];
  printf("请按层序输入结点的值(字符),空格表示空结点,结点数≤%d:\n",MAX_TREE_SIZE);
  gets(s); /* 输入字符串 */
  l=strlen(s); /* 求字符串的长度 */
  for(;i<l;i++) /* 将字符串赋值给T */
  {
    T[i]=s[i];
    if(i!=0&&T[(i+1)/2-1]==Nil&&T[i]!=Nil) /* 此结点(不空)无双亲且不是根 */
    {
      printf("出现无双亲的非根结点%c\n",T[i]);
      exit(ERROR);
    }
  }
  for(i=l;i<MAX_TREE_SIZE;i++) /* 将空赋值给T的后面的结点 */
    T[i]=Nil;
#else
    printf("请按层序输入结点的值(整型),0表示空结点,输999结束。结点数≤%d:\n", MAX_TREE_SIZE);
    while (1) {
        scanf("%d", &T[i]);
        if (T[i] == 999)
            break;
        if (i != 0 && T[(i + 1) / 2 - 1] == Nil && T[i] != Nil) /* 此结点(不空)无双亲且不是根 */
        {
            printf("出现无双亲的非根结点%d\n", T[i]);
            exit(ERROR);
        }
        i++;
    }
    while (i < MAX_TREE_SIZE) {
        T[i] = Nil; /* 将空赋值给T的后面的结点 */
        i++;
    }
#endif
    return OK;
}

Status BiTreeEmpty(SqBiTree T) { /* 初始条件: 二叉树T存在 */
    /* 操作结果: 若T为空二叉树,则返回TRUE,否则FALSE */
    if (T[0] == Nil) /* 根结点为空,则树空 */
        return TRUE;
    else
        return FALSE;
}

TElemType Value(SqBiTree T, position e) { /* 初始条件: 二叉树T存在,e是T中某个结点(的位置) */
    /* 操作结果: 返回处于位置e(层,本层序号)的结点的值 */
    return T[(int) pow(2, e.level - 1) + e.order - 2];
}

Status Assign(SqBiTree T, position e, TElemType value) { /* 初始条件: 二叉树T存在,e是T中某个结点(的位置) */
    /* 操作结果: 给处于位置e(层,本层序号)的结点赋新值value */
    int i = (int) pow(2, e.level - 1) + e.order - 2; /* 将层、本层序号转为矩阵的序号 */
    if (value != Nil && T[(i + 1) / 2 - 1] == Nil) /* 给叶子赋非空值但双亲为空 */
        return ERROR;
    else if (value == Nil && (T[i * 2 + 1] != Nil || T[i * 2 + 2] != Nil)) /*  给双亲赋空值但有叶子(不空) */
        return ERROR;
    T[i] = value;
    return OK;
}

Status (*VisitFunc)(TElemType); /* 函数变量 */
void PreTraverse(SqBiTree T, int e) { /* PreOrderTraverse()调用 */
    VisitFunc(T[e]);
    if (T[2 * e + 1] != Nil) /* 左子树不空 */
        PreTraverse(T, 2 * e + 1);
    if (T[2 * e + 2] != Nil) /* 右子树不空 */
        PreTraverse(T, 2 * e + 2);
}

Status PreOrderTraverse(SqBiTree T, Status(*Visit)(TElemType)) { /* 初始条件: 二叉树存在,Visit是对结点操作的应用函数 */
    /* 操作结果: 先序遍历T,对每个结点调用函数Visit一次且仅一次。 */
    /*           一旦Visit()失败,则操作失败 */
    VisitFunc = Visit;
    if (!BiTreeEmpty(T)) /* 树不空 */
        PreTraverse(T, 0);
    printf("\n");
    return OK;
}

Status visit(TElemType e) {
    printf("%d ", e);
    return OK;
}

int main() {
    Status i;
    position p;
    TElemType e;
    SqBiTree T;
    InitBiTree(T);
    CreateBiTree(T);
    printf("请输入待修改结点的层号 本层序号: ");
    scanf("%d%d", &p.level, &p.order);
    e = Value(T, p);
    printf("待修改结点的原值为%d请输入新值: ", e);
    scanf("%d", &e);
    Assign(T, p, e);
    printf("先序遍历二叉树:\n");
    PreOrderTraverse(T, visit);
    return 0;
}

运行结果

1.4.5 节点的修改(链式结构)

#define CHAR /* 字符型 */

#include <stdio.h> /* EOF(=^Z或F6),NULL */
#include <math.h> /* floor(),ceil(),abs() */
#include <stdlib.h>

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW 3
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
#ifdef CHAR
typedef char TElemType;
TElemType Nil = ' '; /* 字符型以空格符为空 */
#endif
#ifdef INT
typedef int TElemType;
  TElemType Nil=0; /* 整型以0为空 */
#endif
typedef struct BiTNode {
    TElemType data;
    struct BiTNode *lchild, *rchild; /* 左右孩子指针 */
} BiTNode, *BiTree;
typedef BiTree QElemType; /* 设队列元素为二叉树的指针类型 */
typedef struct QNode {
    QElemType data;
    struct QNode *next;
} QNode, *QueuePtr;

typedef struct {
    QueuePtr front, rear; /* 队头、队尾指针 */
} LinkQueue;

Status InitQueue(LinkQueue *Q) { /* 构造一个空队列Q */
    (*Q).front = (*Q).rear = (QueuePtr) malloc(sizeof(QNode));
    if (!(*Q).front)
        exit(OVERFLOW);
    (*Q).front->next = NULL;
    return OK;
}

Status QueueEmpty(LinkQueue Q) { /* 若Q为空队列,则返回TRUE,否则返回FALSE */
    if (Q.front == Q.rear)
        return TRUE;
    else
        return FALSE;
}

Status EnQueue(LinkQueue *Q, QElemType e) { /* 插入元素e为Q的新的队尾元素 */
    QueuePtr p = (QueuePtr) malloc(sizeof(QNode));
    if (!p) /* 存储分配失败 */
        exit(OVERFLOW);
    p->data = e;
    p->next = NULL;
    (*Q).rear->next = p;
    (*Q).rear = p;
    return OK;
}

Status DeQueue(LinkQueue *Q, QElemType *e) { /* 若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR */
    QueuePtr p;
    if ((*Q).front == (*Q).rear)
        return ERROR;
    p = (*Q).front->next;
    *e = p->data;
    (*Q).front->next = p->next;
    if ((*Q).rear == p)
        (*Q).rear = (*Q).front;
    free(p);
    return OK;
}

void LevelOrderTraverse(BiTree T, Status(*Visit)(TElemType)) { /* 初始条件:二叉树T存在,Visit是对结点操作的应用函数 */
    /* 操作结果:层序递归遍历T(利用队列),对每个结点调用函数Visit一次且仅一次 */
    LinkQueue q;
    QElemType a;
    if (T) {
        InitQueue(&q);
        EnQueue(&q, T);
        while (!QueueEmpty(q)) {
            DeQueue(&q, &a);
            Visit(a->data);
            if (a->lchild != NULL)
                EnQueue(&q, a->lchild);
            if (a->rchild != NULL)
                EnQueue(&q, a->rchild);
        }
        printf("\n");
    }
}

Status visitT(TElemType e) {
#ifdef CHAR
    printf("%c ", e);
#endif
#ifdef INT
    printf("%d ",e);
#endif
    return OK;
}

Status InitBiTree(BiTree *T) { /* 操作结果: 构造空二叉树T */
    *T = NULL;
    return OK;
}

void CreateBiTree(BiTree *T) {
    TElemType ch;
#ifdef CHAR
    scanf("%c", &ch);
#endif
#ifdef INT
    scanf("%d",&ch);
#endif
    if (ch == Nil) /* 空 */
        *T = NULL;
    else {
        *T = (BiTree) malloc(sizeof(BiTNode));
        if (!*T)
            exit(OVERFLOW);
        (*T)->data = ch; /* 生成根结点 */
        CreateBiTree(&(*T)->lchild); /* 构造左子树 */
        CreateBiTree(&(*T)->rchild); /* 构造右子树 */
    }
}

TElemType Value(BiTree p) { /* 初始条件: 二叉树T存在,p指向T中某个结点 */
    /* 操作结果: 返回p所指结点的值 */
    return p->data;
}

void Assign(BiTree p, TElemType value) { /* 给p所指结点赋值为value */
    p->data = value;
}

BiTree Point(BiTree T, TElemType s) { /* 返回二叉树T中指向元素值为s的结点的指针。另加 */
    LinkQueue q;
    QElemType a;
    if (T) /* 非空树 */
    {
        InitQueue(&q); /* 初始化队列 */
        EnQueue(&q, T); /* 根结点入队 */
        while (!QueueEmpty(q)) /* 队不空 */
        {
            DeQueue(&q, &a); /* 出队,队列元素赋给a */
            if (a->data == s)
                return a;
            if (a->lchild) /* 有左孩子 */
                EnQueue(&q, a->lchild); /* 入队左孩子 */
            if (a->rchild) /* 有右孩子 */
                EnQueue(&q, a->rchild); /* 入队右孩子 */
        }
    }
    return NULL;
}

int main() {
    BiTree T, p;
    TElemType e1, e2;
    InitBiTree(&T);
#ifdef CHAR
    printf("请先序输入二叉树(如:ab三个空格表示a为根结点,b为左子树的二叉树)\n");
#endif
#ifdef INT
    printf("请先序输入二叉树(如:1 2 0 0 0表示1为根结点,2为左子树的二叉树)\n");
#endif
    CreateBiTree(&T);
    printf("请输入一个结点的值: ");
#ifdef CHAR
    scanf("%*c%c", &e1);
#endif
#ifdef INT
    scanf("%d",&e1);
#endif
    p = Point(T, e1); /* p为e1的指针 */
#ifdef CHAR
    printf("结点的值为%c\n", Value(p));
#endif
#ifdef INT
    printf("结点的值为%d\n",Value(p));
#endif
    printf("欲改变此结点的值,请输入新值: ");
#ifdef CHAR
    scanf("%*c%c%*c", &e2);
#endif
#ifdef INT
    scanf("%d",&e2);
#endif
    Assign(p, e2);
    printf("层次遍历二叉树:\n");
    LevelOrderTraverse(T, visitT);
    return 0;
}

运行结果

1.4.6 双亲、孩子和兄弟节点的查询(顺序结构)

#include <stdio.h> /* EOF(=^Z或F6),NULL */
#include <stdlib.h>

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
#if CHAR
typedef char TElemType;
TElemType Nil=' '; /* 设字符型以空格符为空 */
#else
typedef int TElemType;
TElemType Nil = 0; /* 设整型以0为空 */
#endif
#define MAX_TREE_SIZE 100 /* 二叉树的最大结点数 */
typedef TElemType SqBiTree[MAX_TREE_SIZE]; /* 0号单元存储根结点 */
Status InitBiTree(SqBiTree T) { /* 构造空二叉树T。因为T是固定数组,不会改变,故不需要& */
    int i;
    for (i = 0; i < MAX_TREE_SIZE; i++)
        T[i] = Nil; /* 初值为空 */
    return OK;
}

Status CreateBiTree(SqBiTree T) { /* 按层序次序输入二叉树中结点的值(字符型或整型), 构造顺序存储的二叉树T */
    int i = 0;
#if CHAR
    int l;
  char s[MAX_TREE_SIZE];
  printf("请按层序输入结点的值(字符),空格表示空结点,结点数≤%d:\n",MAX_TREE_SIZE);
  gets(s); /* 输入字符串 */
  l=strlen(s); /* 求字符串的长度 */
  for(;i<l;i++) /* 将字符串赋值给T */
  {
    T[i]=s[i];
    if(i!=0&&T[(i+1)/2-1]==Nil&&T[i]!=Nil) /* 此结点(不空)无双亲且不是根 */
    {
      printf("出现无双亲的非根结点%c\n",T[i]);
      exit(ERROR);
    }
  }
  for(i=l;i<MAX_TREE_SIZE;i++) /* 将空赋值给T的后面的结点 */
    T[i]=Nil;
#else
    printf("请按层序输入结点的值(整型),0表示空结点,输999结束。结点数≤%d:\n", MAX_TREE_SIZE);
    while (1) {
        scanf("%d", &T[i]);
        if (T[i] == 999)
            break;
        if (i != 0 && T[(i + 1) / 2 - 1] == Nil && T[i] != Nil) /* 此结点(不空)无双亲且不是根 */
        {
            printf("出现无双亲的非根结点%d\n", T[i]);
            exit(ERROR);
        }
        i++;
    }
    while (i < MAX_TREE_SIZE) {
        T[i] = Nil; /* 将空赋值给T的后面的结点 */
        i++;
    }
#endif
    return OK;
}

TElemType Parent(SqBiTree T, TElemType e) { /* 初始条件: 二叉树T存在,e是T中某个结点 */
    /* 操作结果: 若e是T的非根结点,则返回它的双亲,否则返回"空" */
    int i;
    if (T[0] == Nil) /* 空树 */
        return Nil;
    for (i = 1; i <= MAX_TREE_SIZE - 1; i++)
        if (T[i] == e) /* 找到e */
            return T[(i + 1) / 2 - 1];
    return Nil; /* 没找到e */
}

TElemType LeftChild(SqBiTree T, TElemType e) { /* 初始条件: 二叉树T存在,e是T中某个结点 */
    /* 操作结果: 返回e的左孩子。若e无左孩子,则返回"空" */
    int i;
    if (T[0] == Nil) /* 空树 */
        return Nil;
    for (i = 0; i <= MAX_TREE_SIZE - 1; i++)
        if (T[i] == e) /* 找到e */
            return T[i * 2 + 1];
    return Nil; /* 没找到e */
}

TElemType RightChild(SqBiTree T, TElemType e) { /* 初始条件: 二叉树T存在,e是T中某个结点 */
    /* 操作结果: 返回e的右孩子。若e无右孩子,则返回"空" */
    int i;
    if (T[0] == Nil) /* 空树 */
        return Nil;
    for (i = 0; i <= MAX_TREE_SIZE - 1; i++)
        if (T[i] == e) /* 找到e */
            return T[i * 2 + 2];
    return Nil; /* 没找到e */
}

TElemType LeftSibling(SqBiTree T, TElemType e) { /* 初始条件: 二叉树T存在,e是T中某个结点 */
    /* 操作结果: 返回e的左兄弟。若e是T的左孩子或无左兄弟,则返回"空" */
    int i;
    if (T[0] == Nil) /* 空树 */
        return Nil;
    for (i = 1; i <= MAX_TREE_SIZE - 1; i++)
        if (T[i] == e && i % 2 == 0) /* 找到e且其序号为偶数(是右孩子) */
            return T[i - 1];
    return Nil; /* 没找到e */
}

TElemType RightSibling(SqBiTree T, TElemType e) { /* 初始条件: 二叉树T存在,e是T中某个结点 */
    /* 操作结果: 返回e的右兄弟。若e是T的右孩子或无右兄弟,则返回"空" */
    int i;
    if (T[0] == Nil) /* 空树 */
        return Nil;
    for (i = 1; i <= MAX_TREE_SIZE - 1; i++)
        if (T[i] == e && i % 2) /* 找到e且其序号为奇数(是左孩子) */
            return T[i + 1];
    return Nil; /* 没找到e */
}

int main() {
    TElemType e;
    SqBiTree T;
    InitBiTree(T);
    CreateBiTree(T);
    printf("请输入待查询结点的值:");
    scanf("%d", &e);
    printf("结点%d的双亲为%d,左右孩子分别为", e, Parent(T, e));
    printf("%d,%d,左右兄弟分别为", LeftChild(T, e), RightChild(T, e));
    printf("%d,%d\n", LeftSibling(T, e), RightSibling(T, e));
    return 0;
}

运行结果

1.4.7 双亲、孩子和兄弟节点的查询(链式结构)

#define CHAR /* 字符型 */

#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<math.h> /* floor(),ceil(),abs() */
#include <stdlib.h>

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW 3
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */

#ifdef CHAR
typedef char TElemType;
TElemType Nil = ' '; /* 字符型以空格符为空 */
#endif
#ifdef INT
typedef int TElemType;
TElemType Nil=0; /* 整型以0为空 */
#endif

typedef struct BiTNode {
    TElemType data;
    struct BiTNode *lchild, *rchild; /* 左右孩子指针 */
} BiTNode, *BiTree;

typedef BiTree QElemType; /* 设队列元素为二叉树的指针类型 */

typedef struct QNode//队列节点,包括一个数据域和一个指针域,数据域为二叉树的指针类型
{
    QElemType data;
    struct QNode *next;
} QNode, *QueuePtr;

typedef struct {
    QueuePtr front, rear; /* 队头、队尾指针 */
} LinkQueue;

Status InitBiTree(BiTree *T) { /* 操作结果: 构造空二叉树T */
    *T = NULL;
    return OK;
}

void CreateBiTree(BiTree *T) {
    TElemType ch;
#ifdef CHAR
    scanf("%c", &ch);
#endif
#ifdef INT
    scanf("%d",&ch);
#endif
    if (ch == Nil) /* 空 */
        *T = NULL;
    else {
        *T = (BiTree) malloc(sizeof(BiTNode));
        if (!*T)
            exit(OVERFLOW);
        (*T)->data = ch; /* 生成根结点 */
        CreateBiTree(&(*T)->lchild); /* 构造左子树 */
        CreateBiTree(&(*T)->rchild); /* 构造右子树 */
    }
}

Status InitQueue(LinkQueue *Q) { /* 构造一个空队列Q */
    (*Q).front = (*Q).rear = (QueuePtr) malloc(sizeof(QNode));
    if (!(*Q).front)
        exit(OVERFLOW);
    (*Q).front->next = NULL;
    return OK;
}

Status EnQueue(LinkQueue *Q, QElemType e) { /* 插入元素e为Q的新的队尾元素 */
    QueuePtr p = (QueuePtr) malloc(sizeof(QNode));
    if (!p) /* 存储分配失败 */
        exit(OVERFLOW);
    p->data = e;
    p->next = NULL;
    (*Q).rear->next = p;
    (*Q).rear = p;
    return OK;
}

Status QueueEmpty(LinkQueue Q) { /* 若Q为空队列,则返回TRUE,否则返回FALSE */
    if (Q.front == Q.rear)
        return TRUE;
    else
        return FALSE;
}

Status DeQueue(LinkQueue *Q, QElemType *e) { /* 若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR */
    QueuePtr p;
    if ((*Q).front == (*Q).rear)
        return ERROR;
    p = (*Q).front->next;
    *e = p->data;
    (*Q).front->next = p->next;
    if ((*Q).rear == p)
        (*Q).rear = (*Q).front;
    free(p);
    return OK;
}

TElemType Parent(BiTree T, TElemType e) { /* 初始条件: 二叉树T存在,e是T中某个结点 */
    /* 操作结果: 若e是T的非根结点,则返回它的双亲,否则返回"空" */
    LinkQueue q;
    QElemType a;
    if (T) /* 非空树 */
    {
        InitQueue(&q); /* 初始化队列 */
        EnQueue(&q, T); /* 树根入队 */
        while (!QueueEmpty(q)) /* 队不空 */
        {
            DeQueue(&q, &a); /* 出队,队列元素赋给a */
            if (a->lchild && a->lchild->data == e || a->rchild && a->rchild->data == e)
                /* 找到e(是其左或右孩子) */
                return a->data; /* 返回e的双亲的值 */
            else /* 没找到e,则入队其左右孩子指针(如果非空) */
            {
                if (a->lchild)
                    EnQueue(&q, a->lchild);
                if (a->rchild)
                    EnQueue(&q, a->rchild);
            }
        }
    }
    return Nil; /* 树空或没找到e */
}

BiTree Point(BiTree T, TElemType s) { /* 返回二叉树T中指向元素值为s的结点的指针。另加 */
    LinkQueue q;
    QElemType a;
    if (T) /* 非空树 */
    {
        InitQueue(&q); /* 初始化队列 */
        EnQueue(&q, T); /* 根结点入队 */
        while (!QueueEmpty(q)) /* 队不空 */
        {
            DeQueue(&q, &a); /* 出队,队列元素赋给a */
            if (a->data == s)
                return a;
            if (a->lchild) /* 有左孩子 */
                EnQueue(&q, a->lchild); /* 入队左孩子 */
            if (a->rchild) /* 有右孩子 */
                EnQueue(&q, a->rchild); /* 入队右孩子 */
        }
    }
    return NULL;
}

TElemType LeftChild(BiTree T, TElemType e) { /* 初始条件: 二叉树T存在,e是T中某个结点 */
    /* 操作结果: 返回e的左孩子。若e无左孩子,则返回"空" */
    BiTree a;
    if (T) /* 非空树 */
    {
        a = Point(T, e); /* a是结点e的指针 */
        if (a && a->lchild) /* T中存在结点e且e存在左孩子 */
            return a->lchild->data; /* 返回e的左孩子的值 */
    }
    return Nil; /* 其余情况返回空 */
}

TElemType RightChild(BiTree T, TElemType e) { /* 初始条件: 二叉树T存在,e是T中某个结点 */
    /* 操作结果: 返回e的右孩子。若e无右孩子,则返回"空" */
    BiTree a;
    if (T) /* 非空树 */
    {
        a = Point(T, e); /* a是结点e的指针 */
        if (a && a->rchild) /* T中存在结点e且e存在右孩子 */
            return a->rchild->data; /* 返回e的右孩子的值 */
    }
    return Nil; /* 其余情况返回空 */
}

TElemType LeftSibling(BiTree T, TElemType e) { /* 初始条件: 二叉树T存在,e是T中某个结点 */
    /* 操作结果: 返回e的左兄弟。若e是T的左孩子或无左兄弟,则返回"空" */
    TElemType a;
    BiTree p;
    if (T) /* 非空树 */
    {
        a = Parent(T, e); /* a为e的双亲 */
        p = Point(T, a); /* p为指向结点a的指针 */
        if (p->lchild && p->rchild && p->rchild->data == e) /* p存在左右孩子且右孩子是e */
            return p->lchild->data; /* 返回p的左孩子(e的左兄弟) */
    }
    return Nil; /* 树空或没找到e的左兄弟 */
}

TElemType RightSibling(BiTree T, TElemType e) { /* 初始条件: 二叉树T存在,e是T中某个结点 */
    /* 操作结果: 返回e的右兄弟。若e是T的右孩子或无右兄弟,则返回"空" */
    TElemType a;
    BiTree p;
    if (T) /* 非空树 */
    {
        a = Parent(T, e); /* a为e的双亲 */
        p = Point(T, a); /* p为指向结点a的指针 */
        if (p->lchild && p->rchild && p->lchild->data == e) /* p存在左右孩子且左孩子是e */
            return p->rchild->data; /* 返回p的右孩子(e的右兄弟) */
    }
    return Nil; /* 树空或没找到e的右兄弟 */
}

int main() {
    BiTree T;
    TElemType e1, e2;
    InitBiTree(&T);
#ifdef CHAR
    printf("请先序输入二叉树(如:ab三个空格表示a为根结点,b为左子树的二叉树)\n");
#endif
#ifdef INT
    printf("请先序输入二叉树(如:1 2 0 0 0表示1为根结点,2为左子树的二叉树)\n");
#endif
    CreateBiTree(&T);
    printf("请输入要查询结点的值:");
#ifdef CHAR
    scanf("%*c%c%*c", &e2);
#endif
#ifdef INT
    scanf("%d",&e2);
#endif
    e1 = Parent(T, e2);
    if (e1 != Nil)
#ifdef CHAR
        printf("%c的双亲是%c\n", e2, e1);
#endif
#ifdef INT
        printf("%d的双亲是%d\n",e2,e1);
#endif
    else
#ifdef CHAR
        printf("%c没有双亲\n", e2);
#endif
#ifdef INT
    printf("%d没有双亲\n",e2);
#endif
    e1 = LeftChild(T, e2);
    if (e1 != Nil)
#ifdef CHAR
        printf("%c的左孩子是%c\n", e2, e1);
#endif
#ifdef INT
        printf("%d的左孩子是%d\n",e2,e1);
#endif
    else
#ifdef CHAR
        printf("%c没有左孩子\n", e2);
#endif
#ifdef INT
    printf("%d没有左孩子\n",e2);
#endif
    e1 = RightChild(T, e2);
    if (e1 != Nil)
#ifdef CHAR
        printf("%c的右孩子是%c\n", e2, e1);
#endif
#ifdef INT
        printf("%d的右孩子是%d\n",e2,e1);
#endif
    else
#ifdef CHAR
        printf("%c没有右孩子\n", e2);
#endif
#ifdef INT
    printf("%d没有右孩子\n",e2);
#endif
    e1 = LeftSibling(T, e2);
    if (e1 != Nil)
#ifdef CHAR
        printf("%c的左兄弟是%c\n", e2, e1);
#endif
#ifdef INT
        printf("%d的左兄弟是%d\n",e2,e1);
#endif
    else
#ifdef CHAR
        printf("%c没有左兄弟\n", e2);
#endif
#ifdef INT
    printf("%d没有左兄弟\n",e2);
#endif
    e1 = RightSibling(T, e2);
    if (e1 != Nil)
#ifdef CHAR
        printf("%c的右兄弟是%c\n", e2, e1);
#endif
#ifdef INT
        printf("%d的右兄弟是%d\n",e2,e1);
#endif
    else
#ifdef CHAR
        printf("%c没有右兄弟\n", e2);
#endif
#ifdef INT
    printf("%d没有右兄弟\n",e2);
#endif
    return 0;
}

运行结果

1.4.8 中序遍历二叉树(顺序结构)

#define CHAR /* 字符型 */

#include <stdio.h> /* EOF(=^Z或F6),NULL */
#include <stdlib.h>
#include <math.h> /* floor(),ceil(),abs() */

#define TRUE 1
#define FALSE 0
#define OK 1
#define OVERFLOW 3
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
#ifdef CHAR
typedef char TElemType;
TElemType Nil = ' '; /* 字符型以空格符为空 */
#endif
#ifdef INT
typedef int TElemType;
  TElemType Nil=0; /* 整型以0为空 */
#endif
typedef struct BiTNode {
    TElemType data;
    struct BiTNode *lchild, *rchild; /* 左右孩子指针 */
} BiTNode, *BiTree;

Status InitBiTree(BiTree *T) { /* 操作结果: 构造空二叉树T */
    *T = NULL;
    return OK;
}

void CreateBiTree(BiTree *T) {
    TElemType ch;
#ifdef CHAR
    scanf("%c", &ch);
#endif
#ifdef INT
    scanf("%d",&ch);
#endif
    if (ch == Nil) /* 空 */
        *T = NULL;
    else {
        *T = (BiTree) malloc(sizeof(BiTNode));
        if (!*T)
            exit(OVERFLOW);
        (*T)->data = ch; /* 生成根结点 */
        CreateBiTree(&(*T)->lchild); /* 构造左子树 */
        CreateBiTree(&(*T)->rchild); /* 构造右子树 */
    }
}

void InOrderTraverse(BiTree T, Status(*Visit)(TElemType)) { /* 初始条件: 二叉树T存在,Visit是对结点操作的应用函数 */
    /* 操作结果: 中序递归遍历T,对每个结点调用函数Visit一次且仅一次 */
    if (T) {
        InOrderTraverse(T->lchild, Visit); /* 先中序遍历左子树 */
        Visit(T->data); /* 再访问根结点 */
        InOrderTraverse(T->rchild, Visit); /* 最后中序遍历右子树 */
    }
}

Status visitT(TElemType e) {
#ifdef CHAR
    printf("%c ", e);
#endif
#ifdef INT
    printf("%d ",e);
#endif
    return OK;
}

int main() {
    BiTree T;
    InitBiTree(&T);
#ifdef CHAR
    printf("请先序输入二叉树(如:ab三个空格表示a为根结点,b为左子树的二叉树)\n");
#endif
#ifdef INT
    printf("请先序输入二叉树(如:1 2 0 0 0表示1为根结点,2为左子树的二叉树)\n");
#endif
    CreateBiTree(&T);
    printf("中序递归遍历二叉树:\n");
    InOrderTraverse(T, visitT);
    return 0;
}

运行结果

1.4.9 中序遍历二叉树(链式结构)

#define CHAR /* 字符型 */

#include <stdio.h> /* EOF(=^Z或F6),NULL */
#include <math.h> /* floor(),ceil(),abs() */
#include <stdlib.h>

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define STACK_INIT_SIZE 10 /* 存储空间初始分配量 */
#define STACKINCREMENT 2 /* 存储空间分配增量 */
#define OVERFLOW 3
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
#ifdef CHAR
typedef char TElemType;
TElemType Nil = ' '; /* 字符型以空格符为空 */
#endif
#ifdef INT
typedef int TElemType;
  TElemType Nil=0; /* 整型以0为空 */
#endif
typedef struct BiTNode {
    TElemType data;
    struct BiTNode *lchild, *rchild; /* 左右孩子指针 */
} BiTNode, *BiTree;
typedef BiTree SElemType; /* 设栈元素为二叉树的指针类型 */
typedef struct SqStack {
    SElemType *base; /* 在栈构造之前和销毁之后,base的值为NULL */
    SElemType *top; /* 栈顶指针 */
    int stacksize; /* 当前已分配的存储空间,以元素为单位 */
} SqStack; /* 顺序栈 */
Status InitBiTree(BiTree *T) { /* 操作结果: 构造空二叉树T */
    *T = NULL;
    return OK;
}

void CreateBiTree(BiTree *T) {
    TElemType ch;
#ifdef CHAR
    scanf("%c", &ch);
#endif
#ifdef INT
    scanf("%d",&ch);
#endif
    if (ch == Nil) /* 空 */
        *T = NULL;
    else {
        *T = (BiTree) malloc(sizeof(BiTNode));
        if (!*T)
            exit(OVERFLOW);
        (*T)->data = ch; /* 生成根结点 */
        CreateBiTree(&(*T)->lchild); /* 构造左子树 */
        CreateBiTree(&(*T)->rchild); /* 构造右子树 */
    }
}

Status InitStack(SqStack *S) { /* 构造一个空栈S */
    (*S).base = (SElemType *) malloc(STACK_INIT_SIZE * sizeof(SElemType));
    if (!(*S).base)
        exit(OVERFLOW); /* 存储分配失败 */
    (*S).top = (*S).base;
    (*S).stacksize = STACK_INIT_SIZE;
    return OK;
}

Status StackEmpty(SqStack S) { /* 若栈S为空栈,则返回TRUE,否则返回FALSE */
    if (S.top == S.base)
        return TRUE;
    else
        return FALSE;
}

Status Push(SqStack *S, SElemType e) { /* 插入元素e为新的栈顶元素 */
    if ((*S).top - (*S).base >= (*S).stacksize) /* 栈满,追加存储空间 */
    {
        (*S).base = (SElemType *) realloc((*S).base, ((*S).stacksize + STACKINCREMENT) * sizeof(SElemType));
        if (!(*S).base)
            exit(OVERFLOW); /* 存储分配失败 */
        (*S).top = (*S).base + (*S).stacksize;
        (*S).stacksize += STACKINCREMENT;
    }
    *((*S).top)++ = e;
    return OK;
}

Status Pop(SqStack *S, SElemType *e) { /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */
    if ((*S).top == (*S).base)
        return ERROR;
    *e = *--(*S).top;
    return OK;
}

Status GetTop(SqStack S, SElemType *e) { /* 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR */
    if (S.top > S.base) {
        *e = *(S.top - 1);
        return OK;
    } else
        return ERROR;
}

Status InOrderTraverse2(BiTree T, Status(*Visit)(TElemType)) { /* 采用二叉链表存储结构,Visit是对数据元素操作的应用函数。*/
    /* 中序遍历二叉树T的非递归算法(利用栈),对每个数据元素调用函数Visit */
    SqStack S;
    BiTree p;
    InitStack(&S);
    Push(&S, T); /* 根指针进栈 */
    while (!StackEmpty(S)) {
        while (GetTop(S, &p) && p)
            Push(&S, p->lchild); /* 向左走到尽头 */
        Pop(&S, &p); /* 空指针退栈 */
        if (!StackEmpty(S)) { /* 访问结点,向右一步 */
            Pop(&S, &p);
            if (!Visit(p->data))
                return ERROR;
            Push(&S, p->rchild);
        }
    }
    printf("\n");
    return OK;
}

Status visitT(TElemType e) {
#ifdef CHAR
    printf("%c ", e);
#endif
#ifdef INT
    printf("%d ",e);
#endif
    return OK;
}

int main() {
    BiTree T;
    InitBiTree(&T);
#ifdef CHAR
    printf("请先序输入二叉树(如:ab三个空格表示a为根结点,b为左子树的二叉树)\n");
#endif
#ifdef INT
    printf("请先序输入二叉树(如:1 2 0 0 0表示1为根结点,2为左子树的二叉树)\n");
#endif
    CreateBiTree(&T);
    printf("中序非递归遍历二叉树(另一种方法):\n");
    InOrderTraverse2(T, visitT);
    return 0;
}

运行结果

1.4.10 中序非递归遍历二叉树(链式结构)

#define CHAR /* 字符型 */

#include <stdio.h> /* EOF(=^Z或F6),NULL */
#include <math.h> /* floor(),ceil(),abs() */
#include <stdlib.h>

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW 3
#define STACK_INIT_SIZE 10 /* 存储空间初始分配量 */
#define STACKINCREMENT 2 /* 存储空间分配增量 */
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
#ifdef CHAR
typedef char TElemType;
TElemType Nil = ' '; /* 字符型以空格符为空 */
#endif
#ifdef INT
typedef int TElemType;
TElemType Nil=0; /* 整型以0为空 */
#endif
typedef struct BiTNode {
    TElemType data;
    struct BiTNode *lchild, *rchild; /* 左右孩子指针 */
} BiTNode, *BiTree;
typedef BiTree SElemType; /* 设栈元素为二叉树的指针类型 */
typedef struct SqStack {
    SElemType *base; /* 在栈构造之前和销毁之后,base的值为NULL */
    SElemType *top; /* 栈顶指针 */
    int stacksize; /* 当前已分配的存储空间,以元素为单位 */
} SqStack; /* 顺序栈 */
Status InitBiTree(BiTree *T) { /* 操作结果: 构造空二叉树T */
    *T = NULL;
    return OK;
}

void CreateBiTree(BiTree *T) {
    TElemType ch;
#ifdef CHAR
    scanf("%c", &ch);
#endif
#ifdef INT
    scanf("%d",&ch);
#endif
    if (ch == Nil) /* 空 */
        *T = NULL;
    else {
        *T = (BiTree) malloc(sizeof(BiTNode));
        if (!*T)
            exit(OVERFLOW);
        (*T)->data = ch; /* 生成根结点 */
        CreateBiTree(&(*T)->lchild); /* 构造左子树 */
        CreateBiTree(&(*T)->rchild); /* 构造右子树 */
    }
}

Status InitStack(SqStack *S) { /* 构造一个空栈S */
    (*S).base = (SElemType *) malloc(STACK_INIT_SIZE * sizeof(SElemType));
    if (!(*S).base)
        exit(OVERFLOW); /* 存储分配失败 */
    (*S).top = (*S).base;
    (*S).stacksize = STACK_INIT_SIZE;
    return OK;
}

Status StackEmpty(SqStack S) { /* 若栈S为空栈,则返回TRUE,否则返回FALSE */
    if (S.top == S.base)
        return TRUE;
    else
        return FALSE;
}

Status Push(SqStack *S, SElemType e) { /* 插入元素e为新的栈顶元素 */
    if ((*S).top - (*S).base >= (*S).stacksize) /* 栈满,追加存储空间 */
    {
        (*S).base = (SElemType *) realloc((*S).base, ((*S).stacksize + STACKINCREMENT) * sizeof(SElemType));
        if (!(*S).base)
            exit(OVERFLOW); /* 存储分配失败 */
        (*S).top = (*S).base + (*S).stacksize;
        (*S).stacksize += STACKINCREMENT;
    }
    *((*S).top)++ = e;
    return OK;
}

Status Pop(SqStack *S, SElemType *e) { /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */
    if ((*S).top == (*S).base)
        return ERROR;
    *e = *--(*S).top;
    return OK;
}

Status GetTop(SqStack S, SElemType *e) { /* 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR */
    if (S.top > S.base) {
        *e = *(S.top - 1);
        return OK;
    } else
        return ERROR;
}

Status InOrderTraverse2(BiTree T, Status(*Visit)(TElemType))//先压入,后判断
{ /* 采用二叉链表存储结构,Visit是对数据元素操作的应用函数。*/
    /* 中序遍历二叉树T的非递归算法(利用栈),对每个数据元素调用函数Visit */
    SqStack S;
    BiTree p;
    InitStack(&S);
    Push(&S, T); /* 根指针进栈 */
    while (!StackEmpty(S)) {
        while (GetTop(S, &p) && p)
            Push(&S, p->lchild); /* 向左走到尽头 */
        Pop(&S, &p); /* 空指针退栈 */

        if (!StackEmpty(S)) { /* 访问结点,向右一步 */
            Pop(&S, &p);
            if (!Visit(p->data))
                return ERROR;
            Push(&S, p->rchild);
        }
    }
    printf("\n");
    return OK;
}

Status visitT(TElemType e) {
#ifdef CHAR
    printf("%c ", e);
#endif
#ifdef INT
    printf("%d ",e);
#endif
    return OK;
}

int main() {
    BiTree T;
    InitBiTree(&T);
#ifdef CHAR
    printf("请先序输入二叉树(如:ab三个空格表示a为根结点,b为左子树的二叉树)\n");
#endif
#ifdef INT
    printf("请先序输入二叉树(如:1 2 0 0 0表示1为根结点,2为左子树的二叉树)\n");
#endif
    CreateBiTree(&T);
    printf("中序非递归遍历二叉树(另一种方法):\n");
    InOrderTraverse2(T, visitT);
    return 0;
}

运行结果

1.4.11 中序非递归遍历二叉树(链式结构)(2)

#define CHAR /* 字符型 */

#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<math.h> /* floor(),ceil(),abs() */

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define STACK_INIT_SIZE 10 /* 存储空间初始分配量 */
#define STACKINCREMENT 2 /* 存储空间分配增量 */
#define OVERFLOW 3
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
#ifdef CHAR
typedef char TElemType;
TElemType Nil = ' '; /* 字符型以空格符为空 */
#endif
#ifdef INT
typedef int TElemType;
  TElemType Nil=0; /* 整型以0为空 */
#endif
typedef struct BiTNode {
    TElemType data;
    struct BiTNode *lchild, *rchild; /* 左右孩子指针 */
} BiTNode, *BiTree;
typedef BiTree SElemType; /* 设栈元素为二叉树的指针类型 */
typedef struct SqStack {
    SElemType *base; /* 在栈构造之前和销毁之后,base的值为NULL */
    SElemType *top; /* 栈顶指针 */
    int stacksize; /* 当前已分配的存储空间,以元素为单位 */
} SqStack; /* 顺序栈 */
Status InitBiTree(BiTree *T) { /* 操作结果: 构造空二叉树T */
    *T = NULL;
    return OK;
}

void CreateBiTree(BiTree *T) {
    TElemType ch;
#ifdef CHAR
    scanf("%c", &ch);
#endif
#ifdef INT
    scanf("%d",&ch);
#endif
    if (ch == Nil) /* 空 */
        *T = NULL;
    else {
        *T = (BiTree) malloc(sizeof(BiTNode));
        if (!*T)
            exit(OVERFLOW);
        (*T)->data = ch; /* 生成根结点 */
        CreateBiTree(&(*T)->lchild); /* 构造左子树 */
        CreateBiTree(&(*T)->rchild); /* 构造右子树 */
    }
}

Status InitStack(SqStack *S) { /* 构造一个空栈S */
    (*S).base = (SElemType *) malloc(STACK_INIT_SIZE * sizeof(SElemType));
    if (!(*S).base)
        exit(OVERFLOW); /* 存储分配失败 */
    (*S).top = (*S).base;
    (*S).stacksize = STACK_INIT_SIZE;
    return OK;
}

Status StackEmpty(SqStack S) { /* 若栈S为空栈,则返回TRUE,否则返回FALSE */
    if (S.top == S.base)
        return TRUE;
    else
        return FALSE;
}

Status Push(SqStack *S, SElemType e) { /* 插入元素e为新的栈顶元素 */
    if ((*S).top - (*S).base >= (*S).stacksize) /* 栈满,追加存储空间 */
    {
        (*S).base = (SElemType *) realloc((*S).base, ((*S).stacksize + STACKINCREMENT) * sizeof(SElemType));
        if (!(*S).base)
            exit(OVERFLOW); /* 存储分配失败 */
        (*S).top = (*S).base + (*S).stacksize;
        (*S).stacksize += STACKINCREMENT;
    }
    *((*S).top)++ = e;
    return OK;
}

Status Pop(SqStack *S, SElemType *e) { /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */
    if ((*S).top == (*S).base)
        return ERROR;
    *e = *--(*S).top;
    return OK;
}

Status GetTop(SqStack S, SElemType *e) { /* 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR */
    if (S.top > S.base) {
        *e = *(S.top - 1);
        return OK;
    } else
        return ERROR;
}

Status InOrderTraverse2(BiTree T, Status(*Visit)(TElemType)) { /* 采用二叉链表存储结构,Visit是对数据元素操作的应用函数。*/
    /* 中序遍历二叉树T的非递归算法(利用栈),对每个数据元素调用函数Visit */
    SqStack S;
    BiTree p;
    InitStack(&S);
    Push(&S, T); /* 根指针进栈 */
    while (!StackEmpty(S)) {
        while (GetTop(S, &p) && p)
            Push(&S, p->lchild); /* 向左走到尽头 */
        Pop(&S, &p); /* 空指针退栈 */
        if (!StackEmpty(S)) { /* 访问结点,向右一步 */
            Pop(&S, &p);
            if (!Visit(p->data))
                return ERROR;
            Push(&S, p->rchild);
        }
    }
    printf("\n");
    return OK;
}

Status visitT(TElemType e) {
#ifdef CHAR
    printf("%c ", e);
#endif
#ifdef INT
    printf("%d ",e);
#endif
    return OK;
}

int main() {
    BiTree T;
    InitBiTree(&T);
#ifdef CHAR
    printf("请先序输入二叉树(如:ab三个空格表示a为根结点,b为左子树的二叉树)\n");
#endif
#ifdef INT
    printf("请先序输入二叉树(如:1 2 0 0 0表示1为根结点,2为左子树的二叉树)\n");
#endif
    CreateBiTree(&T);
    printf("中序非递归遍历二叉树(另一种方法):\n");
    InOrderTraverse2(T, visitT);
    return 0;
}

运行结果

1.4.12 后序遍历二叉树(顺序结构)

#define CHAR /* 字符型 */

#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<math.h> /* floor(),ceil(),abs() */

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW 3
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
#ifdef CHAR
typedef char TElemType;
TElemType Nil = ' '; /* 字符型以空格符为空 */
#endif
#ifdef INT
typedef int TElemType;
  TElemType Nil=0; /* 整型以0为空 */
#endif
typedef struct BiTNode {
    TElemType data;
    struct BiTNode *lchild, *rchild; /* 左右孩子指针 */
} BiTNode, *BiTree;

Status InitBiTree(BiTree *T) { /* 操作结果: 构造空二叉树T */
    *T = NULL;
    return OK;
}

void CreateBiTree(BiTree *T) {
    TElemType ch;
#ifdef CHAR
    scanf("%c", &ch);
#endif
#ifdef INT
    scanf("%d",&ch);
#endif
    if (ch == Nil) /* 空 */
        *T = NULL;
    else {
        *T = (BiTree) malloc(sizeof(BiTNode));
        if (!*T)
            exit(OVERFLOW);
        (*T)->data = ch; /* 生成根结点 */
        CreateBiTree(&(*T)->lchild); /* 构造左子树 */
        CreateBiTree(&(*T)->rchild); /* 构造右子树 */
    }
}

void PostOrderTraverse(BiTree T, Status(*Visit)(TElemType)) { /* 初始条件: 二叉树T存在,Visit是对结点操作的应用函数 */
    /* 操作结果: 后序递归遍历T,对每个结点调用函数Visit一次且仅一次 */
    if (T) /* T不空 */
    {
        PostOrderTraverse(T->lchild, Visit); /* 先后序遍历左子树 */
        PostOrderTraverse(T->rchild, Visit); /* 再后序遍历右子树 */
        Visit(T->data); /* 最后访问根结点 */
    }
}

Status visitT(TElemType e) {
#ifdef CHAR
    printf("%c ", e);
#endif
#ifdef INT
    printf("%d ",e);
#endif
    return OK;
}

int main() {
    BiTree T;
    InitBiTree(&T);
#ifdef CHAR
    printf("请先序输入二叉树(如:ab三个空格表示a为根结点,b为左子树的二叉树)\n");
#endif
#ifdef INT
    printf("请先序输入二叉树(如:1 2 0 0 0表示1为根结点,2为左子树的二叉树)\n");
#endif
    CreateBiTree(&T);
    printf("后序递归遍历二叉树:\n");
    PostOrderTraverse(T, visitT);
    return 0;
}

运行结果

1.4.13 后序遍历二叉树(链式结构)

#define CHAR /* 字符型 */

#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<math.h> /* floor(),ceil(),abs() */

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW 3
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
#ifdef CHAR
typedef char TElemType;
TElemType Nil = ' '; /* 字符型以空格符为空 */
#endif
#ifdef INT
typedef int TElemType;
  TElemType Nil=0; /* 整型以0为空 */
#endif
typedef struct BiTNode {
    TElemType data;
    struct BiTNode *lchild, *rchild; /* 左右孩子指针 */
} BiTNode, *BiTree;

Status InitBiTree(BiTree *T) { /* 操作结果: 构造空二叉树T */
    *T = NULL;
    return OK;
}

void CreateBiTree(BiTree *T) {
    TElemType ch;
#ifdef CHAR
    scanf("%c", &ch);
#endif
#ifdef INT
    scanf("%d",&ch);
#endif
    if (ch == Nil) /* 空 */
        *T = NULL;
    else {
        *T = (BiTree) malloc(sizeof(BiTNode));
        if (!*T)
            exit(OVERFLOW);
        (*T)->data = ch; /* 生成根结点 */
        CreateBiTree(&(*T)->lchild); /* 构造左子树 */
        CreateBiTree(&(*T)->rchild); /* 构造右子树 */
    }
}

void PostOrderTraverse(BiTree T, Status(*Visit)(TElemType)) { /* 初始条件: 二叉树T存在,Visit是对结点操作的应用函数 */
    /* 操作结果: 后序递归遍历T,对每个结点调用函数Visit一次且仅一次 */
    if (T) /* T不空 */
    {
        PostOrderTraverse(T->lchild, Visit); /* 先后序遍历左子树 */
        PostOrderTraverse(T->rchild, Visit); /* 再后序遍历右子树 */
        Visit(T->data); /* 最后访问根结点 */
    }
}

Status visitT(TElemType e) {
#ifdef CHAR
    printf("%c ", e);
#endif
#ifdef INT
    printf("%d ",e);
#endif
    return OK;
}

int main() {
    BiTree T;
    InitBiTree(&T);
#ifdef CHAR
    printf("请先序输入二叉树(如:ab三个空格表示a为根结点,b为左子树的二叉树)\n");
#endif
#ifdef INT
    printf("请先序输入二叉树(如:1 2 0 0 0表示1为根结点,2为左子树的二叉树)\n");
#endif
    CreateBiTree(&T);
    printf("后序递归遍历二叉树:\n");
    PostOrderTraverse(T, visitT);
    return 0;
}

运行结果

1.4.14 层次遍历二叉树(顺序结构)

#include <stdio.h> /* EOF(=^Z或F6),NULL */
#include <stdlib.h>

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
#if CHAR
typedef char TElemType;
  TElemType Nil=' '; /* 设字符型以空格符为空 */
#else
typedef int TElemType;
TElemType Nil = 0; /* 设整型以0为空 */
#endif
#define MAX_TREE_SIZE 100 /* 二叉树的最大结点数 */
typedef TElemType SqBiTree[MAX_TREE_SIZE]; /* 0号单元存储根结点 */
Status InitBiTree(SqBiTree T) { /* 构造空二叉树T。因为T是固定数组,不会改变,故不需要& */
    int i;
    for (i = 0; i < MAX_TREE_SIZE; i++)
        T[i] = Nil; /* 初值为空 */
    return OK;
}

Status CreateBiTree(SqBiTree T) { /* 按层序次序输入二叉树中结点的值(字符型或整型), 构造顺序存储的二叉树T */
    int i = 0;
#if CHAR
    int l;
  char s[MAX_TREE_SIZE];
  printf("请按层序输入结点的值(字符),空格表示空结点,结点数≤%d:\n",MAX_TREE_SIZE);
  gets(s); /* 输入字符串 */
  l=strlen(s); /* 求字符串的长度 */
  for(;i<l;i++) /* 将字符串赋值给T */
  {
    T[i]=s[i];
    if(i!=0&&T[(i+1)/2-1]==Nil&&T[i]!=Nil) /* 此结点(不空)无双亲且不是根 */
    {
      printf("出现无双亲的非根结点%c\n",T[i]);
      exit(ERROR);
    }
  }
  for(i=l;i<MAX_TREE_SIZE;i++) /* 将空赋值给T的后面的结点 */
    T[i]=Nil;
#else
    printf("请按层序输入结点的值(整型),0表示空结点,输999结束。结点数≤%d:\n", MAX_TREE_SIZE);
    while (1) {
        scanf("%d", &T[i]);
        if (T[i] == 999)
            break;
        if (i != 0 && T[(i + 1) / 2 - 1] == Nil && T[i] != Nil) /* 此结点(不空)无双亲且不是根 */
        {
            printf("出现无双亲的非根结点%d\n", T[i]);
            exit(ERROR);
        }
        i++;
    }
    while (i < MAX_TREE_SIZE) {
        T[i] = Nil; /* 将空赋值给T的后面的结点 */
        i++;
    }
#endif
    return OK;
}

void LevelOrderTraverse(SqBiTree T, Status(*Visit)(TElemType)) { /* 层序遍历二叉树 */
    int i = MAX_TREE_SIZE - 1, j;
    while (T[i] == Nil)
        i--; /* 找到最后一个非空结点的序号 */
    for (j = 0; j <= i; j++)  /* 从根结点起,按层序遍历二叉树 */
        if (T[j] != Nil)
            Visit(T[j]); /* 只遍历非空的结点 */
    printf("\n");
}

Status visit(TElemType e) {
    printf("%d ", e);
    return OK;
}

int main() {
    SqBiTree T;
    InitBiTree(T);
    CreateBiTree(T);
    printf("层序遍历二叉树:\n");
    LevelOrderTraverse(T, visit);
    return 0;
}

运行结果

1.4.15 层次遍历二叉树(链式结构)

#define CHAR /* 字符型 */

#include <stdio.h> /* EOF(=^Z或F6),NULL */
#include <math.h> /* floor(),ceil(),abs() */
#include <stdlib.h>

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW 3
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
#ifdef CHAR
typedef char TElemType;
TElemType Nil = ' '; /* 字符型以空格符为空 */
#endif
#ifdef INT
typedef int TElemType;
  TElemType Nil=0; /* 整型以0为空 */
#endif
typedef struct BiTNode {
    TElemType data;
    struct BiTNode *lchild, *rchild; /* 左右孩子指针 */
} BiTNode, *BiTree;
typedef BiTree QElemType; /* 设队列元素为二叉树的指针类型 */
typedef struct QNode {
    QElemType data;
    struct QNode *next;
} QNode, *QueuePtr;

typedef struct {
    QueuePtr front, rear; /* 队头、队尾指针 */
} LinkQueue;

Status InitBiTree(BiTree *T) { /* 操作结果: 构造空二叉树T */
    *T = NULL;
    return OK;
}

void CreateBiTree(BiTree *T) {
    TElemType ch;
#ifdef CHAR
    scanf("%c", &ch);
#endif
#ifdef INT
    scanf("%d",&ch);
#endif
    if (ch == Nil) /* 空 */
        *T = NULL;
    else {
        *T = (BiTree) malloc(sizeof(BiTNode));
        if (!*T)
            exit(OVERFLOW);
        (*T)->data = ch; /* 生成根结点 */
        CreateBiTree(&(*T)->lchild); /* 构造左子树 */
        CreateBiTree(&(*T)->rchild); /* 构造右子树 */
    }
}

Status InitQueue(LinkQueue *Q) { /* 构造一个空队列Q */
    (*Q).front = (*Q).rear = (QueuePtr) malloc(sizeof(QNode));
    if (!(*Q).front)
        exit(OVERFLOW);
    (*Q).front->next = NULL;
    return OK;
}

Status QueueEmpty(LinkQueue Q) { /* 若Q为空队列,则返回TRUE,否则返回FALSE */
    if (Q.front == Q.rear)
        return TRUE;
    else
        return FALSE;
}

Status EnQueue(LinkQueue *Q, QElemType e) { /* 插入元素e为Q的新的队尾元素 */
    QueuePtr p = (QueuePtr) malloc(sizeof(QNode));
    if (!p) /* 存储分配失败 */
        exit(OVERFLOW);
    p->data = e;
    p->next = NULL;
    (*Q).rear->next = p;
    (*Q).rear = p;
    return OK;
}

Status DeQueue(LinkQueue *Q, QElemType *e) { /* 若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR */
    QueuePtr p;
    if ((*Q).front == (*Q).rear)
        return ERROR;
    p = (*Q).front->next;
    *e = p->data;
    (*Q).front->next = p->next;
    if ((*Q).rear == p)
        (*Q).rear = (*Q).front;
    free(p);
    return OK;
}

void LevelOrderTraverse(BiTree T, Status(*Visit)(TElemType)) { /* 初始条件:二叉树T存在,Visit是对结点操作的应用函数 */
    /* 操作结果:层序递归遍历T(利用队列),对每个结点调用函数Visit一次且仅一次 */
    LinkQueue q;
    QElemType a;
    if (T) {
        InitQueue(&q);
        EnQueue(&q, T);
        while (!QueueEmpty(q)) {
            DeQueue(&q, &a);
            Visit(a->data);
            if (a->lchild != NULL)
                EnQueue(&q, a->lchild);
            if (a->rchild != NULL)
                EnQueue(&q, a->rchild);
        }
        printf("\n");
    }
}

Status visitT(TElemType e) {
#ifdef CHAR
    printf("%c ", e);
#endif
#ifdef INT
    printf("%d ",e);
#endif
    return OK;
}

int main() {
    BiTree T;
    InitBiTree(&T);
#ifdef CHAR
    printf("请先序输入二叉树(如:ab三个空格表示a为根结点,b为左子树的二叉树)\n");
#endif
#ifdef INT
    printf("请先序输入二叉树(如:1 2 0 0 0表示1为根结点,2为左子树的二叉树)\n");
#endif
    CreateBiTree(&T);
    printf("层次遍历二叉树:\n");
    LevelOrderTraverse(T, visitT);
    return 0;
}

运行结果

1.4.16 树的合并

#include "stdio.h"

#define MAX_PARENT 100
int parent[MAX_PARENT];

void Initialize(int n) {/* 初始化,每个类/树有一个元素*/
    int e;
    for (e = 1; e <= n && n < MAX_PARENT; e++)
        parent[e] = 0;
}

int Find(int e) { /*返回包含e的树的根节点*/
    while (parent[e] && e < MAX_PARENT)
        e = parent[e]; /* 上移一层*/
    return e;
}

void Union(int i, int j) {/* 将根为i 和j的两棵树进行合并*/
    if (j < MAX_PARENT)
        parent[j] = i;
}

void Combine(int a, int b) {
    int i = Find(a);
    int j = Find(b);
    if (i != j)
        Union(i, j);
}

int main() {
    Combine(1, 2);
    return 0;
}

运行结果

1.4.17 树的二叉链表存储的基本操作

#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<math.h> /* floor(),ceil(),abs() */
#include <cstring>

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW 3
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef char TElemType;
TElemType Nil = ' '; /* 以空格符为空 */
typedef struct CSNode {
    TElemType data;
    struct CSNode *firstchild, *nextsibling;
} CSNode, *CSTree;

Status InitTree(CSTree *T) { /* 操作结果: 构造空树T */
    *T = NULL;
    return OK;
}

void DestroyTree(CSTree *T) { /* 初始条件: 树T存在。操作结果: 销毁树T */
    if (*T) {
        if ((*T)->firstchild) /* T有长子 */
            DestroyTree(&(*T)->firstchild); /* 销毁T的长子为根结点的子树 */
        if ((*T)->nextsibling) /* T有下一个兄弟 */
            DestroyTree(&(*T)->nextsibling); /* 销毁T的下一个兄弟为根结点的子树 */
        free(*T); /* 释放根结点 */
        *T = NULL;
    }
}

typedef CSTree QElemType; /* 定义队列元素类型 */
typedef struct QNode {
    QElemType data;
    struct QNode *next;
} QNode, *QueuePtr;
typedef struct {
    QueuePtr front, rear; /* 队头、队尾指针 */
} LinkQueue;

/* bo3-2.c 链队列(存储结构由c3-2.h定义)的基本操作(9个) */
Status InitQueue(LinkQueue *Q) { /* 构造一个空队列Q */
    (*Q).front = (*Q).rear = (QueuePtr) malloc(sizeof(QNode));
    if (!(*Q).front)
        exit(OVERFLOW);
    (*Q).front->next = NULL;
    return OK;
}

Status QueueEmpty(LinkQueue Q) { /* 若Q为空队列,则返回TRUE,否则返回FALSE */
    if (Q.front == Q.rear)
        return TRUE;
    else
        return FALSE;
}

Status EnQueue(LinkQueue *Q, QElemType e) { /* 插入元素e为Q的新的队尾元素 */
    QueuePtr p = (QueuePtr) malloc(sizeof(QNode));
    if (!p) /* 存储分配失败 */
        exit(OVERFLOW);
    p->data = e;
    p->next = NULL;
    (*Q).rear->next = p;
    (*Q).rear = p;
    return OK;
}

Status DeQueue(LinkQueue *Q, QElemType *e) { /* 若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR */
    QueuePtr p;
    if ((*Q).front == (*Q).rear)
        return ERROR;
    p = (*Q).front->next;
    *e = p->data;
    (*Q).front->next = p->next;
    if ((*Q).rear == p)
        (*Q).rear = (*Q).front;
    free(p);
    return OK;
}

Status CreateTree(CSTree *T) { /* 构造树T */
    char c[20]; /* 临时存放孩子结点(设不超过20个)的值 */
    CSTree p, p1;
    LinkQueue q;
    int i, l;
    InitQueue(&q);
    printf("请输入根结点(字符型,空格为空): ");
    scanf("%c%*c", &c[0]);
    if (c[0] != Nil) /* 非空树 */
    {
        *T = (CSTree) malloc(sizeof(CSNode)); /* 建立根结点 */
        (*T)->data = c[0];
        (*T)->nextsibling = NULL;
        EnQueue(&q, *T); /* 入队根结点的指针 */
        while (!QueueEmpty(q)) /* 队不空 */
        {
            DeQueue(&q, &p); /* 出队一个结点的指针 */
            printf("请按长幼顺序输入结点%c的所有孩子: ", p->data);
            fgets(c, 20, stdin);
            l = strlen(c);
            if (l > 0) /* 有孩子 */
            {
                p1 = p->firstchild = (CSTree) malloc(sizeof(CSNode)); /* 建立长子结点 */
                p1->data = c[0];
                for (i = 1; i < l; i++) {
                    p1->nextsibling = (CSTree) malloc(sizeof(CSNode)); /* 建立下一个兄弟结点 */
                    EnQueue(&q, p1); /* 入队上一个结点 */
                    p1 = p1->nextsibling;
                    p1->data = c[i];
                }
                p1->nextsibling = NULL;
                EnQueue(&q, p1); /* 入队最后一个结点 */
            } else
                p->firstchild = NULL;
        }
    } else
        *T = NULL;
    return OK;
}

#define ClearTree DestroyTree /* 二者操作相同 */

Status TreeEmpty(CSTree T) { /* 初始条件: 树T存在。操作结果: 若T为空树,则返回TURE,否则返回FALSE */
    if (T) /* T不空 */
        return FALSE;
    else
        return TRUE;
}

int TreeDepth(CSTree T) { /* 初始条件: 树T存在。操作结果: 返回T的深度 */
    CSTree p;
    int depth, max = 0;
    if (!T) /* 树空 */
        return 0;
    if (!T->firstchild) /* 树无长子 */
        return 1;
    for (p = T->firstchild; p; p = p->nextsibling) {
        depth = TreeDepth(p);
        if (depth > max)
            max = depth;
    }
    return max + 1;
}

TElemType Value(CSTree p) { /* 返回p所指结点的值 */
    return p->data;
}

TElemType Root(CSTree T) { /* 初始条件: 树T存在。操作结果: 返回T的根 */
    if (T)
        return Value(T);
    else
        return Nil;
}

CSTree Point(CSTree T, TElemType s) { /* 返回二叉链表(孩子-兄弟)树T中指向元素值为s的结点的指针。另加 */
    LinkQueue q;
    QElemType a;
    if (T) /* 非空树 */
    {
        InitQueue(&q); /* 初始化队列 */
        EnQueue(&q, T); /* 根结点入队 */
        while (!QueueEmpty(q)) /* 队不空 */
        {
            DeQueue(&q, &a); /* 出队,队列元素赋给a */
            if (a->data == s)
                return a;
            if (a->firstchild) /* 有长子 */
                EnQueue(&q, a->firstchild); /* 入队长子 */
            if (a->nextsibling) /* 有下一个兄弟 */
                EnQueue(&q, a->nextsibling); /* 入队下一个兄弟 */
        }
    }
    return NULL;
}

Status Assign(CSTree *T, TElemType cur_e, TElemType value) { /* 初始条件: 树T存在,cur_e是树T中结点的值。操作结果: 改cur_e为value */
    CSTree p;
    if (*T) /* 非空树 */
    {
        p = Point(*T, cur_e); /* p为cur_e的指针 */
        if (p) /* 找到cur_e */
        {
            p->data = value; /* 赋新值 */
            return OK;
        }
    }
    return Nil; /* 树空或没找到 */
}

TElemType Parent(CSTree T, TElemType cur_e) { /* 初始条件: 树T存在,cur_e是T中某个结点 */
    /* 操作结果: 若cur_e是T的非根结点,则返回它的双亲,否则函数值为"空" */
    CSTree p, t;
    LinkQueue q;
    InitQueue(&q);
    if (T) /* 树非空 */
    {
        if (Value(T) == cur_e) /* 根结点值为cur_e */
            return Nil;
        EnQueue(&q, T); /* 根结点入队 */
        while (!QueueEmpty(q)) {
            DeQueue(&q, &p);
            if (p->firstchild) /* p有长子 */
            {
                if (p->firstchild->data == cur_e) /* 长子为cur_e */
                    return Value(p); /* 返回双亲 */
                t = p; /* 双亲指针赋给t */
                p = p->firstchild; /* p指向长子 */
                EnQueue(&q, p); /* 入队长子 */
                while (p->nextsibling) /* 有下一个兄弟 */
                {
                    p = p->nextsibling; /* p指向下一个兄弟 */
                    if (Value(p) == cur_e) /* 下一个兄弟为cur_e */
                        return Value(t); /* 返回双亲 */
                    EnQueue(&q, p); /* 入队下一个兄弟 */
                }
            }
        }
    }
    return Nil; /* 树空或没找到cur_e */
}

TElemType LeftChild(CSTree T, TElemType cur_e) { /* 初始条件: 树T存在,cur_e是T中某个结点 */
    /* 操作结果: 若cur_e是T的非叶子结点,则返回它的最左孩子,否则返回"空" */
    CSTree f;
    f = Point(T, cur_e); /* f指向结点cur_e */
    if (f && f->firstchild) /* 找到结点cur_e且结点cur_e有长子 */
        return f->firstchild->data;
    else
        return Nil;
}

TElemType RightSibling(CSTree T, TElemType cur_e) { /* 初始条件: 树T存在,cur_e是T中某个结点 */
    /* 操作结果: 若cur_e有右兄弟,则返回它的右兄弟,否则返回"空" */
    CSTree f;
    f = Point(T, cur_e); /* f指向结点cur_e */
    if (f && f->nextsibling) /* 找到结点cur_e且结点cur_e有右兄弟 */
        return f->nextsibling->data;
    else
        return Nil; /* 树空 */
}

Status InsertChild(CSTree *T, CSTree p, int i, CSTree c) { /* 初始条件: 树T存在,p指向T中某个结点,1≤i≤p所指结点的度+1,非空树c与T不相交 */
    /* 操作结果: 插入c为T中p结点的第i棵子树 */
    /* 因为p所指结点的地址不会改变,故p不需是引用类型 */
    int j;
    if (*T) /* T不空 */
    {
        if (i == 1) /* 插入c为p的长子 */
        {
            c->nextsibling = p->firstchild; /* p的原长子现是c的下一个兄弟(c本无兄弟) */
            p->firstchild = c;
        } else /* 找插入点 */
        {
            p = p->firstchild; /* 指向p的长子 */
            j = 2;
            while (p && j < i) {
                p = p->nextsibling;
                j++;
            }
            if (j == i) /* 找到插入位置 */
            {
                c->nextsibling = p->nextsibling;
                p->nextsibling = c;
            } else /* p原有孩子数小于i-1 */
                return ERROR;
        }
        return OK;
    } else /* T空 */
        return ERROR;
}

Status DeleteChild(CSTree *T, CSTree p, int i) { /* 初始条件: 树T存在,p指向T中某个结点,1≤i≤p所指结点的度 */
    /* 操作结果: 删除T中p所指结点的第i棵子树 */
    /* 因为p所指结点的地址不会改变,故p不需是引用类型 */
    CSTree b;
    int j;
    if (*T) /* T不空 */
    {
        if (i == 1) /* 删除长子 */
        {
            b = p->firstchild;
            p->firstchild = b->nextsibling; /* p的原次子现是长子 */
            b->nextsibling = NULL;
            DestroyTree(&b);
        } else /* 删除非长子 */
        {
            p = p->firstchild; /* p指向长子 */
            j = 2;
            while (p && j < i) {
                p = p->nextsibling;
                j++;
            }
            if (j == i) /* 找到第i棵子树 */
            {
                b = p->nextsibling;
                p->nextsibling = b->nextsibling;
                b->nextsibling = NULL;
                DestroyTree(&b);
            } else /* p原有孩子数小于i */
                return ERROR;
        }
        return OK;
    } else
        return ERROR;
}

void PreOrderTraverse(CSTree T, void(*Visit)(TElemType)) { /* 先根遍历孩子-兄弟二叉链表结构的树T */
    if (T) {
        Visit(Value(T)); /* 先访问根结点 */
        PreOrderTraverse(T->firstchild, Visit); /* 再先根遍历长子子树 */
        PreOrderTraverse(T->nextsibling, Visit); /* 最后先根遍历下一个兄弟子树 */
    }
}

void PostOrderTraverse(CSTree T, void(*Visit)(TElemType)) { /* 后根遍历孩子-兄弟二叉链表结构的树T */
    CSTree p;
    if (T) {
        if (T->firstchild) /* 有长子 */
        {
            PostOrderTraverse(T->firstchild, Visit); /* 后根遍历长子子树 */
            p = T->firstchild->nextsibling; /* p指向长子的下一个兄弟 */
            while (p) {
                PostOrderTraverse(p, Visit); /* 后根遍历下一个兄弟子树 */
                p = p->nextsibling; /* p指向再下一个兄弟 */
            }
        }
        Visit(Value(T)); /* 最后访问根结点 */
    }
}

void LevelOrderTraverse(CSTree T, void(*Visit)(TElemType)) { /* 层序遍历孩子-兄弟二叉链表结构的树T */
    CSTree p;
    LinkQueue q;
    InitQueue(&q);
    if (T) {
        Visit(Value(T)); /* 先访问根结点 */
        EnQueue(&q, T); /* 入队根结点的指针 */
        while (!QueueEmpty(q)) /* 队不空 */
        {
            DeQueue(&q, &p); /* 出队一个结点的指针 */
            if (p->firstchild) /* 有长子 */
            {
                p = p->firstchild;
                Visit(Value(p)); /* 访问长子结点 */
                EnQueue(&q, p); /* 入队长子结点的指针 */
                while (p->nextsibling) /* 有下一个兄弟 */
                {
                    p = p->nextsibling;
                    Visit(Value(p)); /* 访问下一个兄弟 */
                    EnQueue(&q, p); /* 入队兄弟结点的指针 */
                }
            }
        }
    }
}

void vi(TElemType c) {
    printf("%c ", c);
}

int main() {
    int i;
    CSTree T, p, q;
    TElemType e, e1;
    InitTree(&T);
    printf("构造空树后,树空否? %d(1:是 0:否) 树根为%c 树的深度为%d\n", TreeEmpty(T), Root(T), TreeDepth(T));
    CreateTree(&T);
    printf("构造树T后,树空否? %d(1:是 0:否) 树根为%c 树的深度为%d\n", TreeEmpty(T), Root(T), TreeDepth(T));
    printf("先根遍历树T:\n");
    PreOrderTraverse(T, vi);
    printf("\n请输入待修改的结点的值 新值: ");
    scanf("%c%*c%c%*c", &e, &e1);
    Assign(&T, e, e1);
    printf("后根遍历修改后的树T:\n");
    PostOrderTraverse(T, vi);
    printf("\n%c的双亲是%c,长子是%c,下一个兄弟是%c\n", e1, Parent(T, e1), LeftChild(T, e1), RightSibling(T, e1));
    printf("建立树p:\n");
    InitTree(&p);
    CreateTree(&p);
    printf("层序遍历树p:\n");
    LevelOrderTraverse(p, vi);
    printf("\n将树p插到树T中,请输入T中p的双亲结点 子树序号: ");
    scanf("%c%d%*c", &e, &i);
    q = Point(T, e);
    InsertChild(&T, q, i, p);
    printf("层序遍历树T:\n");
    LevelOrderTraverse(T, vi);
    printf("\n删除树T中结点e的第i棵子树,请输入e i: ");
    scanf("%c%d", &e, &i);
    q = Point(T, e);
    DeleteChild(&T, q, i);
    printf("层序遍历树T:\n", e, i);
    LevelOrderTraverse(T, vi);
    printf("\n");
    DestroyTree(&T);
    return 0;
}

运行结果

1.4.18 二叉树的三叉链表存储的基本操作

#define CHAR /* 字符型 */

#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<math.h> /* floor(),ceil(),abs() */

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW 3
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
#ifdef CHAR
typedef char TElemType;
TElemType Nil = ' '; /* 字符型以空格符为空 */
#endif
#ifdef INT
typedef int TElemType;
  TElemType Nil=0; /* 整型以0为空 */
#endif
typedef struct BiTPNode {
    TElemType data;
    struct BiTPNode *parent, *lchild, *rchild; /* 双亲、左右孩子指针 */
} BiTPNode, *BiPTree;

Status InitBiTree(BiPTree *T) { /* 操作结果: 构造空二叉树T */
    *T = NULL;
    return OK;
}

void DestroyBiTree(BiPTree *T) { /* 初始条件: 二叉树T存在。操作结果: 销毁二叉树T */
    if (*T) /* 非空树 */
    {
        if ((*T)->lchild) /* 有左孩子 */
            DestroyBiTree(&(*T)->lchild); /* 销毁左孩子子树 */
        if ((*T)->rchild) /* 有右孩子 */
            DestroyBiTree(&(*T)->rchild); /* 销毁右孩子子树 */
        free(*T); /* 释放根结点 */
        *T = NULL; /* 空指针赋0 */
    }
}

void Create(BiPTree *T) /* CreateBiTree()调用 */
{ /* 按先序次序输入二叉树中结点的值(可为字符型或整型,在主程中定义), */
    /* 构造仅缺双亲指针的三叉链表表示的二叉树T。变量Nil表示空(子)树 */
    TElemType ch;
#ifdef CHAR
    scanf("%c", &ch);
#endif
#ifdef INT
    scanf("%d",&ch);
#endif
    if (ch == Nil) /* 空 */
        *T = NULL;
    else {
        *T = (BiPTree) malloc(sizeof(BiTPNode));
        if (!*T)
            exit(OVERFLOW);
        (*T)->data = ch; /* 生成根结点 */
        Create(&(*T)->lchild); /* 构造左子树 */
        Create(&(*T)->rchild); /* 构造右子树 */
    }
}

typedef BiPTree QElemType; /* 设队列元素为二叉树的指针类型 */
/* c3-2.h 单链队列--队列的链式存储结构 */
typedef struct QNode {
    QElemType data;
    struct QNode *next;
} QNode, *QueuePtr;
typedef struct {
    QueuePtr front, rear; /* 队头、队尾指针 */
} LinkQueue;

Status InitQueue(LinkQueue *Q) { /* 构造一个空队列Q */
    (*Q).front = (*Q).rear = (QueuePtr) malloc(sizeof(QNode));
    if (!(*Q).front)
        exit(OVERFLOW);
    (*Q).front->next = NULL;
    return OK;
}

Status QueueEmpty(LinkQueue Q) { /* 若Q为空队列,则返回TRUE,否则返回FALSE */
    if (Q.front == Q.rear)
        return TRUE;
    else
        return FALSE;
}

Status EnQueue(LinkQueue *Q, QElemType e) { /* 插入元素e为Q的新的队尾元素 */
    QueuePtr p = (QueuePtr) malloc(sizeof(QNode));
    if (!p) /* 存储分配失败 */
        exit(OVERFLOW);
    p->data = e;
    p->next = NULL;
    (*Q).rear->next = p;
    (*Q).rear = p;
    return OK;
}

Status DeQueue(LinkQueue *Q, QElemType *e) { /* 若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR */
    QueuePtr p;
    if ((*Q).front == (*Q).rear)
        return ERROR;
    p = (*Q).front->next;
    *e = p->data;
    (*Q).front->next = p->next;
    if ((*Q).rear == p)
        (*Q).rear = (*Q).front;
    free(p);
    return OK;
}

Status CreateBiTree(BiPTree *T) { /* 按先序次序输入二叉树中结点的值(可为字符型或整型,在主程中定义), */
    /* 构造三叉链表表示的二叉树T */
    LinkQueue q;
    QElemType a;
    Create(T); /* 构造二叉树(缺双亲指针) */
    if (*T) /* 非空树 */
    {
        (*T)->parent = NULL; /* 根结点的双亲为"空" */
        InitQueue(&q); /* 初始化队列 */
        EnQueue(&q, *T); /* 根指针入队 */
        while (!QueueEmpty(q)) /* 队不空 */
        {
            DeQueue(&q, &a); /* 出队,队列元素赋给a */
            if (a->lchild) /* 有左孩子 */
            {
                a->lchild->parent = a; /* 给左孩子的双亲指针赋值 */
                EnQueue(&q, a->lchild); /* 左孩子入队 */
            }
            if (a->rchild) /* 有右孩子 */
            {
                a->rchild->parent = a; /* 给右孩子的双亲指针赋值 */
                EnQueue(&q, a->rchild); /* 右孩子入队 */
            }
        }
    }
    return OK;
}

#define ClearBiTree DestroyBiTree

Status BiTreeEmpty(BiPTree T) { /* 初始条件: 二叉树T存在。操作结果: 若T为空二叉树,则返回TRUE,否则FALSE */
    if (T)
        return FALSE;
    else
        return TRUE;
}

int BiTreeDepth(BiPTree T) { /* 初始条件: 二叉树T存在。操作结果: 返回T的深度 */
    int i, j;
    if (!T)
        return 0;
    if (T->lchild)
        i = BiTreeDepth(T->lchild);
    else
        i = 0;
    if (T->rchild)
        j = BiTreeDepth(T->rchild);
    else
        j = 0;
    return i > j ? i + 1 : j + 1;
}

TElemType Root(BiPTree T) { /* 初始条件: 二叉树T存在。操作结果: 返回T的根 */
    if (T)
        return T->data;
    else
        return Nil;
}

TElemType Value(BiPTree p) { /* 初始条件: 二叉树T存在,p指向T中某个结点 */
    /* 操作结果: 返回p所指结点的值 */
    return p->data;
}

void Assign(BiPTree p, TElemType value) { /* 给p所指结点赋值为value */
    p->data = value;
}

BiPTree Point(BiPTree T, TElemType e) { /* 返回二叉树T中指向元素值为e的结点的指针。加 */
    LinkQueue q;
    QElemType a;
    if (T) /* 非空树 */
    {
        InitQueue(&q); /* 初始化队列 */
        EnQueue(&q, T); /* 根结点入队 */
        while (!QueueEmpty(q)) /* 队不空 */
        {
            DeQueue(&q, &a); /* 出队,队列元素赋给a */
            if (a->data == e)
                return a;
            if (a->lchild) /* 有左孩子 */
                EnQueue(&q, a->lchild); /* 入队左孩子 */
            if (a->rchild) /* 有右孩子 */
                EnQueue(&q, a->rchild); /* 入队右孩子 */
        }
    }
    return NULL;
}

TElemType Parent(BiPTree T, TElemType e) { /* 初始条件: 二叉树T存在,e是T中某个结点 */
    /* 操作结果: 若e是T的非根结点,则返回它的双亲,否则返回"空" */
    BiPTree a;
    if (T) /* 非空树 */
    {
        a = Point(T, e); /* a是结点e的指针 */
        if (a && a != T) /* T中存在结点e且e是非根结点 */
            return a->parent->data; /* 返回e的双亲的值 */
    }
    return Nil; /* 其余情况返回空 */
}

TElemType LeftChild(BiPTree T, TElemType e) { /* 初始条件: 二叉树T存在,e是T中某个结点 */
    /* 操作结果: 返回e的左孩子。若e无左孩子,则返回"空" */
    BiPTree a;
    if (T) /* 非空树 */
    {
        a = Point(T, e); /* a是结点e的指针 */
        if (a && a->lchild) /* T中存在结点e且e存在左孩子 */
            return a->lchild->data; /* 返回e的左孩子的值 */
    }
    return Nil; /* 其余情况返回空 */
}

TElemType RightChild(BiPTree T, TElemType e) { /* 初始条件: 二叉树T存在,e是T中某个结点 */
    /* 操作结果: 返回e的右孩子。若e无右孩子,则返回"空" */
    BiPTree a;
    if (T) /* 非空树 */
    {
        a = Point(T, e); /* a是结点e的指针 */
        if (a && a->rchild) /* T中存在结点e且e存在右孩子 */
            return a->rchild->data; /* 返回e的右孩子的值 */
    }
    return Nil; /* 其余情况返回空 */
}

TElemType LeftSibling(BiPTree T, TElemType e) { /* 初始条件: 二叉树T存在,e是T中某个结点 */
    /* 操作结果: 返回e的左兄弟。若e是T的左孩子或无左兄弟,则返回"空" */
    BiPTree a;
    if (T) /* 非空树 */
    {
        a = Point(T, e); /* a是结点e的指针 */
        if (a && a != T && a->parent->lchild && a->parent->lchild != a) /* T中存在结点e且e存在左兄弟 */
            return a->parent->lchild->data; /* 返回e的左兄弟的值 */
    }
    return Nil; /* 其余情况返回空 */
}

TElemType RightSibling(BiPTree T, TElemType e) { /* 初始条件: 二叉树T存在,e是T中某个结点 */
    /* 操作结果: 返回e的右兄弟。若e是T的右孩子或无右兄弟,则返回"空" */
    BiPTree a;
    if (T) /* 非空树 */
    {
        a = Point(T, e); /* a是结点e的指针 */
        if (a && a != T && a->parent->rchild && a->parent->rchild != a) /* T中存在结点e且e存在右兄弟 */
            return a->parent->rchild->data; /* 返回e的右兄弟的值 */
    }
    return Nil; /* 其余情况返回空 */
}

Status InsertChild(BiPTree p, int LR, BiPTree c) /* 形参T无用 */
{ /* 初始条件: 二叉树T存在,p指向T中某个结点,LR为0或1,非空二叉树c与T */
    /*           不相交且右子树为空 */
    /* 操作结果: 根据LR为0或1,插入c为T中p所指结点的左或右子树。p所指结点 */
    /*           的原有左或右子树则成为c的右子树。 */
    if (p) /* p不空 */
    {
        if (LR == 0) {
            c->rchild = p->lchild;
            if (c->rchild) /* c有右孩子(p原有左孩子) */
                c->rchild->parent = c;
            p->lchild = c;
            c->parent = p;
        } else /* LR==1 */
        {
            c->rchild = p->rchild;
            if (c->rchild) /* c有右孩子(p原有右孩子) */
                c->rchild->parent = c;
            p->rchild = c;
            c->parent = p;
        }
        return OK;
    }
    return ERROR; /* p空 */
}

Status DeleteChild(BiPTree p, int LR) /* 形参T无用 */
{ /* 初始条件: 二叉树T存在,p指向T中某个结点,LR为0或1 */
    /* 操作结果: 根据LR为0或1,删除T中p所指结点的左或右子树 */
    if (p) /* p不空 */
    {
        if (LR == 0) /* 删除左子树 */
            ClearBiTree(&p->lchild);
        else /* 删除右子树 */
            ClearBiTree(&p->rchild);
        return OK;
    }
    return ERROR; /* p空 */
}

void PreOrderTraverse(BiPTree T, Status(*Visit)(BiPTree)) { /* 先序递归遍历二叉树T */
    if (T) {
        Visit(T); /* 先访问根结点 */
        PreOrderTraverse(T->lchild, Visit); /* 再先序遍历左子树 */
        PreOrderTraverse(T->rchild, Visit); /* 最后先序遍历右子树 */
    }
}

void InOrderTraverse(BiPTree T, Status(*Visit)(BiPTree)) { /* 中序递归遍历二叉树T */
    if (T) {
        InOrderTraverse(T->lchild, Visit); /* 中序遍历左子树 */
        Visit(T); /* 再访问根结点 */
        InOrderTraverse(T->rchild, Visit); /* 最后中序遍历右子树 */
    }
}

void PostOrderTraverse(BiPTree T, Status(*Visit)(BiPTree)) { /* 后序递归遍历二叉树T */
    if (T) {
        PostOrderTraverse(T->lchild, Visit); /* 后序遍历左子树 */
        PostOrderTraverse(T->rchild, Visit); /* 后序遍历右子树 */
        Visit(T); /* 最后访问根结点 */
    }
}

void LevelOrderTraverse(BiPTree T, Status(*Visit)(BiPTree)) { /* 层序遍历二叉树T(利用队列) */
    LinkQueue q;
    QElemType a;
    if (T) {
        InitQueue(&q);
        EnQueue(&q, T);
        while (!QueueEmpty(q)) {
            DeQueue(&q, &a);
            Visit(a);
            if (a->lchild != NULL)
                EnQueue(&q, a->lchild);
            if (a->rchild != NULL)
                EnQueue(&q, a->rchild);
        }
    }
}

Status visitT(BiPTree T) {
    if (T) /* T非空 */
#ifdef CHAR
        printf("%c是", T->data);
    if (T->parent) /* T有双亲 */
    {
        printf("%c", T->parent->data);
#endif
#ifdef INT
        printf("%d是",T->data);
  if(T->parent) /* T有双亲 */
  {
    printf("%d",T->parent->data);
#endif
        if (T->parent->lchild == T)
            printf("的左孩子\n");
        else
            printf("的右孩子\n");
    } else
        printf("根结点\n");
    return OK;
}

int main() {
    int i;
    BiPTree T, c, q;
    TElemType e1, e2;
    InitBiTree(&T);
    printf("构造空二叉树后,树空否?%d(1:是 0:否) 树的深度=%d\n", BiTreeEmpty(T), BiTreeDepth(T));
    e1 = Root(T);
    if (e1 != Nil)
#ifdef CHAR
        printf("二叉树的根为: %c\n", e1);
#endif
#ifdef INT
        printf("二叉树的根为: %d\n",e1);
#endif
    else
        printf("树空,无根\n");
#ifdef CHAR
    printf("请按先序输入二叉树(如:ab三个空格表示a为根结点,b为左子树的二叉树)\n");
#endif
#ifdef INT
    printf("请按先序输入二叉树(如:1 2 0 0 0表示1为根结点,2为左子树的二叉树)\n");
#endif
    CreateBiTree(&T);
    printf("建立二叉树后,树空否?%d(1:是 0:否) 树的深度=%d\n", BiTreeEmpty(T), BiTreeDepth(T));
    e1 = Root(T);
    if (e1 != Nil)
#ifdef CHAR
        printf("二叉树的根为: %c\n", e1);
#endif
#ifdef INT
        printf("二叉树的根为: %d\n",e1);
#endif
    else
        printf("树空,无根\n");
    printf("中序递归遍历二叉树:\n");
    InOrderTraverse(T, visitT);
    printf("后序递归遍历二叉树:\n");
    PostOrderTraverse(T, visitT);
    scanf("%*c"); /* 吃掉回车符 */
    printf("按回车键继续:");
    getchar(); /* 暂停输出 */
    printf("层序遍历二叉树:\n");
    LevelOrderTraverse(T, visitT);
    printf("请输入一个结点的值: ");
#ifdef CHAR
    scanf("%c", &e1);
#endif
#ifdef INT
    scanf("%d",&e1);
#endif
    c = Point(T, e1); /* c为e1的指针 */
#ifdef CHAR
    printf("结点的值为%c\n", Value(c));
#endif
#ifdef INT
    printf("结点的值为%d\n",Value(c));
#endif
    printf("欲改变此结点的值,请输入新值: ");
#ifdef CHAR
    scanf("%*c%c%*c", &e2);
#endif
#ifdef INT
    scanf("%d",&e2);
#endif
    Assign(c, e2);
    printf("层序遍历二叉树:\n");
    LevelOrderTraverse(T, visitT);
    e1 = Parent(T, e2);
    if (e1 != Nil)
#ifdef CHAR
        printf("%c的双亲是%c\n", e2, e1);
#endif
#ifdef INT
        printf("%d的双亲是%d\n",e2,e1);
#endif
    else
#ifdef CHAR
        printf("%c没有双亲\n", e2);
#endif
#ifdef INT
    printf("%d没有双亲\n",e2);
#endif
    e1 = LeftChild(T, e2);
    if (e1 != Nil)
#ifdef CHAR
        printf("%c的左孩子是%c\n", e2, e1);
#endif
#ifdef INT
        printf("%d的左孩子是%d\n",e2,e1);
#endif
    else
#ifdef CHAR
        printf("%c没有左孩子\n", e2);
#endif
#ifdef INT
    printf("%d没有左孩子\n",e2);
#endif
    e1 = RightChild(T, e2);
    if (e1 != Nil)
#ifdef CHAR
        printf("%c的右孩子是%c\n", e2, e1);
#endif
#ifdef INT
        printf("%d的右孩子是%d\n",e2,e1);
#endif
    else
#ifdef CHAR
        printf("%c没有右孩子\n", e2);
#endif
#ifdef INT
    printf("%d没有右孩子\n",e2);
#endif
    e1 = LeftSibling(T, e2);
    if (e1 != Nil)
#ifdef CHAR
        printf("%c的左兄弟是%c\n", e2, e1);
#endif
#ifdef INT
        printf("%d的左兄弟是%d\n",e2,e1);
#endif
    else
#ifdef CHAR
        printf("%c没有左兄弟\n", e2);
#endif
#ifdef INT
    printf("%d没有左兄弟\n",e2);
#endif
    e1 = RightSibling(T, e2);
    if (e1 != Nil)
#ifdef CHAR
        printf("%c的右兄弟是%c\n", e2, e1);
#endif
#ifdef INT
        printf("%d的右兄弟是%d\n",e2,e1);
#endif
    else
#ifdef CHAR
        printf("%c没有右兄弟\n", e2);
#endif
#ifdef INT
    printf("%d没有右兄弟\n",e2);
#endif
    InitBiTree(&c);
    printf("构造一个右子树为空的二叉树c:\n");
#ifdef CHAR
    printf("请先序输入二叉树(如:ab三个空格表示a为根结点,b为左子树的二叉树)\n");
#endif
#ifdef INT
    printf("请先序输入二叉树(如:1 2 0 0 0表示1为根结点,2为左子树的二叉树)\n");
#endif
    CreateBiTree(&c);
    printf("先序递归遍历二叉树c:\n");
    PreOrderTraverse(c, visitT);
    printf("树c插到树T中,请输入树T中树c的双亲结点 c为左(0)或右(1)子树: ");
#ifdef CHAR
    scanf("%*c%c%d", &e1, &i);
#endif
#ifdef INT
    scanf("%d%d",&e1,&i);
#endif
    q = Point(T, e1);
    InsertChild(q, i, c);
    printf("先序递归遍历二叉树:\n");
    PreOrderTraverse(T, visitT);
    printf("删除子树,请输入待删除子树的双亲结点  左(0)或右(1)子树: ");
#ifdef CHAR
    scanf("%*c%c%d", &e1, &i);
#endif
#ifdef INT
    scanf("%d%d",&e1,&i);
#endif
    q = Point(T, e1);
    DeleteChild(q, i);
    printf("先序递归遍历二叉树:\n");
    PreOrderTraverse(T, visitT);
    DestroyBiTree(&T);
    return 0;
}

运行结果

1.4.19 二叉树的二叉线索存储的基本操作

#define CHAR 1 /* 字符型 */
#if CHAR
typedef char TElemType;
TElemType Nil = ' '; /* 字符型以空格符为空 */
#else
typedef int TElemType;
  TElemType Nil=0; /* 整型以0为空 */
#endif

#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<math.h> /* floor(),ceil(),abs() */

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW 3
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef enum {
    Link, Thread
} PointerTag; /* Link(0):指针,Thread(1):线索 */
typedef struct BiThrNode {
    TElemType data;
    struct BiThrNode *lchild, *rchild; /* 左右孩子指针 */
    PointerTag LTag, RTag; /* 左右标志 */
} BiThrNode, *BiThrTree;

Status CreateBiThrTree(BiThrTree *T) { /* 按先序输入二叉线索树中结点的值,构造二叉线索树T */
    /* 0(整型)/空格(字符型)表示空结点 */
    TElemType h;
#if CHAR
    scanf("%c", &h);
#else
    scanf("%d",&h);
#endif
    if (h == Nil)
        *T = NULL;
    else {
        *T = (BiThrTree) malloc(sizeof(BiThrNode));
        if (!*T)
            exit(OVERFLOW);
        (*T)->data = h; /* 生成根结点(先序) */
        CreateBiThrTree(&(*T)->lchild); /* 递归构造左子树 */
        if ((*T)->lchild) /* 有左孩子 */
            (*T)->LTag = Link;
        CreateBiThrTree(&(*T)->rchild); /* 递归构造右子树 */
        if ((*T)->rchild) /* 有右孩子 */
            (*T)->RTag = Link;
    }
    return OK;
}

BiThrTree pre; /* 全局变量,始终指向刚刚访问过的结点 */
void InThreading(BiThrTree p) { /* 中序遍历进行中序线索化。*/
    if (p) {
        InThreading(p->lchild); /* 递归左子树线索化 */
        if (!p->lchild) /* 没有左孩子 */
        {
            p->LTag = Thread; /* 前驱线索 */
            p->lchild = pre; /* 左孩子指针指向前驱 */
        }
        if (!pre->rchild) /* 前驱没有右孩子 */
        {
            pre->RTag = Thread; /* 后继线索 */
            pre->rchild = p; /* 前驱右孩子指针指向后继(当前结点p) */
        }
        pre = p; /* 保持pre指向p的前驱 */
        InThreading(p->rchild); /* 递归右子树线索化 */
    }
}

Status InOrderThreading(BiThrTree *Thrt, BiThrTree T) { /* 中序遍历二叉树T,并将其中序线索化,Thrt指向头结点。*/
    *Thrt = (BiThrTree) malloc(sizeof(BiThrNode));
    if (!*Thrt)
        exit(OVERFLOW);
    (*Thrt)->LTag = Link; /* 建头结点 */
    (*Thrt)->RTag = Thread;
    (*Thrt)->rchild = *Thrt; /* 右指针回指 */
    if (!T) /* 若二叉树空,则左指针回指 */
        (*Thrt)->lchild = *Thrt;
    else {
        (*Thrt)->lchild = T;
        pre = *Thrt;
        InThreading(T); /* 中序遍历进行中序线索化 */
        pre->rchild = *Thrt;
        pre->RTag = Thread; /* 最后一个结点线索化 */
        (*Thrt)->rchild = pre;
    }
    return OK;
}

Status InOrderTraverse_Thr(BiThrTree T, Status(*Visit)(TElemType)) { /* 中序遍历二叉线索树T(头结点)的非递归算法。*/
    BiThrTree p;
    p = T->lchild; /* p指向根结点 */
    while (p != T) { /* 空树或遍历结束时,p==T */
        while (p->LTag == Link)
            p = p->lchild;
        if (!Visit(p->data)) /* 访问其左子树为空的结点 */
            return ERROR;
        while (p->RTag == Thread && p->rchild != T) {
            p = p->rchild;
            Visit(p->data); /* 访问后继结点 */
        }
        p = p->rchild;
    }
    return OK;
}

Status vi(TElemType c) {
#if CHAR
    printf("%c ", c);
#else
    printf("%d ",c);
#endif
    return OK;
}

int main() {
    BiThrTree H, T;
#if CHAR
    printf("请按先序输入二叉树(如:ab三个空格表示a为根结点,b为左子树的二叉树)\n");
#else
    printf("请按先序输入二叉树(如:1 2 0 0 0表示1为根结点,2为左子树的二叉树)\n");
#endif
    CreateBiThrTree(&T); /* 按先序产生二叉树 */
    InOrderThreading(&H, T); /* 中序遍历,并中序线索化二叉树 */
    printf("中序遍历(输出)二叉线索树:\n");
    InOrderTraverse_Thr(H, vi); /* 中序遍历(输出)二叉线索树 */
    printf("\n");
    return 0;
}

运行结果

1.4.20 树的双亲表存储的基本操作

#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<math.h> /* floor(),ceil(),abs() */
#include <cstring>

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW 3
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef char TElemType;
TElemType Nil = ' '; /* 以空格符为空 */
#define MAX_TREE_SIZE 100
typedef struct {
    TElemType data;
    int parent; /* 双亲位置域 */
} PTNode;
typedef struct {
    PTNode nodes[MAX_TREE_SIZE];
    int n; /* 结点数 */
} PTree;

Status InitTree(PTree *T) { /* 操作结果: 构造空树T */
    (*T).n = 0;
    return OK;
}

void DestroyTree() { /* 由于PTree是定长类型,无法销毁 */
}

typedef struct {
    int num;
    TElemType name;
} QElemType; /* 定义队列元素类型 */
typedef struct QNode {
    QElemType data;
    struct QNode *next;
} QNode, *QueuePtr;
typedef struct {
    QueuePtr front, rear; /* 队头、队尾指针 */
} LinkQueue;

Status InitQueue(LinkQueue *Q) { /* 构造一个空队列Q */
    (*Q).front = (*Q).rear = (QueuePtr) malloc(sizeof(QNode));
    if (!(*Q).front)
        exit(OVERFLOW);
    (*Q).front->next = NULL;
    return OK;
}

Status QueueEmpty(LinkQueue Q) { /* 若Q为空队列,则返回TRUE,否则返回FALSE */
    if (Q.front == Q.rear)
        return TRUE;
    else
        return FALSE;
}

Status EnQueue(LinkQueue *Q, QElemType e) { /* 插入元素e为Q的新的队尾元素 */
    QueuePtr p = (QueuePtr) malloc(sizeof(QNode));
    if (!p) /* 存储分配失败 */
        exit(OVERFLOW);
    p->data = e;
    p->next = NULL;
    (*Q).rear->next = p;
    (*Q).rear = p;
    return OK;
}

Status DeQueue(LinkQueue *Q, QElemType *e) { /* 若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR */
    QueuePtr p;
    if ((*Q).front == (*Q).rear)
        return ERROR;
    p = (*Q).front->next;
    *e = p->data;
    (*Q).front->next = p->next;
    if ((*Q).rear == p)
        (*Q).rear = (*Q).front;
    free(p);
    return OK;
}

Status CreateTree(PTree *T) { /* 操作结果: 构造树T */
    LinkQueue q;
    QElemType p, qq;
    int i = 1, j, l;
    char c[MAX_TREE_SIZE]; /* 临时存放孩子结点数组 */
    InitQueue(&q); /* 初始化队列 */
    printf("请输入根结点(字符型,空格为空): ");
    scanf("%c%*c", &(*T).nodes[0].data); /* 根结点序号为0,%*c吃掉回车符 */
    if ((*T).nodes[0].data != Nil) /* 非空树 */
    {
        (*T).nodes[0].parent = -1; /* 根结点无双亲 */
        qq.name = (*T).nodes[0].data;
        qq.num = 0;
        EnQueue(&q, qq); /* 入队此结点 */
        while (i < MAX_TREE_SIZE && !QueueEmpty(q)) /* 数组未满且队不空 */
        {
            DeQueue(&q, &qq); /* 出队一个结点 */
            printf("请按长幼顺序输入结点%c的所有孩子: ", qq.name);
            fgets(c, MAX_TREE_SIZE, stdin);
            l = strlen(c);
            for (j = 0; j < l; j++) {
                (*T).nodes[i].data = c[j];
                (*T).nodes[i].parent = qq.num;
                p.name = c[j];
                p.num = i;
                EnQueue(&q, p); /* 入队此结点 */
                i++;
            }
        }
        if (i > MAX_TREE_SIZE) {
            printf("结点数超过数组容量\n");
            exit(OVERFLOW);
        }
        (*T).n = i;
    } else
        (*T).n = 0;
    return OK;
}

#define ClearTree InitTree /* 二者操作相同 */

Status TreeEmpty(PTree T) { /* 初始条件: 树T存在。操作结果: 若T为空树,则返回TRUE,否则返回FALSE */
    if (T.n)
        return FALSE;
    else
        return TRUE;
}

int TreeDepth(PTree T) { /* 初始条件: 树T存在。操作结果: 返回T的深度 */
    int k, m, def, max = 0;
    for (k = 0; k < T.n; ++k) {
        def = 1; /* 初始化本际点的深度 */
        m = T.nodes[k].parent;
        while (m != -1) {
            m = T.nodes[m].parent;
            def++;
        }
        if (max < def)
            max = def;
    }
    return max; /* 最大深度 */
}

TElemType Root(PTree T) { /* 初始条件: 树T存在。操作结果: 返回T的根 */
    int i;
    for (i = 0; i < T.n; i++)
        if (T.nodes[i].parent < 0)
            return T.nodes[i].data;
    return Nil;
}

TElemType Value(PTree T, int i) { /* 初始条件: 树T存在,i是树T中结点的序号。操作结果: 返回第i个结点的值 */
    if (i < T.n)
        return T.nodes[i].data;
    else
        return Nil;
}

Status Assign(PTree *T, TElemType cur_e, TElemType value) { /* 初始条件: 树T存在,cur_e是树T中结点的值。操作结果: 改cur_e为value */
    int j;
    for (j = 0; j < (*T).n; j++) {
        if ((*T).nodes[j].data == cur_e) {
            (*T).nodes[j].data = value;
            return OK;
        }
    }
    return ERROR;
}

TElemType Parent(PTree T, TElemType cur_e) { /* 初始条件: 树T存在,cur_e是T中某个结点 */
    /* 操作结果: 若cur_e是T的非根结点,则返回它的双亲,否则函数值为"空" */
    int j;
    for (j = 1; j < T.n; j++) /* 根结点序号为0 */
        if (T.nodes[j].data == cur_e)
            return T.nodes[T.nodes[j].parent].data;
    return Nil;
}

TElemType LeftChild(PTree T, TElemType cur_e) { /* 初始条件: 树T存在,cur_e是T中某个结点 */
    /* 操作结果: 若cur_e是T的非叶子结点,则返回它的最左孩子,否则返回"空" */
    int i, j;
    for (i = 0; i < T.n; i++)
        if (T.nodes[i].data == cur_e) /* 找到cur_e,其序号为i */
            break;
    for (j = i + 1; j < T.n; j++) /* 根据树的构造函数,孩子的序号>其双亲的序号 */
        if (T.nodes[j].parent == i) /* 根据树的构造函数,最左孩子(长子)的序号<其它孩子的序号 */
            return T.nodes[j].data;
    return Nil;
}

TElemType RightSibling(PTree T, TElemType cur_e) { /* 初始条件: 树T存在,cur_e是T中某个结点 */
    /* 操作结果: 若cur_e有右(下一个)兄弟,则返回它的右兄弟,否则返回"空" */
    int i;
    for (i = 0; i < T.n; i++)
        if (T.nodes[i].data == cur_e) /* 找到cur_e,其序号为i */
            break;
    if (T.nodes[i + 1].parent == T.nodes[i].parent)
        /* 根据树的构造函数,若cur_e有右兄弟的话则右兄弟紧接其后 */
        return T.nodes[i + 1].data;
    return Nil;
}

Status Print(PTree T) { /* 输出树T。加 */
    int i;
    printf("结点个数=%d\n", T.n);
    printf(" 结点 双亲\n");
    for (i = 0; i < T.n; i++) {
        printf("    %c", Value(T, i)); /* 结点 */
        if (T.nodes[i].parent >= 0) /* 有双亲 */
            printf("    %c", Value(T, T.nodes[i].parent)); /* 双亲 */
        printf("\n");
    }
    return OK;
}

Status InsertChild(PTree *T, TElemType p, int i, PTree c) { /* 初始条件: 树T存在,p是T中某个结点,1≤i≤p所指结点的度+1,非空树c与T不相交 */
    /* 操作结果: 插入c为T中p结点的第i棵子树 */
    int j, k, l, f = 1, n = 0; /* 设交换标志f的初值为1,p的孩子数n的初值为0 */
    PTNode t;
    if (!TreeEmpty(*T)) /* T不空 */
    {
        for (j = 0; j < (*T).n; j++) /* 在T中找p的序号 */
            if ((*T).nodes[j].data == p) /* p的序号为j */
                break;
        l = j + 1; /* 如果c是p的第1棵子树,则插在j+1处 */
        if (i > 1) /* c不是p的第1棵子树 */
        {
            for (k = j + 1; k < (*T).n; k++) /* 从j+1开始找p的前i-1个孩子 */
                if ((*T).nodes[k].parent == j) /* 当前结点是p的孩子 */
                {
                    n++; /* 孩子数加1 */
                    if (n == i - 1) /* 找到p的第i-1个孩子,其序号为k1 */
                        break;
                }
            l = k + 1; /* c插在k+1处 */
        } /* p的序号为j,c插在l处 */
        if (l < (*T).n) /* 插入点l不在最后 */
            for (k = (*T).n - 1; k >= l; k--) /* 依次将序号l以后的结点向后移c.n个位置 */
            {
                (*T).nodes[k + c.n] = (*T).nodes[k];
                if ((*T).nodes[k].parent >= l)
                    (*T).nodes[k + c.n].parent += c.n;
            }
        for (k = 0; k < c.n; k++) {
            (*T).nodes[l + k].data = c.nodes[k].data; /* 依次将树c的所有结点插于此处 */
            (*T).nodes[l + k].parent = c.nodes[k].parent + l;
        }
        (*T).nodes[l].parent = j; /* 树c的根结点的双亲为p */
        (*T).n += c.n; /* 树T的结点数加c.n个 */
        while (f) { /* 从插入点之后,将结点仍按层序排列 */
            f = 0; /* 交换标志置0 */
            for (j = l; j < (*T).n - 1; j++)
                if ((*T).nodes[j].parent > (*T).nodes[j + 1].parent) {/* 如果结点j的双亲排在结点j+1的双亲之后(树没有按层序排列),交换两结点*/
                    t = (*T).nodes[j];
                    (*T).nodes[j] = (*T).nodes[j + 1];
                    (*T).nodes[j + 1] = t;
                    f = 1; /* 交换标志置1 */
                    for (k = j; k < (*T).n; k++) /* 改变双亲序号 */
                        if ((*T).nodes[k].parent == j)
                            (*T).nodes[k].parent++; /* 双亲序号改为j+1 */
                        else if ((*T).nodes[k].parent == j + 1)
                            (*T).nodes[k].parent--; /* 双亲序号改为j */
                }
        }
        return OK;
    } else /* 树T不存在 */
        return ERROR;
}

Status deleted[MAX_TREE_SIZE + 1]; /* 删除标志数组(全局量) */
void DeleteChild(PTree *T, TElemType p, int i) { /* 初始条件: 树T存在,p是T中某个结点,1≤i≤p所指结点的度 */
    /* 操作结果: 删除T中结点p的第i棵子树 */
    int j, k, n = 0;
    LinkQueue q;
    QElemType pq, qq;
    for (j = 0; j <= (*T).n; j++)
        deleted[j] = 0; /* 置初值为0(不删除标记) */
    pq.name = 'a'; /* 此成员不用 */
    InitQueue(&q); /* 初始化队列 */
    for (j = 0; j < (*T).n; j++)
        if ((*T).nodes[j].data == p)
            break; /* j为结点p的序号 */
    for (k = j + 1; k < (*T).n; k++) {
        if ((*T).nodes[k].parent == j)
            n++;
        if (n == i)
            break; /* k为p的第i棵子树结点的序号 */
    }
    if (k < (*T).n) /* p的第i棵子树结点存在 */
    {
        n = 0;
        pq.num = k;
        deleted[k] = 1; /* 置删除标记 */
        n++;
        EnQueue(&q, pq);
        while (!QueueEmpty(q)) {
            DeQueue(&q, &qq);
            for (j = qq.num + 1; j < (*T).n; j++)
                if ((*T).nodes[j].parent == qq.num) {
                    pq.num = j;
                    deleted[j] = 1; /* 置删除标记 */
                    n++;
                    EnQueue(&q, pq);
                }
        }
        for (j = 0; j < (*T).n; j++)
            if (deleted[j] == 1) {
                for (k = j + 1; k <= (*T).n; k++) {
                    deleted[k - 1] = deleted[k];
                    (*T).nodes[k - 1] = (*T).nodes[k];
                    if ((*T).nodes[k].parent > j)
                        (*T).nodes[k - 1].parent--;
                }
                j--;
            }
        (*T).n -= n; /* n为待删除结点数 */
    }
}

void TraverseTree(PTree T, void(*Visit)(TElemType)) { /* 初始条件:二叉树T存在,Visit是对结点操作的应用函数 */
    /* 操作结果:层序遍历树T,对每个结点调用函数Visit一次且仅一次 */
    int i;
    for (i = 0; i < T.n; i++)
        Visit(T.nodes[i].data);
    printf("\n");
}

void vi(TElemType c) {
    printf("%c ", c);
}

int main() {
    int i;
    PTree T, p;
    TElemType e, e1;
    InitTree(&T);
    printf("构造空树后,树空否? %d(1:是 0:否) 树根为%c 树的深度为%d\n", TreeEmpty(T), Root(T), TreeDepth(T));
    CreateTree(&T);
    printf("构造树T后,树空否? %d(1:是 0:否) 树根为%c 树的深度为%d\n", TreeEmpty(T), Root(T), TreeDepth(T));
    printf("层序遍历树T:\n");
    TraverseTree(T, vi);
    printf("请输入待修改的结点的值 新值: ");
    scanf("%c%*c%c%*c", &e, &e1);
    Assign(&T, e, e1);
    printf("层序遍历修改后的树T:\n");
    TraverseTree(T, vi);
    printf("%c的双亲是%c,长子是%c,下一个兄弟是%c\n", e1, Parent(T, e1), LeftChild(T, e1), RightSibling(T, e1));
    printf("建立树p:\n");
    InitTree(&p);
    CreateTree(&p);
    printf("层序遍历树p:\n");
    TraverseTree(p, vi);
    printf("将树p插到树T中,请输入T中p的双亲结点 子树序号: ");
    scanf("%c%d%*c", &e, &i);
    InsertChild(&T, e, i, p);
    Print(T);
    printf("删除树T中结点e的第i棵子树,请输入e i: ");
    scanf("%c%d", &e, &i);
    DeleteChild(&T, e, i);
    Print(T);
    return 0;
}

运行结果

1.4.21 哈夫曼编码(1)

#include <limits.h> /* INT_MAX等 */
#include <stdio.h> /* EOF(=^Z或F6),NULL */
#include <stdlib.h>
#include <cstring>

typedef struct {
    unsigned int weight;
    unsigned int parent, lchild, rchild;
} HTNode, *HuffmanTree; /* 动态分配数组存储赫夫曼树 */
typedef char **HuffmanCode; /* 动态分配数组存储赫夫曼编码表 */
int min1(HuffmanTree t, int i) { /* 函数void select()调用 */
    int j, flag;
    unsigned int k = UINT_MAX; /* 取k为不小于可能的值 */
    for (j = 1; j <= i; j++)
        if (t[j].weight < k && t[j].parent == 0)
            k = t[j].weight, flag = j;
    t[flag].parent = 1;
    return flag;
}

void select(HuffmanTree t, int i, int *s1, int *s2) { /* s1为最小的两个值中序号小的那个 */
    int j;
    *s1 = min1(t, i);
    *s2 = min1(t, i);
    if (*s1 > *s2) {
        j = *s1;
        *s1 = *s2;
        *s2 = j;
    }
}

void HuffmanCoding(HuffmanTree *HT, HuffmanCode *HC, int *w, int n) { /* w存放n个字符的权值(均>0),构造赫夫曼树HT,并求出n个字符的赫夫曼编码HC */
    int m, i, s1, s2, start;
    unsigned c, f;
    HuffmanTree p;
    char *cd;
    if (n <= 1)
        return;
    m = 2 * n - 1;
    *HT = (HuffmanTree) malloc((m + 1) * sizeof(HTNode)); /* 0号单元未用 */
    for (p = *HT + 1, i = 1; i <= n; ++i, ++p, ++w) {
        (*p).weight = *w;
        (*p).parent = 0;
        (*p).lchild = 0;
        (*p).rchild = 0;
    }
    for (; i <= m; ++i, ++p)
        (*p).parent = 0;
    for (i = n + 1; i <= m; ++i) /* 建赫夫曼树 */
    { /* 在HT[1~i-1]中选择parent为0且weight最小的两个结点,其序号分别为s1和s2 */
        select(*HT, i - 1, &s1, &s2);
        (*HT)[s1].parent = (*HT)[s2].parent = i;
        (*HT)[i].lchild = s1;
        (*HT)[i].rchild = s2;
        (*HT)[i].weight = (*HT)[s1].weight + (*HT)[s2].weight;
    }
    /* 从叶子到根逆向求每个字符的赫夫曼编码 */
    *HC = (HuffmanCode) malloc((n + 1) * sizeof(char *));
    /* 分配n个字符编码的头指针向量([0]不用) */
    cd = (char *) malloc(n * sizeof(char)); /* 分配求编码的工作空间 */
    cd[n - 1] = '\0'; /* 编码结束符 */
    for (i = 1; i <= n; i++) { /* 逐个字符求赫夫曼编码 */
        start = n - 1; /* 编码结束符位置 */
        for (c = i, f = (*HT)[i].parent; f != 0; c = f, f = (*HT)[f].parent)
            /* 从叶子到根逆向求编码 */
            if ((*HT)[f].lchild == c)
                cd[--start] = '0';
            else
                cd[--start] = '1';
        (*HC)[i] = (char *) malloc((n - start) * sizeof(char));
        /* 为第i个字符编码分配空间 */
        strcpy((*HC)[i], &cd[start]); /* 从cd复制编码(串)到HC */
    }
    free(cd); /* 释放工作空间 */
}

int main() {
    HuffmanTree HT;
    HuffmanCode HC;
    int *w, n, i;
    printf("请输入权值的个数(>1):");
    scanf("%d", &n);
    w = (int *) malloc(n * sizeof(int));
    printf("请依次输入%d个权值(整型):\n", n);
    for (i = 0; i <= n - 1; i++)
        scanf("%d", w + i);
    HuffmanCoding(&HT, &HC, w, n);
    for (i = 1; i <= n; i++)
        puts(HC[i]);
    return 0;
}

运行结果

1.4.22 哈夫曼编码(2)

#include <limits.h> /* INT_MAX等 */
#include <stdio.h> /* EOF(=^Z或F6),NULL */
#include <stdlib.h>
#include <cstring>

typedef struct {
    unsigned int weight;
    unsigned int parent, lchild, rchild;
} HTNode, *HuffmanTree; /* 动态分配数组存储赫夫曼树 */
typedef char **HuffmanCode; /* 动态分配数组存储赫夫曼编码表 */
int min1(HuffmanTree t, int i) { /* 函数void select()调用 */
    int j, flag;
    unsigned int k = UINT_MAX; /* 取k为不小于可能的值 */
    for (j = 1; j <= i; j++)
        if (t[j].weight < k && t[j].parent == 0)
            k = t[j].weight, flag = j;
    t[flag].parent = 1;
    return flag;
}

void select(HuffmanTree t, int i, int *s1, int *s2) { /* s1为最小的两个值中序号小的那个 */
    int j;
    *s1 = min1(t, i);
    *s2 = min1(t, i);
    if (*s1 > *s2) {
        j = *s1;
        *s1 = *s2;
        *s2 = j;
    }
}

void HuffmanCoding(HuffmanTree *HT, HuffmanCode *HC, int *w, int n) { /* w存放n个字符的权值(均>0),构造赫夫曼树HT,并求出n个字符的赫夫曼编码HC */
    int m, i, s1, s2;
    unsigned c, cdlen;
    HuffmanTree p;
    char *cd;
    if (n <= 1)
        return;
    m = 2 * n - 1;
    *HT = (HuffmanTree) malloc((m + 1) * sizeof(HTNode)); /* 0号单元未用 */
    for (p = *HT + 1, i = 1; i <= n; ++i, ++p, ++w) {
        (*p).weight = *w;
        (*p).parent = 0;
        (*p).lchild = 0;
        (*p).rchild = 0;
    }
    for (; i <= m; ++i, ++p)
        (*p).parent = 0;
    for (i = n + 1; i <= m; ++i) /* 建赫夫曼树 */
    { /* 在HT[1~i-1]中选择parent为0且weight最小的两个结点,其序号分别为s1和s2 */
        select(*HT, i - 1, &s1, &s2);
        (*HT)[s1].parent = (*HT)[s2].parent = i;
        (*HT)[i].lchild = s1;
        (*HT)[i].rchild = s2;
        (*HT)[i].weight = (*HT)[s1].weight + (*HT)[s2].weight;
    }
    /* 以下为无栈非递归遍历赫夫曼树,求赫夫曼编码*/
    *HC = (HuffmanCode) malloc((n + 1) * sizeof(char *));
    /* 分配n个字符编码的头指针向量([0]不用) */
    cd = (char *) malloc(n * sizeof(char)); /* 分配求编码的工作空间 */
    c = m;
    cdlen = 0;
    for (i = 1; i <= m; ++i)
        (*HT)[i].weight = 0; /* 遍历赫夫曼树时用作结点状态标志 */
    while (c) {
        if ((*HT)[c].weight == 0) { /* 向左 */
            (*HT)[c].weight = 1;
            if ((*HT)[c].lchild != 0) {
                c = (*HT)[c].lchild;
                cd[cdlen++] = '0';
            } else if ((*HT)[c].rchild == 0) { /* 登记叶子结点的字符的编码 */
                (*HC)[c] = (char *) malloc((cdlen + 1) * sizeof(char));
                cd[cdlen] = '\0';
                strcpy((*HC)[c], cd); /* 复制编码(串) */
            }
        } else if ((*HT)[c].weight == 1) { /* 向右 */
            (*HT)[c].weight = 2;
            if ((*HT)[c].rchild != 0) {
                c = (*HT)[c].rchild;
                cd[cdlen++] = '1';
            }
        } else { /* HT[c].weight==2,退回 */
            (*HT)[c].weight = 0;
            c = (*HT)[c].parent;
            --cdlen; /* 退到父结点,编码长度减1 */
        }
    }
    free(cd);
}

int main() {
    HuffmanTree HT;
    HuffmanCode HC;
    int *w, n, i;
    printf("请输入权值的个数(>1):");
    scanf("%d", &n);
    w = (int *) malloc(n * sizeof(int));
    printf("请依次输入%d个权值(整型):\n", n);
    for (i = 0; i <= n - 1; i++)
        scanf("%d", w + i);
    HuffmanCoding(&HT, &HC, w, n);
    for (i = 1; i <= n; i++)
        puts(HC[i]);
    return 0;
}

运行结果

posted @ 2019-11-14 11:13  Xu_Lin  阅读(295)  评论(0编辑  收藏  举报