簡單中序算術表達式直接建立二叉樹測試

/* 簡單中序算術表達式轉爲二叉樹, 至於轉成了二叉樹, 前中後遍歷就隨意了
   1. 將表達式轉爲後綴表達式, 然後轉爲二叉樹, 或者用2步驟.
   2. 理論上來講, 一箇中綴表達式是不能夠轉換出一個唯一的二叉樹的,
      但是中綴算術表達式因爲有運算符的優先級關係, 建立二叉樹時, 需要所有的操作數
      都在葉子節點上, 所有的操作符都在父(根)節點上, 這個特徵可以生成一個唯一的二叉樹
   3. 原理: 每次找到最後計算的運算符, 然後去遞歸處理, 因爲'*'和'/'的運算符優先級高於
      '+', '-', 這樣我們找運算符是應該優先選擇'+','-',然後再考慮'*', '/'.
      至於括號, 去掉對括號內的內容作同樣的遞歸分析即可, 中序遍歷的時候注意將括號恢復.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct _tBINARY_TREE_
{
    int value;
    _tBINARY_TREE_ *lchild;
    _tBINARY_TREE_ *rchild;
}tBINARY_TREE;


static int find_split(const char *express, int start, int end)
{
    int tag = -1;

    if (express[start] == '(' && express[end] == ')')
    {
        ++start;
        --end;
    }

    int is_in_braket = 0;
    int more_grade = 0;
    for (int i = start; i <= end; i++)
    {
        if (express[i] == '(')
            ++is_in_braket;
        else if (express[i] == ')')
            --is_in_braket;

        if ((express[i] == '+' || express[i] == '-')
            && is_in_braket == 0)
        {
            more_grade = 1;
            tag = i; //無break, 找最後一個符合條件的運算符, 取頂級的+和-
        }
        else if ((express[i] == '*' || express[i] == '/')
                 && more_grade == 0
                 && is_in_braket == 0)
        {
            tag = i; //無break, 找最後一個符合條件的運算符
        }
    }
    return tag;
}

static tBINARY_TREE *do_create_binary_tree(const char *express, int start, int end)
{
    tBINARY_TREE *pTree = NULL;

    if (start == end)
    {
        pTree = new tBINARY_TREE;
        pTree->value = express[start];
        pTree->lchild = NULL;
        pTree->rchild = NULL;
    }
    else
    {   //遞歸調用, 各自創建左右的表達式的對應二叉樹
        int tag = find_split(express, start, end);
        if (tag < 0)
        {
            printf("1.invalid express, exit.\n");
            exit(-1);
        }
        else
        {
            pTree = new tBINARY_TREE;
            pTree->value = express[tag];
        }
        if (express[start] == '(' && express[end] == ')')
        {
            ++start;
            --end;
        }
        pTree->lchild = do_create_binary_tree(express, start, tag-1);
        pTree->rchild = do_create_binary_tree(express, tag+1, end);
    }
    return pTree;
}

static tBINARY_TREE *create_binary_tree(const char *infix_express)
{
    return do_create_binary_tree(infix_express, 0, strlen(infix_express)-1);
}

static int priority_com(int operator1, int operator2)
{
    if (operator1 == '*' || operator1 == '/')
    {
        if (operator2 == '+' || operator2 == '-')
            return 1;
    }
    return 0;
}

//遞歸中序遍歷二叉樹, 需要注意將括號恢復
static void in_order_traverser(tBINARY_TREE *pTree)
{
    int flag_l = 0, flag_r = 0;
    if (pTree != NULL)
    {
        int ret;
        if (pTree->lchild != NULL) //非葉子節點
        {
            ret = priority_com(pTree->value, pTree->lchild->value);
            if (ret < 0)
            {
                printf("2. invalid express, exit.\n");
                exit(-1);
            }
            else if (ret == 1) //當前節點的優先級大於左子樹, 左子樹需要加括號, 防止誤解
            {
                printf("%c", '(');
                flag_l = 1;
            }
        }
        in_order_traverser(pTree->lchild);
        if (flag_l == 1)
        {
            printf("%c", ')');
            flag_l = 0;
        }

        printf("%c", pTree->value);

        if (pTree->rchild != NULL) //非葉子結點
        {
            ret = priority_com(pTree->value, pTree->rchild->value);
            if (ret < 0)
            {
                printf("3. invalid express, exit.");
                exit(-1);
            }
            else if (ret == 1)//當前節點的優先級大於右子樹, 又子樹需要加括號, 防誤解
            {
                printf("%c", '(');
                flag_r = 1;
            }
        }
        in_order_traverser(pTree->rchild);
        if (flag_r == 1)
        {
            printf("%c", ')');
            flag_r = 0;
        }
    }
 }

//遞歸先序遍歷二叉樹
static void pre_order_traverser(tBINARY_TREE *pTree)
{
    if (pTree != NULL)
    {
        printf("%c", pTree->value);
        pre_order_traverser(pTree->lchild);
        pre_order_traverser(pTree->rchild);
    }
 }

//遞歸後序遍歷二叉樹
static void post_order_traverser(tBINARY_TREE *pTree)
{
    if (pTree != NULL)
    {
        post_order_traverser(pTree->lchild);
        post_order_traverser(pTree->rchild);
        printf("%c", pTree->value);
    }
 }

 static void destroy_binary_tree(tBINARY_TREE *pTree)
 {
    if (pTree != NULL)
    {
        destroy_binary_tree(pTree->lchild);
        destroy_binary_tree(pTree->rchild);
        delete pTree; pTree = NULL;
    }
 }


int main(void)
{
    const char express[] = "a+b*c+((d*e)+f)*g";
    //const char express[] = "a*(b-c)";
    //const char express[] = "((a+b)*c+d)*e*f+(g-h)*m";
    tBINARY_TREE *pTree = create_binary_tree(express);
    if (pTree != NULL)
    {
        printf("prefix order:\n");
        pre_order_traverser(pTree);

        printf("\n\ninfix order:\n");
        in_order_traverser(pTree);

        printf("\n\npostfix order:\n");
        post_order_traverser(pTree);
        printf("\n");

        destroy_binary_tree(pTree);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章