现在在介绍栈具体实现的两种方式。众所周知,所有的数据结构都跟链表和数组有着莫大的关联。而栈也是如此。而采用顺序储存的栈就叫做顺序栈,借助数组来存放其从栈底到栈顶的各个数据。而链式栈就是用借助链表实现,我们通常将链表的头部作为栈顶,将尾部作为栈底。
#define MAXsize 20//栈中的最大元素
typedef int Elemtype;//数据结构中常用的数据元素类型定义方式
//【】下面是顺序栈的定义
typedef struct odstack {
Elemtype data[MAXsize];
int top;//top就是栈顶指针(表示当前栈顶元素的下标)
}ODstack;
#include
#include
#include
#define MAXsize 20//栈中的最大元素
typedef int Elemtype;//数据结构中常用的数据元素类型定义方式
//【】下面是顺序栈的定义
typedef struct odstack {
Elemtype data[MAXsize];
int top;//top就是栈顶指针(表示当前栈顶元素的下标)
}ODstack;
//栈的初始化【】
bool initODstack(ODstack* s1) {
s1->top = -1;
return true;
}//让栈顶指针先为-1
//入栈【】
bool push(ODstack* s1,Elemtype newdata) {//newdata为要压入栈的新元素
if (MAXsize-1==s1->top) return false;
else s1->data[++s1->top]=newdata;
return true;
}
//出栈【】
bool pop(ODstack* s1,Elemtype *outdata) {//outdata为出栈的元素(用指针为了让这个数能在函数外表示出来)
if (-1 == s1->top)return false;
else *outdata = s1->data[s1->top--];
return true;
}
int main(void) {
ODstack s1;
initODstack(&s1);
int i;
for (i = 0;i < 6;i++) {
int newdata;
scanf("%d", &newdata);
push(&s1, newdata);
}
int length = s1.top;
for (i = 0;i <= length;i++) {
Elemtype *outdata=(int*)malloc(sizeof(ODstack));
pop(&s1, outdata);
printf("顶层为:%d\n", *outdata);
}
}
#include
#include
#include
//【链式栈的定义】
typedef struct linkstack {
int data;
struct linkstack* next;
}LINKstack;//定义一个链式栈(受限的先入后出的规则让它与链表有本质区别)
//【链式栈的初始化】与顺序栈类似
LINKstack* initstack(LINKstack* s) {
s = NULL;
return s;
}
//【判断是否为空栈】
bool emptystack(LINKstack* s) {
if (s)return true;
else return false;
}
//【链式栈的入栈操作】
LINKstack* push(LINKstack* s, Elemtype newnum) {
LINKstack* newstack=(LINKstack*)malloc(sizeof(LINKstack));
newstack->data = newnum;
newstack->next = s;
s = newstack;
return s;
}
//【链式栈的出栈操作】
LINKstack* pop(LINKstack* s,Elemtype *newnum) {
if (s==NULL) {
printf("栈已空");
return NULL;
}
else {
*newnum = s->data;
LINKstack* p = s;
s = s->next;
free(p);
return s;
}
}
bool isValid(char * s){
if(strlen(s)%2==1)return false;//如果是奇数很显然直接错误
char l[10000],r[10000];
int i=0,j=0,left=0;//j是右括号这个数组的下标(如果匹配最后j肯定等于left)
while(*s!='\0')//三个判断语句来进行分类
{
if(*s=='('||*s=='{'||*s=='[')
{
l[++i]=*s;
left++;//统计左括号数目
}
else if(*s==')')
{
r[j]='(';
if(r[j]!=l[i])
return false;
j++;
i--;
}
else if(*s=='}')
{
r[j]='{';
if(r[j]!=l[i])
return false;
j++;
i--;
}else if (*s==']')
{
r[j]='[';
if(r[j]!=l[i])
return false;
j++;
i--;
}
s++;
}
if(j!=left)return false;//左右括号数不相等
return true;
}
char reversech(char s){
if(s==')')return '(';
else if(s=='}')return '{';
else if(s==']')return '[';
return 0;
}//因为右括号要和左括号作比较,所以定义一个反转字符的函数
bool isValid(char * s){
int n =strlen(s);
if(n%2!=0)return false;//特殊情况直接排除
int i=0;
char stack[n+1];//定义栈(char类型)
int top=-1;//栈顶指针(初始化指向-1)
for(i=0;i<n;i++){
if(s[i]=='('||s[i]=='{'||s[i]=='['){
stack[++top]=s[i];//左括号则往栈里填充括号
}else{
if(top==-1||stack[top]!=reversech(s[i])) return false;//如果栈已空,却有右括号则错误。
//最后一个左括号不等于连着的右括号也直接错误
top--;//如果前面两个不跳出,则top--(改变栈顶指针,模拟出栈)
}
}
return top==-1;//(结尾栈空)
}
int longestValidParentheses(char * s){
if(!s)return 0;
int length=strlen(s);
int stack[length+1];//在后文中用来记录这一段有效括号的长度(存储有效括号开始的下标)
int max=0;//存放最长的有效括号
int top=-1;//栈顶指针
int curlength=0;//当前有效括号的长度
stack[++top]=-1;//++top是因为-1不能做下标,为什么为-1(例子:()() 下标为:0 1 2 3 因为0的存在头减尾不等于长度
//所以要往后移动一位。
for(int i=0;i<length;i++){
if(s[i]=='('){//左括号
stack[++top]=i;//入栈,存储当前括号的下标
}else{//右括号时(两种可能:1.栈已空(第一个为右括号肯定错误)2.和栈中一个左括号匹配)
--top;//先对栈顶指针进行自减
if(top==-1){//满足则表示原来栈就已空(第一个情况)
stack[++top]=i;//
}else{
curlength=i-stack[top];//这一段有效括号的长度
if(curlength>max)max=curlength;
}
}
}
return max;
}
除了这个方法以外,还有另外一种题目的转换思路。还是用一个数组去存储没个入栈元素的下标,如果这个左括号匹配成功,就把他置1。最后把剩下来的左括号或右括号置为0。那么问题就变成了找最长连续1的问题,就好解决很多。