原文地址:http://blog.chinaunix.net/uid-25885064-id-3803454.html
栈(Stack)是限制在表的一端进行插入和删除运算的线性表。通常称插入、删除的这一端为栈顶(Top),另一端称为栈底(Bottom)。当表中没有元素时称为空栈。栈为后进先出(Last In First Out)的线性表,简称为LIFO表。栈的修改是按后进先出的原则进行。每次删除(退栈)的总是当前栈中"最新"的元素,即最后插入(进栈)的元素,而最先插入的是被放在栈的底部,要到最后才能删除。
一、栈链结点
出栈与入栈是栈的最主要操作,当无法预见栈所需大小时,需要采用链栈的方式。在链栈中,不需要像单链表一样需要头结点。链栈的结构如下图所示:
根据该结构,用C语言定义为:
- typedef char SElemType
-
- typedef struct StackNode
- {
- SElemType data;//根据实际需要定义数据类型
- struct StackNode *next;
- }StackNode,*LinkStackPtr;
-
- typedef struct LinkStack
- {
- LinkStackPtr top;//指向栈链顶部
- int count;//用以判断栈是否为空,可初始化为0
- }LinkStack;
二、进栈
能够进栈的前提是已成功建立栈空间,即成功调用malloc函数。进栈操作的过程如下图所示。进栈函数所需的参数主要是指向栈顶的指针和入栈内容,因此可定义为:
int Push(LinkStack *pS,SElemType e)
Step1:开辟内存,将需要入栈的元素压入栈:
LinkStackPtr s=(LinkStackPtr)malloc(sizeof(StackNode));
s->data = e;
Step2:更改指针
(1)新结点的*next指向原来栈顶:s->next = pS->top;
(2)栈链新的top指针指向新建立的结点:pS->top = s;
Step3:更改栈状态(累计入栈元素个数)
pS->count++;
三、出栈
出栈之前需要判断当前栈的状态,如果栈元素个数为零,则显然是空栈,无法进行出栈操作。出栈操作函数同样需要两个参数,一是指向栈链的指针,二是弹出的栈元素,因此定义为:
int Pop(LinkStackPtr *pS,SElemType *e)//之所以是*e,是为了在函数结束后可以取得该弹出元素
出栈操作过程如下图所示:
出栈过程:
Step1:获取弹出元素:*e = pS->top->data;
Step2:top指针指向栈顶:p = pS->top ;pS->top = p->next;//LinkStackPtr p;
Step3:释放结点:free(p);
Step4:更改栈状态
pS->count--;
四、测试程序
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
-
- typedef char SElemType;
-
- typedef struct StackNode {
- SElemType data;
- struct StackNode *next;
- } StackNode, *LinkStackPtr;
-
- typedef struct LinkStack {
- LinkStackPtr top;
- int count;
- } LinkStack;
-
- void InitialStack(LinkStack * L)
- {
- L->top = NULL;
- L->count = 0;
-
- return;
- }
-
- int StackEmpty(LinkStack * pS)
- {
- return (!pS->count);
- }
-
- int Push(LinkStack * pS, SElemType e)
- {
- LinkStackPtr s = (LinkStackPtr) malloc(sizeof(StackNode));
- if(s == NULL) {
- printf("no enough memory!\n");
- return -1;
- }
- s->data = e;
- s->next = pS->top;
- pS->top = s;
- pS->count++;
-
- return 0;
- }
-
- int Pop(LinkStack * pS, SElemType * e)
- {
- LinkStackPtr p = NULL;
-
- if (StackEmpty(pS)) {
- printf("stack is empty!\n");
- return 0;
- }
-
- *e = pS->top->data;
- p = pS->top;
- pS->top = p->next;
- free(p);
- pS->count--;
-
- return 0;
- }
-
- void PrintStackLink(LinkStack * pS)
- {
- int i;
- LinkStackPtr L = NULL;
-
- L = pS->top;
- if (StackEmpty(pS)) {
- printf("stack is empty!\n");
- return;
- }
-
- for (i = 0; i < (pS->count); i++) {
- printf("%c\n", L->data);
- L = L->next;
- }
-
- return;
- }
-
- int main(int argc, char **argv)
- {
- char getch;
- char outch;
- LinkStack myStack;
-
- InitialStack(&myStack);
-
- printf("请输入压入栈的数据(char型),输入#结束:\n");
- scanf("%c", &getch);
- while (getch != '#') {
- Push(&myStack, getch);
- scanf("%c", &getch);
- }
- printf("栈链内容为:\n");
- PrintStackLink(&myStack);
-
- while (!StackEmpty(&myStack)) {
- Pop(&myStack, &outch);
- printf("弹出内容为:%c\n", outch);
- }
- PrintStackLink(&myStack);
-
- return 0;
- }