/* 後綴表達式建立二叉樹並遍歷測試
* 原理:
掃描後綴表達式,遇到操作數時即建立單二叉樹節點, 左右指針都爲空,放入棧中, 遇到
操作符時也建立單二叉樹節點, 但是節點的左右指針需要取棧頂元素,即此時依次從棧頂
出棧的元素分別作爲當前掃描節點的右,左子樹(注意順序), 之後也將該節點進棧, 循環
該步驟直到後綴表達式結尾, 此時棧頂元素即爲建立好的二叉樹的根節點.
可以用二叉樹的逆波蘭式與原始表達式對比驗證, 同時可以打印中序遍歷, 得到自然表達式.
後綴表達式測試用例: "ab+cde+**"
*/
#include <stdio.h>
#include <stack>
#include <stdlib.h>
typedef struct _tBINARY_TREE_
{
int value;
_tBINARY_TREE_ *lchild;
_tBINARY_TREE_ *rchild;
}tBINARY_TREE;
static bool is_operator(const char c);
static int priority_com(int operator1, int operator2);
static tBINARY_TREE *suffix_express_create_binary_tree(const char *suffix_express)
{
std::stack<tBINARY_TREE *> operator_stack;
const char *p = suffix_express;
while (*p != '\0')
{
if (!is_operator(*p))
{
tBINARY_TREE *ptree = new tBINARY_TREE;
ptree->value = *p;
ptree->lchild = NULL;
ptree->rchild = NULL;
operator_stack.push(ptree);
}
else
{
tBINARY_TREE *ptree = new tBINARY_TREE;
ptree->value = *p;
ptree->lchild = NULL;
ptree->rchild = NULL;
if (!operator_stack.empty())
{
ptree->rchild = operator_stack.top();
operator_stack.pop();
}
if (!operator_stack.empty())
{
ptree->lchild = operator_stack.top();
operator_stack.pop();
}
if (ptree->lchild == NULL || ptree->rchild == NULL)
{
printf("express is invalid, exit.\n");
exit(-2);
}
operator_stack.push(ptree);
}
++p;
}
if (operator_stack.empty())
{
printf("internal error.\n");
exit(-1);
}
tBINARY_TREE *pRoot = operator_stack.top();
operator_stack.pop();
return pRoot;
}
//遞歸先序遍歷
void pre_order_reserver_tree(tBINARY_TREE *pTree)
{
if (pTree != NULL)
{
printf("%c", pTree->value);
pre_order_reserver_tree(pTree->lchild);
pre_order_reserver_tree(pTree->rchild);
}
return;
}
//遞歸中序遍歷
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;
}
}
}
//遞歸後序遍歷
void post_order_reserver_tree(tBINARY_TREE *pTree)
{
if (pTree != NULL)
{
post_order_reserver_tree(pTree->lchild);
post_order_reserver_tree(pTree->rchild);
printf("%c", pTree->value);
}
return;
}
void destroy_binary_tree(tBINARY_TREE *pTree)
{
if (pTree != NULL)
{
destroy_binary_tree(pTree->lchild);
destroy_binary_tree(pTree->rchild);
delete pTree; pTree = NULL;
}
return;
}
static bool is_operator(const char c)
{
if (c == '+'
|| c == '-'
|| c == '*'
|| c == '/'
|| c == '('
|| c == ')')
return true;
return false;
}
static int priority_com(int operator1, int operator2)
{
if (operator1 == '*' || operator1 == '/')
{
if (operator2 == '+' || operator2 == '-')
return 1;
}
return 0;
}
int main(void)
{
const char suffix_express[] = "ab+cde+**";
tBINARY_TREE *pTree = suffix_express_create_binary_tree(suffix_express);
printf("old suffix express:%s\n", suffix_express);
printf("new suffix express:");
post_order_reserver_tree(pTree);
printf("\nnew prefix express:");
pre_order_reserver_tree(pTree);
printf("\nnew infix express:");
in_order_traverser(pTree);
printf("\n");
destroy_binary_tree(pTree);
return 0;
}
測試結果:
old suffix express:ab+cde+**
new suffix express:ab+cde+**
new prefix express:*+ab*c+de
new infix express:(a+b)*c*(d+e)