栈(Stack)是限定只能在表的一端进行插入和删除操作的线性表。在表中,允许插入和删除的一端称作“栈顶(top)”,不允许插入和删除的另一端称作“栈底(bottom)”。 通常称往栈顶插入元素的操作为“入栈”,称删除栈顶元素的操作为“出栈”。因为后入栈的元素先于先入栈的元素出栈,故被称为是一种“后进先出”的结构,因此又称 LIFO 表(Last In First Out的缩写)。
下面是顺序栈的基本架构的实现:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h> //使用bool必须包含此文件
#define STACK_CAPACITY 5 //栈的容量大小
typedef struct tag_stack //定义结构体类型,包含指针,顶部,长度
{
char *pBuffer;
int top;
int length;
} Stack;
bool InitStack(Stack **pStack); //栈的初始化,形参是指向结构体的指针的指针
void DestroyStack(Stack *pStack); //栈的销毁,形参是指向结构体的指针
bool StackEmpty(Stack *pStack); //判断栈是否为空
bool StackFull(Stack *pStack); //判断栈是否为满
void ClearStack(Stack *pStack); //清空栈
int StackLength(Stack *pStack);//求栈中元素个数
bool Push(Stack *pStack,char *elem);//入栈,形参*elem为入栈元素
bool Pop(Stack *pStack,char *elem); //出栈,
void StackTraverse(Stack *pStack,bool isFromButtom); //遍历栈中所有元素 ,第二个形参为是否从底部遍历
bool InitStack(Stack **pStack)
{
*pStack=(Stack*)malloc(sizeof(Stack)); //开辟一段内存,大小为一个结构体
if(*pStack==NULL) //如果返回的是空指针,开辟失败
{
return false;
}
(*pStack)->pBuffer=(char*)malloc(sizeof(char)*STACK_CAPACITY);//为结构体中的pBuffer开辟一片内存,大小为STACK_CAPACITY
if( (*pStack)->pBuffer ==NULL) //判断内存开辟是否成功
{
return false;
}
ClearStack(*pStack);
return true;
}
void DestroyStack(Stack *pStack)
{
free(pStack->pBuffer); //释放pBuffer所指向的内存
pStack->pBuffer=NULL; //修改野指针
free(pStack);
pStack=NULL;
}
void ClearStack(Stack *pStack)
{
pStack->length=0;
pStack->top=0;
}
bool StackEmpty(Stack *pStack)
{
if(pStack->length==0)
{
return true;
}
return false;
}
bool StackFull(Stack *pStack)
{
if(pStack->length == STACK_CAPACITY)
{
return true;
}
return false;
}
int StackLength(Stack *pStack)
{
return pStack->length;
}
bool Push(Stack *pStack,char *elem)
{
if(StackFull(pStack))//如果满栈
{
return false;
}
pStack->pBuffer[pStack->top++]=*elem;//*elem赋给栈顶元素,指针上移
pStack->length++;//长度+1
return true;
}
bool Pop(Stack *pStack,char *elem)
{
if(StackEmpty(pStack))
{
return false;
}
*elem=pStack->pBuffer[--pStack->top];//赋值,指针下移
pStack->length--;
return true;
}
void StackTraverse(Stack *pStack,bool isFromButtom)
{
if(isFromButtom)
{
int i;
for(i=0;i<pStack->length;i++)
{
printf("%c",pStack->pBuffer[i]);
}
}
else
{
int i;
for(i=pStack->top-1;i>=0;i--)
{
printf("%c",pStack->pBuffer[i]);
}
}
}
int main(int argc, char *argv[])
{
Stack *myStack=NULL;
char ch1='A';
char ch2='C';
char ch3='E';
char ch4='F';
char ch5='G';
char ch=0;
if(InitStack(&myStack))//如果初始化成功
{
if(StackEmpty(myStack))//如果栈为空
{
printf("当前栈为空\n");
}
Push(myStack,&ch1);//栈非空就压入5个元素
Push(myStack,&ch2);
Push(myStack,&ch3);
Push(myStack,&ch4);
Push(myStack,&ch5);
printf("StackLength = %d\n",StackLength(myStack));//打印栈长
StackTraverse(myStack,true);//自底向上遍历
if(StackFull(myStack))
{
printf("\n当前栈为满");
}
Pop(myStack,&ch); //弹出栈顶元素
printf("\n%c\n",ch);
printf("StackLength = %d\n",StackLength(myStack));
StackTraverse(myStack,true);
DestroyStack(myStack);
}
system("pause");
return 0;
}
下面是栈的应用实例,我利用上面的栈架构实现数制转换,输入十进制的数,然后转换为任意进制的数。
数制转换公式:N=(N/d)*d+N%d
举例说明这个原理(短除法):
N N div 8 N mod 8
216 27 0
27 3 3
3 0 3
由此可见,十进制的216对应8进制的330。
下面是代码实现:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h> //使用bool必须包含此文件
#define STACK_CAPACITY 15 //可处理的最大位数
typedef struct tag_stack
{
char *pBuffer;
int top;
int length;
} Stack;
bool InitStack(Stack **pStack);
void DestroyStack(Stack *pStack);
bool StackEmpty(Stack *pStack);
bool StackFull(Stack *pStack);
void ClearStack(Stack *pStack);
int StackLength(Stack *pStack);
bool Push(Stack *pStack,char *elem);
bool Pop(Stack *pStack,char *elem);
void StackTraverse(Stack *pStack,bool isFromButtom); //遍历栈中所有元素
bool InitStack(Stack **pStack)
{
*pStack=(Stack*)malloc(sizeof(Stack));
if(*pStack==NULL)
{
return false;
}
(*pStack)->pBuffer=(char*)malloc(sizeof(char)*STACK_CAPACITY);
if( (*pStack)->pBuffer ==NULL)
{
return false;
}
ClearStack(*pStack);
return true;
}
void DestroyStack(Stack *pStack)
{
free(pStack->pBuffer);
pStack->pBuffer=NULL;
free(pStack);
pStack=NULL;
}
void ClearStack(Stack *pStack)
{
pStack->length=0;
pStack->top=0;
}
bool StackEmpty(Stack *pStack)
{
if(pStack->length==0)
{
return true;
}
return false;
}
bool StackFull(Stack *pStack)
{
if(pStack->length == STACK_CAPACITY)
{
return true;
}
return false;
}
int StackLength(Stack *pStack)
{
return pStack->length;
}
bool Push(Stack *pStack,char *elem)
{
if(StackFull(pStack))
{
return false;
}
pStack->pBuffer[pStack->top++]=*elem;
pStack->length++;
return true;
}
bool Pop(Stack *pStack,char *elem)
{
if(StackEmpty(pStack))
{
return false;
}
*elem=pStack->pBuffer[--pStack->top];
pStack->length--;
return true;
}
void StackTraverse(Stack *pStack,bool isFromButtom)
{
if(isFromButtom)
{
int i;
for(i=0;i<pStack->length;i++)
{
printf("%c",pStack->pBuffer[i]);
}
}
else
{
int i;
for(i=pStack->top-1;i>=0;i--)
{
printf("%c",pStack->pBuffer[i]);
}
}
}
int main(int argc, char *argv[])
{
Stack *myStack=NULL;
int num;
int p;
printf("请输入数字");
scanf("\n%d",&num);
printf("请输入进制");
scanf("\n%d",&p);
char str[]="0123456789ABCDEF";
if(InitStack(&myStack))
{
while(num!=0)
{
Push(myStack,&(str[num%p]));
num=num/p;
}
StackTraverse(myStack,false);
DestroyStack(myStack);
}
system("pause");
return 0;
}