栈是一种先进后出的数据结构,这个我相信大家很好理解。那下面我就通过两个栈的实际应用来帮助大家更好的理解栈的工作状态。
参考清华大学出版社《数据结构》中的说明:
十进制数N和其他d进制数的转换是计算机实现计算的基本问题,其解决方法很多,其中一个简单算法基于下列原理:
N = ( N div d ) * d + N mod d (其中,div为整除运算,mod为求余运算)
例如: ( 1348 ) 10 \ (1348)_{10} (1348)10 = ( 2504 ) 8 \ (2504)_{8} (2504)8
N | N div 8 | N mod 8 |
---|---|---|
1348 | 168 | 4 |
168 | 21 | 0 |
21 | 2 | 5 |
2 | 0 | 2 |
下面看c代码,这里是顺序栈
#include
#include
typedef struct stack
{
int *base;
int *top;
}Stack,*pStack;
Stack s={0};//结构体的声明
//栈的初始化
void InitStack()
{
s.base = (int *)malloc(100 * sizeof(int));
if(!s.base)
{
printf("内存申请失败!!");
exit(0);
}
s.top = s.base;
printf("栈初始化成功!!\n");
}
//push函数,接受两个参数,要往哪个栈中压入哪个值
void push(pStack s,int value)
{
//判断栈是否溢出
if(s->base - s->top >= 100)
{
printf("栈已满,数据入栈失败!");
exit(0);
}
*(s->top) = value;
s->top--;
}
//pop函数,返回栈顶的数据
int pop(pStack s)
{
int tmp = 0;
//判断是否是空栈
if(s->top == s->base)
{
printf("当前栈为空,不能出数据");
exit(0);
}
s->top++;
tmp = *(s->top);
return tmp;
}
//判断栈是否为空
int StackEmpty(pStack s)
{
if(s->base == s->top )
return 1;
return 0;
}
//数制转换函数
void convert(int num,int scale)
{
while(num)
{
push(&s,num % scale);
num /= scale;
}
}
void main()
{
int num;//要转化的十进制数
int scale;//进制
InitStack();
printf("请输入要转化的十进制数:\n");
scanf("%d",&num);
printf("您想转化为几进制呢?\n");
scanf("%d",&scale);
convert(num,scale);
while(!StackEmpty(&s))
{
printf("%d",pop(&s));
}
printf("\n");
}
接下来是链栈
#include
#include
typedef struct stacknode
{
int data; //节点数据
struct stacknode *next; //节点指针
}StackNode,*pStackNode;
//栈底,栈顶方向标
typedef struct stack
{
pStackNode base; //栈底
pStackNode top; //栈顶
int stacksize; //栈中元素的个数
}Stack,*pStack;
int num = 1314;
int scale = 2;
//初始化一个stack的实例,填充0
Stack s = {0};
//指针指向stack实例
pStack pS = &s;
//创建头指针
pStackNode StackNodeInit()
{
pStackNode pHeadNode;
//头结点
pStackNode HeadNode = (pStackNode)malloc(sizeof(StackNode));
HeadNode->data = 0;
HeadNode->next = NULL;
pHeadNode = HeadNode;//头指针指向第一个节点
return pHeadNode;//返回头指针
}
//每次Push,调用一次
pStackNode CreatList(pStack s)
{
pStackNode pNode = (pStackNode)malloc(sizeof(StackNode));
pNode->next = s->top;
pNode->data = 0;
s->top = pNode;//向右移动指针
return s->top;
}
void StackInit(pStackNode p)//接受一个参数,类型为pStackNode
{
s.base = p; //栈底指向节点1
s.top = s.base; //栈顶也指向节点1
s.stacksize = 0; //栈中元素个数为0
}
void push(pStack s,int value)
{
s->top->data = value;
s->top = CreatList(s);
}
//出栈,返回栈顶的数据
int pop(pStack s)
{
int value;
pStackNode p = s->top;
if(s->base == s->top)
{
printf("栈为空,无数据输出!\n");
exit(0);
}
s->top = s->top->next;
value = s->top->data;
free(p);
return value;
}
int StackEmpty(pStack s)
{
if(s->base == s->top)
return 1;
return 0;
}
void convert(pStack s,int num,int scale)
{
while(num)
{
push(s,num % scale);
num /= scale;
}
}
void output(pStack s)
{
while(!StackEmpty(s))
{
printf("%d",pop(s));
}
printf("\n");
}
void Init()
{
printf("***************************************************************************\n");
printf("* *\n");
printf("* Welcome to use number convert tool *\n");
printf("* This tools was programed by lingyin *\n");
printf("* Version 1.0 *\n");
printf("* *\n");
printf("* *\n");
printf("***************************************************************************\n");
printf("\n");
printf("\n");
printf("\n");
printf("Please input the NUM that you want to convert:");
scanf("%d",&num);
printf("Please input the SCALE that you want to convret:");
scanf("%d",&scale);
}
void main()
{
//p为头指针
pStackNode p = StackNodeInit();
//栈的初始化,总指挥的初始化
StackInit(p);
//输出提示信息
Init();
//进行转换
convert(pS,num,scale);
//最后的输出
output(pS);
}
还是参考清华大学出版社《数据结构》一书中的讲解:
假设表达式中允许包含两种括号,圆括号和方括号,其嵌套的顺序随意,即( [ ] ( ) )或者[ ( [ ] [ ] ) ]等为正确的格式,[ ( ] )或( [ ( ) ) 或 ( ( ) ])均为不正确的格式。检验括号是否匹配的正确方法可以用“期待的急迫程度”这个概念来描述。
例如考虑以下括号序列:
[ ( [ ] [ ] ) ]
12345678当计算机接受了第一个括号后,它期待着与其匹配的第八个括号的出现,然而等来的确实第二个括号,此时第一个括号“[”只能暂时靠边,而迫切等待与第二个括号相匹配的、第七个括号“)”的出现。以此类推。
如果从左括号的角度看这个问题,太复杂。我们可以看右括号。
仔细考虑一下,如果我们遇到一个左括号就入栈,然后遇到了一个右括号,那么栈顶的数据一定是与这个右括号相匹配的。如果不匹配,那就说明这个字符串有问题。
思路出来了。
遇到左括号就入栈,遇到右括号就与栈顶的数据匹配
看c代码,顺序栈的实现
#include
#include
#include
#define MAX 100
typedef struct Stack
{
char * base;
char * top;
int stacksize;
}Stack,*pStack;
//定义一个struct Satck变量
Stack s={0};
//获得s的指针
pStack pS = &s;
void StackInit(pStack ps)
{
char *addr;
addr = (char *)malloc(MAX * sizeof(char));
if(!addr)
{
printf("内存申请失败!");
exit(0);
}
ps->base = addr;
ps->top = ps->base;
}
void push(pStack ps,char ch)
{
*(ps->top) = ch;
(ps->top)--;
}
void pop(pStack ps)
{
(ps->top)++;
}
char gettop(pStack ps)
{
char * tmp = ps->top;
tmp ++;
return *tmp;
}
char reverse(char c)
{
if(c == '(')
return ')';
if(c == '{')
return '}';
if(c == '[')
return ']';
else
return 0;
}
void check(char *str,int length,pStack ps)
{
int i;
for(i = 0;i < length;i++)
{
if( str[i] == '(' || str[i] == '{' || str[i] == '[')
push(ps,str[i]);
if(str[i] == ')' || str[i] == '}' || str[i] == ']')
{
if(reverse(gettop(ps)) == str[i])
pop(ps);
else
{
printf("括号不合法!\n");
exit(0);
}
}
}
printf("您输入的字符串没有问题!\n");
}
void main()
{
int length;
char string[MAX]={0};
//栈的初始化
StackInit(pS);
printf("Please input the string you want to check:");
scanf("%s",string);
length = strlen(string);
check(string,length,pS);
printf("\n");
}