一,栈的概念
栈是一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据也在栈顶。
通俗来说就是先进入的数据最后出来,最后进去的数据先出来就比如我们在一个细管子中放入石头,那么最开始放的石头在最底下,最后放的石头就在管口,把石头倒出来,那最先出来的石头就是管口的。
二,栈的结构
栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小。由于刚刚上面的定义介绍我们直到,栈这种结构他只能尾插和尾删,所以这种情况下选择数组是非常方便的。他的结构就和顺序表是非常像的。
typedef int STDataType;
typedef struct Stack
{STDataType* a;int top;int capacity;
}ST;
这里的top就是栈顶位置的下一个
三,栈的实现
//初始化
void STInit(ST* ps);
//销毁
void STDestroy(ST* ps);
//插入
void STPush(ST* ps, STDataType x);
//删除
void STPop(ST* ps);
//找top位置的数据
STDataType STTop(ST* ps);
//一共有多少个数据
int STSize(ST* ps);
//判断是否为空
bool STEmpty(ST* ps);
3.1栈的初始化
//初始化
void STInit(ST* ps)
{assert(ps);ps->a = NULL;ps->capacity = ps->top = 0;
}
3.2栈的销毁
//销毁
void STDestroy(ST* ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->capacity = ps->top = 0;
}
3.3栈的插入
//插入
void STPush(ST* ps, STDataType x)
{assert(ps);//先判断容量是否够if (ps->capacity == ps->top){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * newcapacity);if (tmp == NULL){perror("realloc fail");exit(-1);}ps->capacity = newcapacity;ps->a = tmp;}ps->a[ps->top] = x;++ps->top;
}
这里我们判断扩容的函数直接写到了插入里面是因为,栈只有一个插入,而之前的顺序表的时候插入的方式非常多,所以单独分开写梗方便我们去利用。
3.3栈的删除
//删除void STPop(ST* ps){assert(ps);assert(ps->top > 0);--ps->top;}
3.4栈顶元素的值
//找top位置的数据
STDataType STTop(ST* ps)
{assert(ps);return ps->a[ps->top - 1];
}
我们最开始提到top是栈顶元素的下一个位置,所以我们在找栈顶元素的时候,要减一。
3.5计算栈一共的数据
//一共有多少个数据
int STSize(ST* ps)
{assert(ps);return ps->top;
}
3.6判断是否为空
//判断是否为空
bool STEmpty(ST* ps)
{assert(ps);return ps->top == 0;
}
四,测试
void text1()
{ST st;STInit(&st);STPush(&st, 1);STPush(&st, 2);STPush(&st, 3);STPush(&st, 4);STPush(&st, 5);while (!STEmpty(&st)){printf("%d ", STTop(&st));STPop(&st);}printf("\n");STDestroy(&st);
}
int main()
{text1();return 0;
}
五,题目练习(有效的括号)
括号匹配问题
5.1分析
我们可以让左括号入栈,右括号出栈,进行比较,同样的要注意左右括号数量也要保持一致。
5.2代码
bool isValid(char * s){ST st;STInit(&st);char topval;while(*s){//左括号入栈switch(*s){case '{':case '[':case '(':STPush(&st,*s);break;case '}':case ']':case ')':if(STEmpty(&st)){STDestroy(&st);return false;}topval=STTop(&st);STPop(&st);if(*s=='}'&&topval!='{'||*s==']'&&topval!='['||*s==')'&&topval!='('){return false;}break;}s++;}bool val=STEmpty(&st);STDestroy(&st); return val;
}