摘要:栈是一种新的数据结构,在我们生活中其实也有很多,只是我们没有关注。栈可以形象为一个死胡同,秉承着“先进后出,后进先出”的原则。栈相较于之前的链表较为简单,但其应用十分广泛。
一.代码块
1)栈的创建
#define MAXSIZE 10
typedef struct charStack
{
int top;//记录栈顶的位置,方便我们压栈和出栈
char data[MAXSIZE];//存储数据的本质还是数组
}*charStackPtr;
2)栈的初始化
charStackPtr stackInit()
{
charStackPtr resultStack = (charStackPtr)malloc(sizeof(struct charStack));
resultStack->top = -1;//栈顶在-1,表示该栈为空栈
return resultStack;
}
3)栈的打印
void outputStack(charStackPtr paraStack)
{
int i;
for(i = 0;i <= paraStack->top;i ++)
{
printf("%c ",paraStack->data[i]);
}
printf("\r\n");
}
4)压栈
void push(charStackPtr paraStack,char paraChar)
{
if(paraStack->top >= MAXSIZE-1)
{
printf("Cannot push element:stack full\r\n");
return ;
}
paraStack->top ++;
paraStack->data[paraStack->top] = paraChar;
}
5)出栈
char pop(charStackPtr paraStack)
{
if(paraStack->top < 0)
{
printf("Cannot pop element:stack empty");
return '\0'; /*在不能出栈,我们返回的是‘\0’.相当于空
注意不是‘0’,这就是返回了字符0了*/
}
paraStack->top --;
return paraStack->data[(paraStack->top)+1];
/*我们注意到,压栈和出栈的操作时间复杂度度极低,为o(1),
这也是栈的一个极大优势*/
}
6)压栈出栈测试函数
void pushPopTest()
{
char ch;
int i;
printf("---- pushPopTest begins. ----\r\n");
charStackPtr tempStack = stackInit();
printf("After initialization, the stack is: ");
outputStack(tempStack);
for (ch = 'a'; ch < 'm'; ch ++)
{
printf("Pushing %c.\r\n", ch);
push(tempStack, ch);
outputStack(tempStack);
}
for (i = 0; i < 3; i ++)
{
ch = pop(tempStack);
printf("Pop %c.\r\n", ch);
outputStack(tempStack);
}
printf("---- pushPopTest ends. ----\r\n");
}
7)括号匹配(栈的简单应用)
int bracketMatching(char paraString[],int paraLength)
{
//不知道为啥我的编译器不支持bool,我就用int代替的,效果一样
int i;
char tempChar,tempPopedChar;
charStackPtr tempStack = stackInit();
/*这里是个重要的地方,为了统一操作,我们在第栈的第0个位置手动push
了一个#号,这个#号的作用相当于单链表的头结点,是不能触碰的,如果栈
里面只剩下了#号说明为空栈,这个操作在我们后续写代码也会常用到*/
push(tempStack,'#');
tempStack->top = 0;
/*是这样的,只要我们发现了([{,都将其存入栈中,发现了)]},就将栈顶pop
出来,并且如果栈顶元素不是对应的左括号,代表括号不匹配,就直接return 0了*/
for(i = 0;i < paraLength;i ++)
{
tempChar = paraString[i];
switch (tempChar)
{
case '(':
case '[':
case '{':
push(tempStack,tempChar);
break;
case ')':
tempPopedChar = pop(tempStack);
if(tempPopedChar != '(')
{
return 0;
}
break;
case ']':
tempPopedChar = pop(tempStack);
if(tempPopedChar != '[')
{
return 0;
}
break;
case '}':
tempPopedChar = pop(tempStack);
if(tempPopedChar != '{')
{
return 0;
}
break;
default :
break;
}
}
//如何判断为空栈,直接用到了我们的#号
tempPopedChar = pop(tempStack);
if(tempPopedChar != '#')
{
return 0;
}
return 1;
}
8)括号匹配测试函数
void bracketMatchingTest()
{
char* tempExpression = "[2 + (1 - 3)] * 4";
int tempMatch = bracketMatching(tempExpression, 17);
printf("Is the expression '%s' bracket matching? %d \r\n", tempExpression, tempMatch);
tempExpression = "( ) )";
tempMatch = bracketMatching(tempExpression, 6);
printf("Is the expression '%s' bracket matching? %d \r\n", tempExpression, tempMatch);
tempExpression = "()()(())";
tempMatch = bracketMatching(tempExpression, 8);
printf("Is the expression '%s' bracket matching? %d \r\n", tempExpression, tempMatch);
tempExpression = "({}[])";
tempMatch = bracketMatching(tempExpression, 6);
printf("Is the expression '%s' bracket matching? %d \r\n", tempExpression, tempMatch);
tempExpression = "((((";
tempMatch = bracketMatching(tempExpression, 4);
printf("Is the expression '%s' bracket matching? %d \r\n", tempExpression, tempMatch);
/*这个测试代码也用到了我们设置的#号,第一个字符就直接return 0,
十分方便*/
tempExpression = ")(";
tempMatch = bracketMatching(tempExpression, 2);
printf("Is the expression '%s' bracket matching? %d \r\n", tempExpression, tempMatch);
}
三.全部代码
#include <stdio.h>
#include <malloc.h>
#define MAXSIZE 10
typedef struct charStack
{
int top;//记录栈顶的位置,方便我们压栈和出栈
char data[MAXSIZE];//存储数据的本质还是数组
}*charStackPtr;
charStackPtr stackInit()
{
charStackPtr resultStack = (charStackPtr)malloc(sizeof(struct charStack));
resultStack->top = -1;//栈顶在-1,表示该栈为空栈
return resultStack;
}
void outputStack(charStackPtr paraStack)
{
int i;
for(i = 0;i <= paraStack->top;i ++)
{
printf("%c ",paraStack->data[i]);
}
printf("\r\n");
}
void push(charStackPtr paraStack,char paraChar)
{
if(paraStack->top >= MAXSIZE-1)
{
printf("Cannot push element:stack full\r\n");
return ;
}
paraStack->top ++;
paraStack->data[paraStack->top] = paraChar;
}
char pop(charStackPtr paraStack)
{
if(paraStack->top < 0)
{
printf("Cannot pop element:stack empty");
return '\0'; /*在不能出栈,我们返回的是‘\0’.相当于空
注意不是‘0’,这就是返回了字符0了*/
}
paraStack->top --;
return paraStack->data[(paraStack->top)+1];
/*我们注意到,压栈和出栈的操作时间复杂度度极低,为o(1),
这也是栈的一个极大优势*/
}
void pushPopTest()
{
char ch;
int i;
printf("---- pushPopTest begins. ----\r\n");
charStackPtr tempStack = stackInit();
printf("After initialization, the stack is: ");
outputStack(tempStack);
for (ch = 'a'; ch < 'm'; ch ++)
{
printf("Pushing %c.\r\n", ch);
push(tempStack, ch);
outputStack(tempStack);
}
for (i = 0; i < 3; i ++)
{
ch = pop(tempStack);
printf("Pop %c.\r\n", ch);
outputStack(tempStack);
}
printf("---- pushPopTest ends. ----\r\n");
}
int bracketMatching(char paraString[],int paraLength)
{
//不知道为啥我的编译器不支持bool,我就用int代替的,效果一样
int i;
char tempChar,tempPopedChar;
charStackPtr tempStack = stackInit();
/*这里是个重要的地方,为了统一操作,我们在第栈的第0个位置手动push
了一个#号,这个#号的作用相当于单链表的头结点,是不能触碰的,如果栈
里面只剩下了#号说明为空栈,这个操作在我们后续写代码也会常用到*/
push(tempStack,'#');
tempStack->top = 0;
/*是这样的,只要我们发现了([{,都将其存入栈中,发现了)]},就将栈顶pop
出来,并且如果栈顶元素不是对应的左括号,代表括号不匹配,就直接return 0了*/
for(i = 0;i < paraLength;i ++)
{
tempChar = paraString[i];
switch (tempChar)
{
case '(':
case '[':
case '{':
push(tempStack,tempChar);
break;
case ')':
tempPopedChar = pop(tempStack);
if(tempPopedChar != '(')
{
return 0;
}
break;
case ']':
tempPopedChar = pop(tempStack);
if(tempPopedChar != '[')
{
return 0;
}
break;
case '}':
tempPopedChar = pop(tempStack);
if(tempPopedChar != '{')
{
return 0;
}
break;
default :
break;
}
}
//如何判断为空栈,直接用到了我们的#号
tempPopedChar = pop(tempStack);
if(tempPopedChar != '#')
{
return 0;
}
return 1;
}
void bracketMatchingTest()
{
char* tempExpression = "[2 + (1 - 3)] * 4";
int tempMatch = bracketMatching(tempExpression, 17);
printf("Is the expression '%s' bracket matching? %d \r\n", tempExpression, tempMatch);
tempExpression = "( ) )";
tempMatch = bracketMatching(tempExpression, 6);
printf("Is the expression '%s' bracket matching? %d \r\n", tempExpression, tempMatch);
tempExpression = "()()(())";
tempMatch = bracketMatching(tempExpression, 8);
printf("Is the expression '%s' bracket matching? %d \r\n", tempExpression, tempMatch);
tempExpression = "({}[])";
tempMatch = bracketMatching(tempExpression, 6);
printf("Is the expression '%s' bracket matching? %d \r\n", tempExpression, tempMatch);
tempExpression = "((((";
tempMatch = bracketMatching(tempExpression, 4);
printf("Is the expression '%s' bracket matching? %d \r\n", tempExpression, tempMatch);
/*这个测试代码也用到了我们设置的#号,第一个字符就直接return 0,
十分方便*/
tempExpression = ")(";
tempMatch = bracketMatching(tempExpression, 2);
printf("Is the expression '%s' bracket matching? %d \r\n", tempExpression, tempMatch);
}
int main()
{
pushPopTest();
bracketMatchingTest();
}
四.运行结果
---- pushPopTest begins. ----
After initialization, the stack is:
Pushing a.
a
Pushing b.
a b
Pushing c.
a b c
Pushing d.
a b c d
Pushing e.
a b c d e
Pushing f.
a b c d e f
Pushing g.
a b c d e f g
Pushing h.
a b c d e f g h
Pushing i.
a b c d e f g h i
Pushing j.
a b c d e f g h i j
Pushing k.
Cannot push element:stack full
a b c d e f g h i j
Pushing l.
Cannot push element:stack full
a b c d e f g h i j
Pop j.
a b c d e f g h i
Pop i.
a b c d e f g h
Pop h.
a b c d e f g
---- pushPopTest ends. ----
Is the expression '[2 + (1 - 3)] * 4' bracket matching? 1
Is the expression '( ) )' bracket matching? 0
Is the expression '()()(())' bracket matching? 1
Is the expression '({}[])' bracket matching? 1
Is the expression '((((' bracket matching? 0
Is the expression ')(' bracket matching? 0