二叉树线索化的C语言实现

什么是二叉线索化:
  当用二叉链表作为二叉树的存储结构时,因为每个结点中只有指向其左、右儿子结点的指针,所以从任一结点出发只能直接找到该结点的左、右儿子。在一般情况下靠它无法直接找到该结点在某种遍历序下的前驱和后继结点。如果在每个结点中增加指向其前驱和后继结点的指针,将降低存储空间的效率。
先用一张图来说明怎样对二叉树进行线索化
  这里写图片描述
  root表示二叉树子树的根节点,prev是上一个访问的节点,如果prev右子树为空,就将后继指向root,如果root左子树为空,就将root前驱指向prev。为了充分利用空指针域,可以使用标记来完成线索化,具体代码如下:

//BinTree.h
#pragma once
#include <stddef.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<stdio.h>

typedef enum Flag {
    Child,
    Thread,
}Flag;

typedef char ThreadType;

typedef struct ThreadNode {
    ThreadType data;
    struct ThreadNode* left;
    struct ThreadNode* right;
    Flag lflag;                 //引入两个flag来分别表示左右指针指向的是子树还是线索
    Flag rflag;                 //不直接使用前驱、后继指针可以使用空指针域
}ThreadNode;

ThreadNode* ThreadTreeCreate(ThreadType array[], size_t size, ThreadType invalid);

void PreThreading(ThreadNode* root);//先序线索化

void InThreading(ThreadNode* root);//中序线索化

void PostThreading(ThreadNode* root);  //后序线索化

void PreOrderbyThreading(ThreadNode* root);//先序线索化遍历

void InOrderbyThreading(ThreadNode* root); //中序线索化遍历


void PrintInder(ThreadNode* root);       //中序遍历
//BinTree.c
#include "BinTree.h" 
ThreadNode* CreateNode(ThreadType value)
{
    ThreadNode* newnode = (ThreadNode*)malloc(sizeof(ThreadNode));
    newnode->data = value;
    newnode->left = NULL;
    newnode->right = NULL;
    newnode->lflag = Child;
    newnode->rflag = Child;
    return newnode;
}

ThreadNode* _ThreadTreeCreate(ThreadType array[], size_t size, size_t *index, ThreadType invalid)
{
    if (index == NULL || *index >= size) {
        return NULL;
    }
    if (array[*index] == invalid) {
        return NULL;
    }
    ThreadNode* root = CreateNode(array[*index]);
    ++(*index);
    root->left = _ThreadTreeCreate(array, size, index, invalid);
    ++(*index);
    root->right = _ThreadTreeCreate(array, size, index, invalid);
    return root;
}

//输入的array是二叉树的先序遍历结果
ThreadNode* ThreadTreeCreate(ThreadType array[], size_t size, ThreadType invalid)
{
    size_t index = 0;
    return _ThreadTreeCreate(array, size, &index, invalid);
}

void _PreThreading(ThreadNode* root, ThreadNode** prev)//先序线索化
{
    if (root == NULL || prev == NULL)
    {
        return;
    }
    //处理根节点
    //1.如果当前子树根节点的左子树为空,就把left指针指向前驱
    if (root->left == NULL)
    {
        root->left = *prev;
        root->lflag = Thread;
    }
    //2.如果当前子树根节点的前驱的右子树为空,就把前驱的right指针指向此根节点
    if (*prev != NULL && (*prev)->right == NULL)
    {
        (*prev)->right = root;
        (*prev)->rflag = Thread;
    }
    *prev = root;
    //处理左子树
    if (root->lflag == Child)
    {
        _PreThreading(root->left, prev);
    }
    //处理右子树
    if (root->rflag == Child)
    {
        _PreThreading(root->right, prev);
    }
}

void PreThreading(ThreadNode* root)//封装函数,使用户使用更加方便
{
    ThreadNode *prev = NULL;
    _PreThreading(root, &prev);
}

void PreOrderbyThreading(ThreadNode* root)//先序线索化遍历
{
    assert(root);
    ThreadNode *pcur = root;
    while (pcur != NULL)
    {
        while (pcur->lflag == Child)
        {
            //找到最左边的节点
            printf("%c ", pcur->data);
            pcur = pcur->left;
        }
        //打印最左边的节点
        printf("%c ", pcur->data);
        //如果pcur->right是线索或者有右孩子,都向右走
        pcur = pcur->right;
    }
}

void _InThreading(ThreadNode* root, ThreadNode** prev)//中序线索化(只有处理根节点的位置与前序不同)
{
    if (root == NULL || prev == NULL)
    {
        return;
    }
    if (root->lflag == Child)
    {
        _InThreading(root->left, prev);
    }

    if (root->left == NULL)
    {
        root->left = *prev;
        root->lflag = Thread;
    }

    if (*prev != NULL && (*prev)->right == NULL)
    {
        (*prev)->right = root;
        (*prev)->rflag = Thread;
    }
    *prev = root;
    if (root->rflag== Child)
    {
        _InThreading(root->right, prev);
    }
}

void InThreading(ThreadNode* root)//中序线索化
{
    assert(root);
    ThreadNode *prev = NULL;
    _InThreading(root, &prev);
}

void InOrderbyThreading(ThreadNode* root) //中序线索化遍历
{
    assert(root);
    ThreadNode *pcur = root;
    while (pcur != NULL)
    {
        while (pcur != NULL && pcur->lflag == Child)
        {
            //走到最左边节点
            pcur = pcur->left;
        }

        while (pcur != NULL)
        {
            printf("%c ", pcur->data);//访问最左边节点
            if (pcur->rflag == Thread)
            { 
                //如果右孩子是线索,向右走
                pcur = pcur->right;
            }
            else
            {
                //进入循环
                pcur = pcur->right;
                while (pcur != NULL && pcur->lflag == Child)
                {
                    pcur = pcur->left;
                }
            }
        }

    }
}

void PrintInder(ThreadNode* root)       //中序遍历
{
    if (root == NULL)
        return;
    ThreadNode *pcur = root;
    if (NULL != pcur)
    {
        PrintInder(pcur->left);
        printf("%c ", pcur->data);
        PrintInder(pcur->right);
    }
}

void _PostThreading(ThreadNode* root, ThreadNode** prev)
{
    if (NULL == root || NULL == prev)
        return;
    if (root->lflag == Child)
    {
        _PostThreading(root->left, prev);
    }

    if (root->rflag == Child)
    {
        _PostThreading(root->right, prev);
    }

    if (root->left == NULL)
    {
        root->left = *prev;
        root->lflag = Thread;
    }
    if (NULL != *prev || (*prev)->right == NULL)
    {
        (*prev)->right = root;
        (*prev)->rflag = Thread;
    }
}

void PostThreading(ThreadNode* root)  //后序线索化
{
    ThreadNode* prev = NULL;
    _PostThreading(root, &prev);
}
///////////////////////////////////////////////////////////////////////////
////测试代码
//////////////////////////////////////////////////////////////////////////
#if 1
#include <stdio.h>
#define TEST_HEADER printf("\n=================%s================\n", __FUNCTION__)

void TestPreOrderbyThread()
{
    TEST_HEADER;
    ThreadType array[] = "ABD##EG###C#F##";
    ThreadNode* root = ThreadTreeCreate(array, strlen(array), '#');
    PreThreading(root);
    PreOrderbyThreading(root);  
}

void TestInOrderbyThread()
{
    TEST_HEADER;
    ThreadType array[] = "ABD##EG###C#F##";
    ThreadNode* root = ThreadTreeCreate(array, strlen(array), '#');
    InThreading(root);
    InOrderbyThreading(root);
}

int main()
{
    TestInOrderbyThread();
    system("pause");
    return 0;
}

#endif
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值