Data Type = {Obejcts}{Operations} An ADT is a data type that is orgnized in such a way that the specification(说明) on the objects and specification of the operations on the objects are separated from the representation of the objects and the implementation on the operations.
即对于数据对象的说明、对操作的说明和数据如何表示、操作如何实现是分割开的,如下图 数据对象是m x n的矩阵,矩阵由m x n个三元组构成,我们只知道这个矩阵是个什么东西,但是如何表示的,比如把三元组按顺序存到一维数组里还是三元组构成一个结构用结构数组存?还是用链表?我们不关心 同理,各种操作是怎么实现的,用什么语言,我们也不关心 ADT仅仅是说明了数据对象是什么,可以对它们进行哪些操作,即specification,而不关心representation & implementation
The stack model must be well encapsulated. That is, no part of your code, except for the stack routines, can attempt to access the Array or TopOfStack variable.
/*摘自project 2*/ // Converts a sequence of infix tokens into postfix. // This uses an algorithm that we have learnt in fds. // // Args: // infix_tokens: The original array of tokens in natural order. // infix_count: The total number of tokens in the infix array. // postfix_tokens: The target array to store converted(postfix) tokens. // postfix_count: Pointer to track the number of tokens in the output array. voidinfix_to_postfix(Token* infix_tokens, int infix_count, Token* postfix_tokens, int* postfix_count) { TokenStack op_stack; op_stack.top = -1; // Initialize the stack as empty. int p_count = 0;
for (int i = 0; i < infix_count; i++) { Token cur = infix_tokens[i]; // Operands (numbers and variables) are written directly to the postfix_tokens. if (cur.type == token_const || cur.type == token_variable) { postfix_tokens[p_count++] = cur; }
// Function names are always pushed onto the stack. elseif(cur.type == token_function) { push_token(&op_stack,cur); }
// If '(' is not in the stack, it has the highest precedence. So just push it in. elseif (cur.str_value[0] == '(') { push_token(&op_stack, cur); }
// Right bracket: pop all ops until the matching '(' is found. elseif (cur.str_value[0] == ')') { while (peek_token(&op_stack).str_value[0] != '(') { postfix_tokens[p_count++] = pop_token(&op_stack); } pop_token(&op_stack); // Don't forget to pop '('
// If the parentheses were part of a function call, pop the function token. // e.g. ln(5+x) -> 5 x + ln if(!is_Tokenstack_empty(&op_stack) && peek_token(&op_stack).type == token_function) { postfix_tokens[p_count++] = pop_token(&op_stack); } }
// Comma: effectively closes the current sub-expression inside a function. Pop all ops until the matching '(' is found, but don't pop '(' // e.g. log(2+y,x) -> 2 y + x log elseif(cur.type == token_operator && cur.str_value[0] == ',') { while (peek_token(&op_stack).str_value[0] != '(') { postfix_tokens[p_count++] = pop_token(&op_stack); } } elseif (cur.type == token_operator) { if(cur.str_value[0] == '^') { // '^' is special. Because it's calculated from right to left, the precedence of the top operator must be higher than the current operator. // e.g. 3^2^5 -> 3 2 5 ^ ^ while (!is_Tokenstack_empty(&op_stack) && peek_token(&op_stack).str_value[0] != '(' && get_priority(peek_token(&op_stack)) > get_priority(cur)) { postfix_tokens[p_count++] = pop_token(&op_stack); } } else { // Comparison of priorities to determine which operator executes(pop) first. // Notice that when '(' is the top element, its precedence is absolutely lower than the current operator. while (!is_Tokenstack_empty(&op_stack) && peek_token(&op_stack).str_value[0] != '(' && get_priority(peek_token(&op_stack)) >= get_priority(cur)) { postfix_tokens[p_count++] = pop_token(&op_stack); } } push_token(&op_stack, cur); } }
// Pop any remaining operators from the stack to the output(postfix_tokens). while (!is_Tokenstack_empty(&op_stack)) { postfix_tokens[p_count++] = pop_token(&op_stack); } *postfix_count = p_count; }