目录
栈的函数实现
特点:先进后出FILO(递归是栈的实际应用)。
栈的八个函数:Init,Push,Pop,Clear,Destory,Count,Top,Empty。
栈的最基本的push和pop是链表的头增头删(不是数组的原因是需要开很大空间),他是基于链表的。所以我们先用链表实现一下。
#include<stdio.h>
typedef struct Node
{
int val;
struct Node* next;
}List;
void Push(List** ptop, int num)
{
List* ptem = NULL;
ptem = (List*)malloc(sizeof(List));
ptem->val = num;
ptem->next = *ptop;
*ptop = ptem;
}
void pop(List** ptop)
{
if (*ptop == NULL)return;
List* Delete = *ptop;
*ptop = (*ptop)->next;
printf("%d ", Delete->val);
free(Delete);
Delete = NULL;
}
int main()
{
List* ptop = NULL;
Push(&ptop, 1);
Push(&ptop, 2);
Push(&ptop, 3);
pop(&ptop);
pop(&ptop);
pop(&ptop);
return 0;
}
但是这个代码有问题,因为Destory后,push,pop等都不能用了所以我们还需要一个封装结构体。
结构体:(1)List(2)封装:top,count。
(1)Init:给封装结构体申请空间并赋值。
(2)Push :链表头增。
(3)Pop:链表头删。
(4)Clear:多次调用Pop实现。
(5)Destory:销毁之前先清空,然后在Init申请的空间释放掉,让其他的没法使用。
(6)Count:随着Push++,随着Pop--。
(7)Top:封装结构体取得。
(8)Empty:count是否为0,是则空,不是则非空。
#include<stdio.h>
typedef struct Node
{
int val;
struct Node* next;
}List;
typedef struct node
{
int count;
List* ptop;
}stack;
//通过形参改实参,地址传递。
void Init(stack** pstack)
{
*pstack = (stack*)malloc(sizeof(stack));
(*pstack)->ptop = NULL;
(*pstack)->count = 0;
}
void Push(stack* pstack,int num)
{
//栈不存在
if (pstack == NULL)return;
List* ptem = (List*)malloc(sizeof(List));
ptem->val = num;
ptem->next = pstack->ptop;
pstack->ptop = ptem;
pstack->count++;
}
void Pop(stack* pstack)
{
if (pstack == NULL)return;
if (pstack->count == 0)return;
List* del = pstack->ptop;
pstack->ptop = pstack->ptop->next;
pstack->count--;
free(del);
del = NULL;
}
void Clear(stack* pstack)
{
if (pstack == NULL)return;
while (pstack->count!= 0)
{
Pop(pstack);
}
}
void Count(stack* pstack)
{
if (pstack == NULL)return;
printf("%d\n", pstack->count);
}
void Destory(stack** pstack)
{
Clear(*pstack);
free(*pstack);
*pstack = NULL;
}
void Top(stack* pstack)
{
if (pstack == NULL)return;
if (pstack->count == 0)return;
printf("%d\n", pstack->ptop->val);
}
void Empty(stack* pstack)
{
if (pstack == NULL) return;
if (pstack->count == 0)puts("YES");
else puts("NO");
}
int main()
{
stack* pstack = NULL;
Init(&pstack);
Push(pstack, 1);
Push(pstack, 2);
Push(pstack, 3);
Count(pstack);
Top(pstack);
Pop(pstack);
Top(pstack);
Count(pstack);
Pop(pstack);
Count(pstack);
Destory(pstack);
Count(pstack);
Push(pstack, 222);
return 0;
}
栈在四则运算发挥的作用
首先我们要了解中缀表达式和后缀表达式。
中缀表达式:例如:(3+6)*5-8/4
后缀表达式(后缀表达式中没有括号):3 6 + 5 * 8 4 / -
中缀表达式转后缀表达式:
(1)借助辅助栈。
(2)遇到数字和字母直接打印。
(3)遇到符号,比较当前元素和栈顶元素优先级,如果当前元素优先级高,直接入栈,如果当前元素优先级低,则将栈内元素依次出栈,直到栈顶元素比当前元素优先级低为止,再将元素入栈,如果优先级相同,出栈入栈都行。
(4)遇到“( ”无条件入栈,遇到“ )”栈内元素依次出栈直到“( ”为止。
(小妙招版:将所有可能的表达式用“()”括起来,然后把符号放在对应括号后边,然后把所有括号都去掉。例:(((3+6)*5)-(8/4)) ->(((3 6)+5)*(8 4)/)- -> 3 6 + 5* 8 4 / -)。
后缀转中缀:
(1)借助辅助栈。
(2)遇到数字或字母入栈。
(3)遇到符号,将栈顶元素的下一个和栈顶元素构成表达式。