const int TOKEN_NUMBER = 1;
const int TOKEN_LPAREN = 3;
const int TOKEN_RPAREN = 4;
static int[] tokenTypes = new int[100];
static string[] tokenTexts = new string[100];
static int tokenCount = 0;
const int NODE_NUMBER = 1;
const int NODE_OPERATOR= 2;
static int[] nodeTypes = new int[100];
static string[] nodeValues = new string[100];
static int[] leftChild = new int[100];
static int[] rightChild = new int[100];
static int nodeCountGlobal = 0;
static int[] stackArray = new int[100];
static int stackTop = -1;
static int[] opStackTypes = new int[100];
static string[] opStackText= new string[100];
static int opStackTop = -1;
public static void Main()
string expression = "3+4*5";
Console.WriteLine("Expression: " + expression);
Console.WriteLine("\nTokens:");
for (int i = 0; i < tokenCount; i++)
Console.WriteLine($" Type={tokenTypes[i]}, Text='{tokenTexts[i]}'");
int[] postfixTypes = new int[100];
string[] postfixTexts = new string[100];
int postfixCount = ConvertToPostfix(postfixTypes, postfixTexts);
Console.WriteLine("\nPostfix tokens:");
for (int i = 0; i < postfixCount; i++)
Console.Write(postfixTexts[i] + " ");
int rootIndex = BuildTreeFromPostfix(postfixTypes, postfixTexts, postfixCount);
Console.WriteLine("\nTree (breadth-first):");
PrintTreeBreadthFirst(rootIndex);
static void Tokenize(string expr)
for (int i = 0; i < expr.Length; i++)
while (i+1 < expr.Length && char.IsDigit(expr[i+1]))
string numberText = expr.Substring(startPos, (i - startPos + 1));
tokenTypes[tokenCount] = TOKEN_NUMBER;
tokenTexts[tokenCount] = numberText;
else if (c == '+' || c == '-' || c == '*' || c == '/')
tokenTypes[tokenCount] = TOKEN_OP;
tokenTexts[tokenCount] = c.ToString();
tokenTypes[tokenCount] = TOKEN_LPAREN;
tokenTexts[tokenCount] = "(";
tokenTypes[tokenCount] = TOKEN_RPAREN;
tokenTexts[tokenCount] = ")";
static int ConvertToPostfix(int[] outTypes, string[] outTexts)
for (int i = 0; i < tokenCount; i++)
int tType = tokenTypes[i];
string tText = tokenTexts[i];
if (tType == TOKEN_NUMBER)
outTypes[outCount] = tType;
outTexts[outCount] = tText;
else if (tType == TOKEN_OP)
while (opStackTop >= 0 && opStackTypes[opStackTop] == TOKEN_OP &&
GetPrecedence(opStackText[opStackTop]) >= GetPrecedence(tText))
outTypes[outCount] = opStackTypes[opStackTop];
outTexts[outCount] = opStackText[opStackTop];
opStackTypes[opStackTop] = tType;
opStackText[opStackTop] = tText;
else if (tType == TOKEN_LPAREN)
opStackTypes[opStackTop] = tType;
opStackText[opStackTop] = tText;
else if (tType == TOKEN_RPAREN)
while (opStackTop >= 0 && opStackTypes[opStackTop] != TOKEN_LPAREN)
outTypes[outCount] = opStackTypes[opStackTop];
outTexts[outCount] = opStackText[opStackTop];
if (opStackTop >= 0 && opStackTypes[opStackTop] == TOKEN_LPAREN)
outTypes[outCount] = opStackTypes[opStackTop];
outTexts[outCount] = opStackText[opStackTop];
static int GetPrecedence(string op)
if (op.Equals("*") || op.Equals("/")) return 2;
if (op.Equals("+") || op.Equals("-")) return 1;
static int BuildTreeFromPostfix(int[] pTypes, string[] pTexts, int pCount)
for (int i = 0; i < pCount; i++)
string tText = pTexts[i];
if (tType == TOKEN_NUMBER)
int nIndex = CreateNode(NODE_NUMBER, tText, -1, -1);
stackArray[stackTop] = nIndex;
else if (tType == TOKEN_OP)
int rightIndex = stackArray[stackTop];
int leftIndex = stackArray[stackTop];
int nIndex = CreateNode(NODE_OPERATOR, tText, leftIndex, rightIndex);
stackArray[stackTop] = nIndex;
return stackArray[stackTop];
static int CreateNode(int t, string val, int left, int right)
nodeTypes[nodeCountGlobal] = t;
nodeValues[nodeCountGlobal] = val;
leftChild[nodeCountGlobal] = left;
rightChild[nodeCountGlobal] = right;
return nodeCountGlobal - 1;
static void PrintTreeBreadthFirst(int rootIndex)
if (rootIndex < 0) return;
int[] queue = new int[100];
queue[queueEnd] = rootIndex;
while (queueStart < queueEnd)
int current = queue[queueStart];
$"NodeIndex={current}, " +
$"Type={(nodeTypes[current] == NODE_NUMBER ? "NUMBER" : "OPERATOR")}, " +
$"Value='{nodeValues[current]}', " +
$"Left={leftChild[current]}, Right={rightChild[current]}"
if (leftChild[current] != -1)
queue[queueEnd] = leftChild[current];
if (rightChild[current] != -1)
queue[queueEnd] = rightChild[current];