栈(Stack)是限定仅在表尾进行插入或删除操作的线性表。通常称其表尾为栈顶(top),表头端称为栈底( bottom)。按栈的存储方式可以分为顺序栈、链式栈。
一、顺序表栈
1 #include <stdio.h> 2 #include <malloc.h> 3 4 #define OVERFLOW -1 5 #define OK 1 6 #define ERROR 0 7 #define STACK_INIT_SIZE 100 //存储空间初始分配量 8 #define STACKINCREMENT 10//存储空间分配增量 9 10 typedef int SElemType,Status; 11 /* 顺序栈结构体 */ 12 typedef struct { 13 SElemType *base; //栈底指针 14 SElemType *top; //栈顶指针 15 int stacksize; 16 }SqStack; 17 18 /* 构造一个空栈 */ 19 Status InitStack (SqStack &S ){ 20 S.base = (SElemType*) malloc(STACK_INIT_SIZE*sizeof (SElemType)); 21 if (! S.base) exit(OVERFLOW);//存储分配失败 22 S.top =S.base; 23 S.stacksize = STACK_INIT_SIZE; 24 return OK; 25 } 26 27 /* 返回栈顶元素 */ 28 Status GetTop (SqStack S , SElemType &e ) 29 { 30 if(S.top == S.base) return ERROR;//栈空 top == base 31 e = *(S.top-1); //top指向的是栈顶元素的下一个位置 32 return OK; 33 } 34 35 /* 压栈(插入元素) */ 36 Status Push (SqStack &S , SElemType e ) 37 { 38 if(S.top - S.base >= S.stacksize)//栈满 39 { //当前存储空间已满,增加分配 40 S.base = (SElemType *)realloc(S.base, 41 (S.stacksize+STACKINCREMENT)*sizeof (SElemType)); 42 if (!S.base) exit(OVERFLOW);// 存储分配失败 43 S.top = S.base + S.stacksize;//更新栈顶 44 S.stacksize+= STACKINCREMENT; //增加存储容量 45 } 46 *S.top++ = e;//压栈并更新栈顶 47 return OK; 48 } 49 50 /* 出栈(删除栈顶元素) */ 51 Status Pop (SqStack &S , SElemType &e ) 52 { 53 if(S.top == S.base) return ERROR;//栈空 top == base 54 e = *--S.top; //更新栈顶并出栈 55 return OK; 56 } 57 58 /* 测试 */ 59 int main() 60 { 61 SqStack S; 62 SElemType e; 63 InitStack(S);//构造空栈 64 for(int i=0; i<10; ++i) 65 Push(S,i); //压栈 66 while(Pop(S,e)) 67 printf("%d ",e);//出栈 68 return 0; 69 }
1 //浙大数据结构 顺序栈 2 typedef int Position; 3 struct SNode { 4 ElementType *Data; /* 存储元素的数组 */ 5 Position Top; /* 栈顶指针 */ 6 int MaxSize; /* 堆栈最大容量 */ 7 }; 8 typedef struct SNode *Stack; 9 10 Stack CreateStack( int MaxSize ) 11 { 12 Stack S = (Stack)malloc(sizeof(struct SNode)); 13 S->Data = (ElementType *)malloc(MaxSize * sizeof(ElementType)); 14 S->Top = -1; 15 S->MaxSize = MaxSize; 16 return S; 17 } 18 19 bool IsFull( Stack S ) 20 { 21 return (S->Top == S->MaxSize-1); 22 } 23 24 bool Push( Stack S, ElementType X ) 25 { 26 if ( IsFull(S) ) { 27 printf("堆栈满"); 28 return false; 29 } 30 else { 31 S->Data[++(S->Top)] = X; 32 return true; 33 } 34 } 35 36 bool IsEmpty( Stack S ) 37 { 38 return (S->Top == -1); 39 } 40 41 ElementType Pop( Stack S ) 42 { 43 if ( IsEmpty(S) ) { 44 printf("堆栈空"); 45 return ERROR; /* ERROR是ElementType的特殊值,标志错误 */ 46 } 47 else 48 return ( S->Data[(S->Top)--] ); 49 }
二、链表栈
1 #include <stdio.h> 2 #include <malloc.h> 3 #define OK 1 4 #define ERROR 0 5 /* 0.定义结点 */ 6 typedef int SElemType, Status; 7 typedef struct stack* STACKPTR; 8 typedef struct stack STACK; 9 struct stack{ 10 SElemType e; 11 STACKPTR next; 12 }; 13 14 /* 1.push */ 15 Status push(STACKPTR *top,SElemType e) 16 { 17 STACKPTR p; 18 p = (STACKPTR)malloc(sizeof(STACK)); 19 if(p == NULL) 20 return ERROR; 21 22 p->e=e; 23 p->next = *top; 24 25 *top = p; 26 return OK; 27 } 28 29 /* 2.pop */ 30 Status pop(STACKPTR *top,SElemType *e) 31 { 32 if(*top == NULL) 33 return ERROR; 34 35 *e = (*top)->e; 36 37 STACKPTR t = *top; 38 *top = (*top)->next; 39 free(t); 40 return OK; 41 } 42 43 /* 测试代码 */ 44 int main() 45 { 46 STACKPTR top = NULL; 47 SElemType e; 48 for(int i=0; i<10; ++i) 49 push(&top,i); 50 while(pop(&top,&e)) 51 printf("%d ",e); 52 return 0; 53 }
1 //浙大数据结构 链栈 2 typedef struct SNode *PtrToSNode; 3 struct SNode { 4 ElementType Data; 5 PtrToSNode Next; 6 }; 7 typedef PtrToSNode Stack; 8 9 Stack CreateStack( ) 10 { /* 构建一个堆栈的头结点,返回该结点指针 */ 11 Stack S; 12 13 S = (Stack)malloc(sizeof(struct SNode)); 14 S->Next = NULL; 15 return S; 16 } 17 18 bool IsEmpty ( Stack S ) 19 { /* 判断堆栈S是否为空,若是返回true;否则返回false */ 20 return ( S->Next == NULL ); 21 } 22 23 bool Push( Stack S, ElementType X ) 24 { /* 将元素X压入堆栈S */ 25 PtrToSNode TmpCell; 26 27 TmpCell = (PtrToSNode)malloc(sizeof(struct SNode)); 28 TmpCell->Data = X; 29 TmpCell->Next = S->Next; 30 S->Next = TmpCell; 31 return true; 32 } 33 34 ElementType Pop( Stack S ) 35 { /* 删除并返回堆栈S的栈顶元素 */ 36 PtrToSNode FirstCell; 37 ElementType TopElem; 38 39 if( IsEmpty(S) ) { 40 printf("堆栈空"); 41 return ERROR; 42 } 43 else { 44 FirstCell = S->Next; 45 TopElem = FirstCell->Data; 46 S->Next = FirstCell->Next; 47 free(FirstCell); 48 return TopElem; 49 } 50 }
三、栈的应用举例
1、进制转换
十进制数N和其它d进制数的转换的算法基于原理: N = (N div d)×d + N mod d, 其中,div 相除取整,mod 相除取余。
计算过程是从低位到高位顺序产生d进制数的各个数位,而打印输出,一般来说应从高位到低位进行,恰好和计算过程相反。因此,若将计算过程中得到的d进制数 的各位顺序进栈,则按出栈序列打印输出的即为与输入对应 的d进制数。
/* 用上面链表栈代码测试 */ STACKPTR top = NULL; SElemType e; int n = 1348;//10进制数 int d = 8; //8进制 while(n) { push(&top,n%d); n /= d; } while(pop(&top,&e)) printf("%d",e);