二叉链的基本操作

【目的】

  1. 领会二叉链存储结构;掌握二叉树的各种基本运算和构造二叉树的算法设计。

  2. 领会线索二叉树的构造过程以及构造线索二叉树的算法设计。
【内容及要求】编写程序实现两种方式建立二叉树:

编写一个程序btree.cpp,实现二叉树的基本运算,并在此基础上设计一个程序完成以下功能:(见教材P247,实验题1)
(1)由图7.33所示的二叉树创建对应的二叉链存储结构b,该二叉树的括号表示串为“A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))”。
(2)输出二叉树b。(采用凹入表示法)
(3)输出’H’结点的左、右孩子结点值。
(4)输出二叉树b的高度。
(5)释放二叉树b。
(6)利用先序序列和中序序列重新构造该
二叉树(执行(5)的操作后再执行这一功能),
并以括号表示法输出该二叉树。
(7)对该二叉树进行中序线索化。

 

 

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#define ElemType char
#define BTNode TBTNode
#define MaxSize 100
#define maxsize 100
typedef struct node
{
    ElemType data;
    int ltag, rtag; //线索的标记
    struct node *lchild;
    struct node *rchild;
} BTNode;

BTNode *pre; //全局变量的指针类型

char Pre[100];
char In[100];
int i = 0;

void CreateBTree(BTNode *&b, char *str) //创建二叉树
{
    BTNode *St[MaxSize], *p;
    int top = -1, k, j = 0;
    char ch;
    b = NULL;
    ch = str[j];

    while (ch != '\0')
    {
        switch (ch)
        {
        case '(':
            top++;
            St[top] = p;
            k = 1;
            break;
        case ')':
            top--;
            break;
        case ',':
            k = 2;
            break;
        default:
            p = (BTNode *)malloc(sizeof(BTNode));
            p->data = ch;
            p->lchild = p->rchild = NULL;
            if (b == NULL)
                b = p;
            else
            {
                switch (k)
                {
                case 1:
                    St[top]->lchild = p;
                    break;
                case 2:
                    St[top]->rchild = p;
                    break;
                }
            }
        }
        j++;
        ch = str[j];
    }
}

void DestoryBTree(BTNode *&b) //摧毁二叉树
{
    if (b != NULL)
    {
        DestoryBTree(b->lchild);
        DestoryBTree(b->rchild);
        free(b);
    }
}

BTNode *FindNode(BTNode *b, ElemType x) //寻找值为x的结点
{
    BTNode *p;
    if (b == NULL)
        return NULL;
    else if (b->data == x)
        return b;
    else
    {
        p = FindNode(b->lchild, x);
        if (p != NULL)
            return p;
        else
            return FindNode(b->rchild, x);
    }
}

BTNode *LchildNode(BTNode *p) //返回左孩子结点
{
    return p->lchild;
}

BTNode *RchildNode(BTNode *p) //返回右孩子结点
{
    return p->rchild;
}

int BTHeight(BTNode *b) //输出高度
{
    int lchildh, rchildh;
    if (b == NULL)
        return 0;
    else
    {
        lchildh = BTHeight(b->lchild);
        rchildh = BTHeight(b->rchild);
        return (lchildh > rchildh) ? (lchildh + 1) : (rchildh + 1);
    }
}

void DispBTree(BTNode *b) //输出二叉树
{
    if (b != NULL)
    {
        printf("%c", b->data);
        if (b->lchild != NULL || b->rchild != NULL)
        {
            printf("(");
            DispBTree(b->lchild);
            if (b->rchild != NULL)
                printf(",");
            DispBTree(b->rchild);
            printf(")");
        }
    }
}

void PreOrder(BTNode *b)
//先序遍历的递归形式
{
    if (b != NULL)
    {
        printf("%c ", b->data);
        Pre[i] = b->data;
        i++;
        PreOrder(b->lchild);
        PreOrder(b->rchild);
    }
}
void InOrder(BTNode *b)
//中序遍历的递归算法
{
    if (b != NULL)
    {
        InOrder(b->lchild);
        In[i] = b->data;
        i++;
        printf("%c ", b->data);
        InOrder(b->rchild);
    }
}

BTNode *CreateBTree1(char *pre, char *in, int n)
//根据前序和中序推出二叉树序列
{
    BTNode *b;
    char *p;
    int k;
    if (n <= 0)
        return NULL;
    b = (BTNode *)malloc(sizeof(BTNode));
    b->data = *pre;

    for (p = in; p < in + n; p++)
        if (*p == *pre)
            break;

    k = p - in;
    b->lchild = CreateBTree1(pre + 1, in, k);
    b->rchild = CreateBTree1(pre + k + 1, p + 1, n - k - 1);
    return b;
}

void Thread(TBTNode *&p) //生成二叉树的线索
{
    if (p != NULL)
    {
        Thread(p->lchild);
        if (p->lchild == NULL) //节点左孩子为空时就直接指向前驱的节点线索
        {
            p->lchild = pre;
            p->ltag = 1;
        }
        else
            p->ltag = 0;

        if (pre->rchild == NULL) //右孩子为空时则指向后继的结点线索位置
        {
            pre->rchild = p;
            pre->rtag = 1;
        }
        else
            pre->rtag = 0;

        pre = p;
        Thread(p->rchild);
    }
}

TBTNode *CreateThread(TBTNode *b) //把二叉链转换成线索的形式
{
    TBTNode *root;
    root = (BTNode *)malloc(sizeof(BTNode));
    root->ltag = 0;
    root->rtag = 1;
    root->rchild = b;

    if (b == NULL)
        root->lchild = root; //原二叉链为空,则指针指回自己root
    else
    {
        root->lchild = b;
        pre = root;
        Thread(b);
        pre->rchild = root;
        pre->rtag = 1;
        root->rchild = pre;
    }
    return root;
}

void ThInOrder(TBTNode *tb)
{
    TBTNode *p = tb->lchild;

    while (p != tb)
    {
        while (p->ltag == 0)
            p = p->lchild;                      //找到中序的第一个节点
        printf("%c ", p->data);                 //如果无左孩子说明是已经到达了树梢的叶子节点,直接输出
        while (p->rtag == 1 && p->rchild != tb) //输出在中序中的下一个节点值
        {
            p = p->rchild;
            printf("%c ", p->data);
        }
        p = p->rchild; //回溯到p的前一个节点或者是直接找下一个的右孩子节点
    }
}

void PreOrder2(BTNode *b, int n, int k)
//凹入法输出二叉链
{
    if (b != NULL)
    {

        for (int j = 0; j < k; j++)
            printf(" ");
        printf("%c ", b->data);
        for (int j = 0; j < n; j++)
            printf("-");
        printf("\n");
        PreOrder2(b->lchild, n - 1, k + 1);
        PreOrder2(b->rchild, n - 1, k + 1);
    }
}

int main()
{
    char a[] = "A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))";
    int n = 14;
    BTNode *t, *b;
    CreateBTree(t, a);
    b = FindNode(t, 'H');
    printf("括号法输出二叉树:\n");
    DispBTree(t);
    putchar(10);
    printf("凹入表示法输出二叉树:\n");
    PreOrder2(t, 14, 1);
    putchar(10);
    printf("该结点的左孩子是 %c , 该孩子的右孩子是 %c \n", b->lchild->data, b->rchild->data);

    printf("该二叉树的高度是 %d .\n", BTHeight(t));

    printf("先序遍历的结果:");
    PreOrder(t);
    i = 0;
    printf("\n中序遍历的结果:");
    InOrder(t);

    DestoryBTree(t);
    printf("\n成功销毁二叉树\n");
    printf("\n由先序序列和中序序列生成二叉树:");
    b = CreateBTree1(Pre, In, n);
    putchar(10);
    DispBTree(b);
    putchar(10);

    printf("二叉树的线索化\n");
    TBTNode *g;
    g = CreateThread(b);
    printf("成功创建线索化的二叉树\n");
    printf("中序线索化遍历二叉树:");
    ThInOrder(g);
    putchar(10);

    putchar(10);

    system("pause");
    return 0;
}

喜欢的话,记得支持关注哦。 关注我或者我的csdn博客:https://blog.csdn.net/horizon08/article/details/106254585

posted @ 2020-06-02 16:13    阅读(697)  评论(0编辑  收藏  举报