Data Structure 6 - Threaded Binary Tree

1. Create a binary tree with the filling method

Enter a string of node information ---"conversion ------"binary tree

Preorder traversal: ABD##E##CF#G### -----" apply in reverse

(1) Input a filled binary tree ---- "Preorder traversal   ABD##E##CF#G###

(2) Conversion char ch ;
                  ch == '#' ; ------> Empty binary tree
                  ch != '#' ; -------> Create a new node --- "left subtree right Subtree
is recursive thought again

code: 

#include <stdio.h>
#include <stdlib.h>
 
// 二叉树节点
struct BinTree_node
{
        unsigned char elem;     // 二叉树内容
        struct BinTree_node *ltree, *rtree;    //左右树
}; 
 
// 声明

void pre_order(struct BinTree_node *tree);
void in_order(struct BinTree_node *tree);
void pos_order(struct BinTree_node *tree);

struct BinTree_node *create_bintree(void);   //ask_method创建二叉树
struct BinTree_node *Create_BinTree(void);   //fill_blank_method创建二叉树
// 主函数
int main(void)
{      
	struct BinTree_node *mytree;
        printf("please input a preorder binary tree(with fill blank #):\n");
	mytree = Create_BinTree();
        pre_order(mytree);
        printf("\n");
        in_order(mytree);
        printf("\n");
        pos_order(mytree);
        printf("\n");
	return 0;
}
 
//ask_method创建二叉树
struct BinTree_node *create_bintree(void)  
{
	unsigned char flag;
	struct BinTree_node *tree;
 
        tree = (struct BinTree_node *)malloc(sizeof(struct BinTree_node));
	printf("please input the mode elem:\n");
	while((tree->elem = getchar()) == '\n');
    //左子树
	printf("do you want to insert l_tree for %c, (Y/N)?\n", tree->elem);
	while((flag = getchar()) == '\n');     //避免连续getchar(),该方法避免回车
        if(flag == 'Y')
		tree->ltree = create_bintree();  //递归创建左子树
        else
		tree->ltree = NULL;
    //右子树
	printf("do you want to insert r_tree for %c, (Y/N)?\n", tree->elem);
        while((flag = getchar()) == '\n');     //避免连续getc har(),该方法避免回车
        if(flag == 'Y')
               tree->rtree = create_bintree();  //递归创建左子树
        else
               tree->rtree = NULL;
        return tree;
}

//fill_blank_method创建二叉树
struct BinTree_node *Create_BinTree(void) 
{
       char ch;
       struct BinTree_node *tree;  
       scanf("%c", &ch);    //获取ch
       if(ch == '#')
            tree = NULL;
       else 
       {
            tree = (struct BinTree_node *)malloc(sizeof(struct BinTree_node));
            tree->elem = ch;
            tree->ltree = Create_BinTree();
            tree->rtree = Create_BinTree();
       }
       return tree;
       
} 



// 先序遍历函数  ABDECFG
 
void pre_order(struct BinTree_node *tree)
{
     if(tree)
     {
          printf("%c", tree->elem);
          pre_order(tree->ltree);
          pre_order(tree->rtree);
     }
}
 
// 中序遍历函数   DBEAFGC
 
void in_order(struct BinTree_node *tree)
{
     if(tree)
     {
          in_order(tree->ltree);
          printf("%c", tree->elem);
          in_order(tree->rtree);
     }
}
 
// 后序遍历函数  DEBGFCA
void pos_order(struct BinTree_node *tree)
{
     if(tree)
     {
          pos_order(tree->ltree);
          pos_order(tree->rtree);
          printf("%c", tree->elem);
     }
}

 result:

 2. Clue binary tree

Traditional binary tree: non-linear structure (linked by pointers)

Binary tree ------ "threading (in order to quickly find the predecessor and successor) ----" in-order threading is the best

         The essence of threading is to change the null pointer in the binary linked list to a thread pointing to the predecessor or successor. Since the predecessor and successor information can only be obtained when traversing the binary tree, the threading process is the process of modifying the null pointer during the traversal process

Inorder threading a binary tree

In-order traversal --- "DBEAFGC, if you use stack or queue to consume memory, it will be more troublesome
n nodes ---" 2n pointer fields, but many of them are not used, as shown in the following figure 14 pointer fields, but only 6 are used , so we can use it. If there is no left subtree, it points to the predecessor point, and if there is no right subtree, it points to the successor point.

 Create clue binary tree + traverse clue binary tree + search clue binary tree predecessor and successor

#include <stdio.h>
#include <stdlib.h>
 

// 二叉树节点
struct BinTree_node
{
        unsigned char elem;                    // 二叉树内容
        struct BinTree_node *ltree, *rtree;    // 左右树
        int lflag, rflag;                      // 标志位
}; 
 

struct BinTree_node *pre = NULL;
// 声明

void pre_order(struct BinTree_node *tree);
void in_order(struct BinTree_node *tree);
void pos_order(struct BinTree_node *tree);

struct BinTree_node *create_bintree(void);          // ask_method创建二叉树
struct BinTree_node *Create_BinTree(void);          // fill_blank_method创建二叉树
void In_order_Thread(struct BinTree_node *tree);    // 中序线索化二叉树
void Create_Inorder_Thread(struct BinTree_node *T); // 线索化
void Traverse_Inorder_Thred(struct BinTree_node *tree); // 遍历线索化二叉树
struct BinTree_node *Search_Inorder_Thread(struct BinTree_node *tree, char ch);// 搜索二叉树点(和遍历的思想一样)
struct BinTree_node *Prenode_Inorder_Thread(const struct BinTree_node *node); // 找前驱
struct BinTree_node *Succnode_Inorder_Thread(struct BinTree_node *node);      // 找后继

// 主函数
int main(void)
{      
	struct BinTree_node *mytree;
        char ch;
        struct BinTree_node *node, *precursor, *succeed;

        printf("please input a preorder binary tree(with fill blank #):\n");
	mytree = Create_BinTree();       // 创建二叉树
        pre_order(mytree);               // 前序遍历
        printf("\n");
           
        Create_Inorder_Thread(mytree);   // 线索化
         
        printf("traverse inorder_thred tree:");  // 遍历线索化二叉树
        Traverse_Inorder_Thred(mytree);
        printf("\n");
        // 找到该结点
        printf("please enter the node that you want to find it's pre & succ node:\n");
        while((ch = getchar()) == '\n');                               // 避免捕获回车
        node = Search_Inorder_Thread(mytree, ch);
        // printf("node = %c\n", node->elem); 调试是否能找到A
        // 找到该节点的前驱点
        precursor =  Prenode_Inorder_Thread(node);
        if(precursor == NULL)  // 无前驱点
                  printf("node %c has no precursor\n", node->elem);
        else
                  printf("precursor node = %c\n", precursor->elem);

        // 找到该节点的后继点
        succeed =  Succnode_Inorder_Thread(node);
        if(succeed == NULL)  // 无后继点
                  printf("node %c has no succeed node\n", node->elem);
        else
                  printf("succeed node = %c\n", succeed->elem);
	return 0;
}
 
// ask_method创建二叉树
struct BinTree_node *create_bintree(void)  
{
	unsigned char flag;
	struct BinTree_node *tree;
 
        tree = (struct BinTree_node *)malloc(sizeof(struct BinTree_node));
	printf("please input the mode elem:\n");
	while((tree->elem = getchar()) == '\n');
        // 左子树
	printf("do you want to insert l_tree for %c, (Y/N)?\n", tree->elem);
	while((flag = getchar()) == '\n');       // 避免连续getchar(),该方法避免回车
        if(flag == 'Y')
		tree->ltree = create_bintree();  // 递归创建左子树
        else
		tree->ltree = NULL;
        // 右子树
	printf("do you want to insert r_tree for %c, (Y/N)?\n", tree->elem);
        while((flag = getchar()) == '\n');      // 避免连续getc har(),该方法避免回车
        if(flag == 'Y')
               tree->rtree = create_bintree();  // 递归创建左子树
        else
               tree->rtree = NULL;
        return tree;
}

// fill_blank_method创建二叉树
struct BinTree_node *Create_BinTree(void) 
{
       char ch;
       struct BinTree_node *tree;  
       scanf("%c", &ch);    // 获取ch
       if(ch == '#')
            tree = NULL;
       else 
       {
            tree = (struct BinTree_node *)malloc(sizeof(struct BinTree_node));
            tree->elem = ch;
            tree->ltree = Create_BinTree();
            tree->rtree = Create_BinTree();
       }
       return tree;
       
} 


// 先序遍历函数  ABDECFG
 
void pre_order(struct BinTree_node *tree)
{
     if(tree)
     {
          printf("%c", tree->elem);
          pre_order(tree->ltree);
          pre_order(tree->rtree);
     }
}
 
// 中序遍历函数   DBEAFGC
 
void in_order(struct BinTree_node *tree)
{
     if(tree)
     {
          in_order(tree->ltree);
          printf("%c", tree->elem);
          in_order(tree->rtree);
     }
}
 
// 后序遍历函数  DEBGFCA
void pos_order(struct BinTree_node *tree)
{
     if(tree)
     {
          pos_order(tree->ltree);
          pos_order(tree->rtree);
          printf("%c", tree->elem);
     }
}

// 中序线索化
void In_order_Thread(struct BinTree_node *tree)
{
     if(tree)
     {
           //1.对左子树进行中序线索化
           In_order_Thread(tree->ltree);
           //2.处理当前节点
           if(!tree->ltree)
           {
               tree->lflag = 1;
               tree->ltree = pre;     // 让当前节点左指针指针域指向前驱点
           }
           else
               tree->lflag = 0;
                      
           if(pre)
           {
               if(!pre->rtree)
               {
                    pre->rflag = 1;
                    pre->rtree = tree;     // 让前驱点的右子树指向现在的点
               }
               else
                    pre->rflag = 0;
           }
           pre = tree;                // 更新前驱点 
           //3.对右子树进行中序线索化
           In_order_Thread(tree->rtree);
     }
}


// 线索化打包
void Create_Inorder_Thread(struct BinTree_node *T)
{ 
        if(T)
        {
             In_order_Thread(T);
             pre->rtree = NULL;
             pre->rflag = 1;
        }
}

// 遍历线索化二叉树(不能用原来的遍历)
void Traverse_Inorder_Thred(struct BinTree_node *tree)
{
      
       while(tree)
       {
               // 使用循环找到最左下角的节点
               while(tree->lflag == 0)
               {
                      tree = tree->ltree;
               }
               printf("%c ", tree->elem);  
               // 该节点如果存在后继节点并且确实存在内容   tree-> B
               while((tree->rflag == 1) && (tree->rtree))  
               {
                      tree = tree->rtree;
                      printf("%c ", tree->elem);
               }
               // 如果该结点存在rtree ,后继节点应该是该结点右子树最左下的节点,再次循环    
              tree = tree->rtree;  
       }
}

// 搜索二叉树点(和遍历的思想一样)
struct BinTree_node *Search_Inorder_Thread(struct BinTree_node *tree, char ch)
{ 
      while(tree)
      {
               // 使用循环找到最左下角的节点
               while(tree->lflag == 0)              
                      tree = tree->ltree;          
               if(tree->elem == ch)
                      return tree; 
               // 该节点如果存在后继节点并且确实存在内容   tree-> B
               while((tree->rflag == 1) && (tree->rtree))  
               {
                      tree = tree->rtree;
                      if(tree->elem == ch)
                            return tree; 
               }
               // 如果该结点存在rtree ,后继节点应该是该结点右子树最左下的节点,再次循环    
              tree = tree->rtree;  
      }    
}

// 找前驱点
struct BinTree_node *Prenode_Inorder_Thread(const struct BinTree_node *node)
{
       struct BinTree_node *nd;
       // 无左子树,有前驱点
       if(node->lflag == 1)   
             return node->ltree;
       // 有左子树,找左子树最右下的点
       else               
       {
             nd = node->ltree;
             while(nd->rflag == 0)
                  nd = nd->rtree; 
             return nd;          // 找到最右下的节点
       }
              
}

// 找后继点
struct BinTree_node *Succnode_Inorder_Thread(struct BinTree_node *node)
{
       struct BinTree_node *nd;
       // 无右子树,有后继点
       if(node->rflag == 1)   
             return node->rtree;
       // 有右子树,找右子树最左下的点
       else               
       {
             nd = node->rtree;
             while(nd->lflag == 0)
                  nd = nd->ltree; 
             return nd;          // 找到最左下的节点
       }
}

3. Restore traversal of binary tree

Restore a binary tree based on known traversals of the binary tree

revert_bintree.c 

#include <stdio.h>
#include <stdlib.h>
 
// 二叉树节点
struct BinTree_node
{
        unsigned char elem;                    // 二叉树内容
        struct BinTree_node *ltree, *rtree;    // 左右树
}; 
 
// 声明

void pre_order(struct BinTree_node *tree);
void in_order(struct BinTree_node *tree);
void pos_order(struct BinTree_node *tree);

struct BinTree_node *create_bintree(void);   //ask_method创建二叉树
struct BinTree_node *Create_BinTree(void);   //fill_blank_method创建二叉树
struct BinTree_node *pre_in_CreatBinTree(char *pre, char *in, int len); // 先序+中序还原二叉树 
struct BinTree_node *in_post_CreatBinTree(char *in, char *post, int len);
// 主函数
int main(void)
{      
	struct BinTree_node *mytree;

        char pre[100], in[100], post[100];
        int choose, n;
        printf("1. revert binarytree through pre & in order:\n");
        printf("2. revert binarytree through post & in order:\n");
        scanf("%d", &choose);
        switch(choose)
        {
            case 1:
                   printf("please enter the number of nodes:");
                   scanf("%d", &n);
                   getchar();  //消耗掉回车
                   printf("please enter the pre order:");
                   gets(pre);
                   printf("please enter the in order:");
                   gets(in);
                   mytree = pre_in_CreatBinTree(pre, in, n);
                   printf("after revert, show the bintree in post order:");
                   pos_order(mytree);
                   printf("\n");
                   break;
            case 2:
                   printf("please enter the number of nodes:");
                   scanf("%d", &n);
                   getchar();  //消耗掉回车
                   printf("please enter the in order:");
                   gets(in);
                   printf("please enter the pos order:");
                   gets(post);
                   mytree = in_post_CreatBinTree(in, post, n);
                   printf("after revert, show the bintree in pre order:");
                   pre_order(mytree);
                   printf("\n");
                   break;
        }
        printf("\n");
	return 0;
}
 
//ask_method创建二叉树
struct BinTree_node *create_bintree(void)  
{
	unsigned char flag;
	struct BinTree_node *tree;
 
        tree = (struct BinTree_node *)malloc(sizeof(struct BinTree_node));
	printf("please input the mode elem:\n");
	while((tree->elem = getchar()) == '\n');
    //左子树
	printf("do you want to insert l_tree for %c, (Y/N)?\n", tree->elem);
	while((flag = getchar()) == '\n');     //避免连续getchar(),该方法避免回车
        if(flag == 'Y')
		tree->ltree = create_bintree();  //递归创建左子树
        else
		tree->ltree = NULL;
    //右子树
	printf("do you want to insert r_tree for %c, (Y/N)?\n", tree->elem);
        while((flag = getchar()) == '\n');     //避免连续getc har(),该方法避免回车
        if(flag == 'Y')
               tree->rtree = create_bintree();  //递归创建左子树
        else
               tree->rtree = NULL;
        return tree;
}

//fill_blank_method创建二叉树
struct BinTree_node *Create_BinTree(void) 
{
       char ch;
       struct BinTree_node *tree;  
       scanf("%c", &ch);    //获取ch
       if(ch == '#')
            tree = NULL;
       else 
       {
            tree = (struct BinTree_node *)malloc(sizeof(struct BinTree_node));
            tree->elem = ch;
            tree->ltree = Create_BinTree();
            tree->rtree = Create_BinTree();
       }
       return tree;
       
} 



// 先序遍历函数  ABDECFG
 
void pre_order(struct BinTree_node *tree)
{
     if(tree)
     {
          printf("%c", tree->elem);
          pre_order(tree->ltree);
          pre_order(tree->rtree);
     }
}
 
// 中序遍历函数   DBEAFGC
 
void in_order(struct BinTree_node *tree)
{
     if(tree)
     {
          in_order(tree->ltree);
          printf("%c", tree->elem);
          in_order(tree->rtree);
     }
}
 
// 后序遍历函数  DEBGFCA
void pos_order(struct BinTree_node *tree)
{
     if(tree)
     {
          pos_order(tree->ltree);
          pos_order(tree->rtree);
          printf("%c", tree->elem);
     }
}

// 用先序+中序还原二叉树
struct BinTree_node *pre_in_CreatBinTree(char *pre, char *in, int len)
{
      struct BinTree_node *tree;
      if(len == 0)              // 长度为0,结束循环
             return NULL;
      char ch = pre[0];
      int index = 0;
      while(in[index] != ch)
            index++;

      tree = (struct BinTree_node *)malloc(sizeof(struct BinTree_node));
      tree->elem = ch;
      tree->ltree = pre_in_CreatBinTree(pre+1, in, index);  // 左子树
      tree->rtree = pre_in_CreatBinTree(pre+index+1, in+index+1, len-index-1);  // 右子树
      
      return tree;
}

// 用后序+中序还原二叉树
struct BinTree_node *in_post_CreatBinTree(char *in, char *post, int len)
{
      struct BinTree_node *tree;
      if(len == 0)              // 长度为0,结束循环
             return NULL;
      char ch = post[len-1];    // 后序最后一个为根结点
      int index = 0;
      while(in[index] != ch)    // 找到中序根结点
           index++;

      tree = (struct BinTree_node *)malloc(sizeof(struct BinTree_node));
      tree->elem = ch;
      tree->ltree = in_post_CreatBinTree(in, post, index);                     // 左子树
      tree->rtree = in_post_CreatBinTree(in+index+1, post+index, len-index-1);  // 右子树
      
      return tree;
}

result 

Guess you like

Origin blog.csdn.net/qq_44177768/article/details/127575071