运算符号位于两个运算数中间。eg: abc*+de/-。数组
处理后缀表达式的思想:记住数字,等到扫描到运算符号后进行计算。所以须要一种数据结构,能顺序存储运算数而且倒序输出——引入堆栈(后进先出LIFO)数据结构
栈的顺序存储结构一般由一个一维数组和一个记录栈顶元素位置的变量组成。指针
typedef int Position; struct SNode { ElementType *Data; /* 存储元素的数组 */ Position Top; /* 栈顶指针 */ int MaxSize; /* 堆栈最大容量 */ }; typedef struct SNode *Stack; Stack CreateStack( int MaxSize ) { Stack S = (Stack)malloc(sizeof(struct SNode)); S->Data = (ElementType *)malloc(MaxSize * sizeof(ElementType)); S->Top = -1; S->MaxSize = MaxSize; return S; }
bool IsFull( Stack S ) { return (S->Top == S->MaxSize-1); } bool Push( Stack S, ElementType X ) { if ( IsFull(S) ) { printf("堆栈满"); return false; } else { S->Data[++(S->Top)] = X; return true; } }
bool IsEmpty( Stack S ) { return (S->Top == -1); } ElementType Pop( Stack S ) { if ( IsEmpty(S) ) { printf("堆栈空"); return ERROR; /* ERROR是ElementType的特殊值,标志错误 */ } else return ( S->Data[(S->Top)--] ); }
栈的链式存储结构实际上就是一个单链表,叫作连栈。插入和删除操做只能在链栈的栈顶进行。栈顶指针top应该在链表的头上。code
typedef struct SNode *PtrToSNode; struct SNode { ElementType Data; PtrToSNode Next; }; typedef PtrToSNode Stack;
Stack CreateStack( ) { /* 构建一个堆栈的头结点,返回该结点指针,头结点不放东西哦 */ Stack S; S = (Stack)malloc(sizeof(struct SNode)); S->Next = NULL; return S; } bool IsEmpty ( Stack S ) { /* 判断堆栈S是否为空,如果返回true;不然返回false */ return ( S->Next == NULL ); }
bool Push( Stack S, ElementType X ) { /* 将元素X压入堆栈S */ PtrToSNode TmpCell; TmpCell = (PtrToSNode)malloc(sizeof(struct SNode)); TmpCell->Data = X; TmpCell->Next = S->Next; S->Next = TmpCell; return true; }
ElementType Pop( Stack S ) { /* 删除并返回堆栈S的栈顶元素 */ PtrToSNode FirstCell; ElementType TopElem; if( IsEmpty(S) ) { printf("堆栈空"); return ERROR; } else { FirstCell = S->Next; TopElem = FirstCell->Data; S->Next = FirstCell->Next; free(FirstCell); return TopElem; } }
队列的顺序存储结构一般由一个一维数组和一个记录队列头元素位置的变量front以及一个记录队列元素位置的变量rear组成。队列
typedef int Position; struct QNode { ElementType *Data; /* 存储元素的数组 */ Position Front, Rear; /* 队列的头、尾指针 */ int MaxSize; /* 队列最大容量 */ }; typedef struct QNode *Queue; Queue CreateQueue( int MaxSize ) { Queue Q = (Queue)malloc(sizeof(struct QNode)); Q->Data = (ElementType *)malloc(MaxSize * sizeof(ElementType)); Q->Front = Q->Rear = 0; Q->MaxSize = MaxSize; return Q; }
为了避免浪费空间,引入顺环队列:it
注意:为了判断这种队列的空满,要么引入size记录元素个数,要么只放n-1个空间。io
bool IsFull( Queue Q ) { return ((Q->Rear+1)%Q->MaxSize == Q->Front); } bool AddQ( Queue Q, ElementType X ) { if ( IsFull(Q) ) { printf("队列满"); return false; } else { Q->Rear = (Q->Rear+1)%Q->MaxSize; Q->Data[Q->Rear] = X; return true; } }
bool IsEmpty( Queue Q ) { return (Q->Front == Q->Rear); } ElementType DeleteQ( Queue Q ) { if ( IsEmpty(Q) ) { printf("队列空"); return ERROR; } else { Q->Front =(Q->Front+1)%Q->MaxSize; return Q->Data[Q->Front]; } }
单向链表头部作插入删除操做均可以,尾部不能作删除操做。所以只能头部作插入尾部作删除。入门
typedef struct Node *PtrToNode; struct Node { /* 队列中的结点 */ ElementType Data; PtrToNode Next; }; typedef PtrToNode Position; struct QNode { Position Front, Rear; /* 队列的头、尾指针 */ int MaxSize; /* 队列最大容量 */ }; typedef struct QNode *Queue;
bool IsEmpty( Queue Q ) { return ( Q->Front == NULL); } ElementType DeleteQ( Queue Q ) { Position FrontCell; ElementType FrontElem; if ( IsEmpty(Q) ) { printf("队列空"); return ERROR; } else { FrontCell = Q->Front; if ( Q->Front == Q->Rear ) /* 若队列只有一个元素 */ Q->Front = Q->Rear = NULL; /* 删除后队列置为空 */ else Q->Front = Q->Front->Next; FrontElem = FrontCell->Data; free( FrontCell ); /* 释放被删除结点空间 */ return FrontElem; } }