一、栈的定义及功能:
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端
称为栈底。不包含任何元素的栈称为空栈,栈又称为后进先出的线性表。
栈特性:后进先出(LILO)特殊线性表
栈功能:将数据从一种序列改变到另一种序列
二、栈的分类:
1、顺序栈:
顺序栈和顺序表数据成员相同,不同之处:顺序栈的入栈和出栈操作只允许对当前栈顶进行操作
顺序栈所有操作时间复杂度为O(1)
2、链式栈
三、静态顺序栈的部分实现(包括初始化,出、入栈,取顶元素,检测是否为空,统计元素个数括号匹配问题和逆波兰表达式)
1. 代码及过程
.h
# pragma oncee
# include<stdio.h>
# include<stdlib.h>
# include<string.h>
# include<assert.h>
#define MAX_SIZE 10
typedef int DataTYpe;
typedef struct Stack
{
DataTYpe _array[MAX_SIZE];//有效元素的个数
int _top; //栈顶元素的位置
}Stack;
//初始化
void StackInit(Stack *s);
//入栈
void StackPush(Stack *s, DataTYpe data);
//出栈
void StackPop(Stack *s);
//取栈顶元素
DataTYpe StackTop(Stack *s);
//有效元素的个数
int StackSize(Stack *s);
//检测栈是否为空
int Stackempty(Stack *s);
.c
# include"Stack.h"
void StackInit(Stack *s)
{
assert(s);
s->_top = 0;
}
void StackPush(Stack *s, DataTYpe data)
{
assert(s);
if (MAX_SIZE == s->_top)
{
printf("栈已满,放不下了");
return;
}
s->_array[s->_top++]=data;
}
void StackPop(Stack *s)
{
if (Stackempty(s))
return;
s->_top--;
}
int Stackempty(Stack *s)
{
assert(s);
return 0 == s->_top;
}
DataTYpe StackTop(Stack *s)
{
assert(!Stackempty(s));
return s->_array[s->_top - 1];
}
int StackSize(Stack *s)
{
assert(s);
return s->_top;
}
test.c
#define _CRT_SECURE_NO_WARNINGS 1
# include"Stack.h"
void test()
{
Stack s;
StackInit(&s);
StackPush(&s, 2);
StackPush(&s, 3);
StackPush(&s, 4);
StackPush(&s, 5);
printf("size=%d\n", StackSize(&s));
printf("stacktop=%d\n", StackTop(&s));
StackPop(&s);
StackTop(&s);
printf("size=%d\n", StackSize(&s));
printf("stacktop=%d\n", StackTop(&s));
}
int main()
{
test();
system("pause");
return 0;
}
结果为:
括号匹配问题:
1.取i位置的字符
2.判断字符是否为括号
(1)如果不是括号:继续执行步骤1;
(2)如果是括号:如果为左括号则入栈,然后继续执行步骤1;
如果是右括号则用用当前括号与栈顶元素比较:若匹配,则出栈并继续执行步骤1;不匹配则返回。
.h
# pragma oncee
# include<stdio.h>
# include<stdlib.h>
# include<string.h>
# include<assert.h>
#define MAX_SIZE 10
typedef int DataTYpe;
typedef struct Stack
{
DataTYpe _array[MAX_SIZE];//有效元素的个数
int _top; //栈顶元素的位置
}Stack;
//初始化
void StackInit(Stack *s);
//入栈
void StackPush(Stack *s, DataTYpe data);
//出栈
void StackPop(Stack *s);
//取栈顶元素
DataTYpe StackTop(Stack *s);
//有效元素的个数
int StackSize(Stack *s);
//检测栈是否为空
int Stackempty(Stack *s);
//判断括号是否匹配
int IsBracket(char c);
int MatchBrackets(const char *pStr);
.c
int IsBracket(char c)
{
if (('(' == c || ')' == c) ||
('{' == c || '}' == c) ||
('[' == c || ']' == c))
{
return 1;
}
return 0;
}
int MatchBrackets(const char *pStr)
{
int i = 0;
Stack s;
if (NULL == pStr)
return 0;
StackInit(&s);
int len = strlen(pStr);
for (i = 0; i < len; ++i)
{
if (!IsBracket(pStr[i]))
continue;
else
{
if ('(' == pStr[i] || '{' == pStr[i] || '[' == pStr[i])
StackPush(&s, pStr[i]);
else
{
if (Stackempty(&s)){
printf("左括号比右括号少\n");
return 0;
}
char c = StackTop(&s);
if (('(' == c&&')' == pStr[i]) ||
('{' == c&&'}' == pStr[i]) ||
('[' == c&&']' == pStr[i]))
{
StackPop(&s);
}
else
{
printf("左右括号匹配存在问题\n");
return 0;
}
}
}
}
if (!Stackempty(&s))
{
printf("左括号比有括号多\n");
return 0;
}
printf("左右括号匹配\n");
return 1;
}
test.c
void TestMatchBrackets()
{
char a[] = "(())abc{[(])}";
char b[] = "(()))abc{[]}";
char c[] = "(()()abc{[]}";
char d[] = "(())abc{[]()}";
MatchBrackets(a);
MatchBrackets(b);
MatchBrackets(c);
MatchBrackets(d);
}
int main()
{
TestMatchBrackets();
system("pause");
return 0;
}
结果:
逆波兰表达式
1.取数组中的元素
2.判断该元素是否为数字
若是数字,则入栈,并继续执行步骤1;
若不是数字,则取栈顶元素为右操作数,出栈;再去栈顶元素为左操作数,出栈
3.进行当前操作,结果入栈,继续执行步骤1
.h
# pragma oncee
# include<stdio.h>
# include<stdlib.h>
# include<string.h>
# include<assert.h>
#define MAX_SIZE 10
typedef int DataTYpe;
typedef enum{
ADD,SUB,MUL,DIV,DATA
}OPERATE;
typedef struct Cell{
OPERATE _op;
int data;
}Cell;
typedef struct Stack
{
DataTYpe _array[MAX_SIZE];//有效元素的个数
int _top; //栈顶元素的位置
}Stack;
//初始化
void StackInit(Stack *s);
//入栈
void StackPush(Stack *s, DataTYpe data);
//出栈
void StackPop(Stack *s);
//取栈顶元素
DataTYpe StackTop(Stack *s);
//有效元素的个数
int StackSize(Stack *s);
//检测栈是否为空
int Stackempty(Stack *s);
//检测逆波兰数
int CalRPN(Cell RPN[], int size);
.c
int CalRPN(Cell RPN[], int size)
{
int i = 0;
Stack s;
StackInit(&s);
for (; i < size; ++i)
{
if (RPN[i]._op == DATA)
StackPush(&s,RPN[i].data);
else
{
int left = 0;
int right = 0;
right = StackTop(&s);
StackPop(&s);
left = StackTop(&s);
StackPop(&s);
switch (RPN[i]._op)
{
case ADD:
StackPush(&s, left + right);
break;
case SUB:
StackPush(&s, left - right);
break;
case MUL:
StackPush(&s, left*right);
break;
case DIV:
if (0 == right)
{
printf("除数为非法\n");
return 0;
}
StackPush(&s, left / right);
break;
}
}
}
return StackTop(&s);
}
test.c
结果:
void TestCalRPN()
{
Cell RPN[] = { { DATA, 12 }, { DATA, 3 },
{ DATA, 4 }, { ADD, 0 },
{ MUL, 0 }, { DATA, 0 },
{ MUL, 0 }, { DATA, 6 },
{ SUB, 0 }, { DATA, 8 },
{ DATA, 2 }, { DIV, 0 },
{ ADD, 0 } };
printf("%d\n", CalRPN(RPN, sizeof(RPN) / sizeof(RPN[0])));
}
int main()
{
TestCalRPN();
system("pause");
return 0;
}