赞
踩
今天我们主要来了解栈!如果对知识点有模糊,可翻阅以往文章哦!
所属专栏:数据结构【c语言版】_小八哥向前冲~的博客-CSDN博客
c语言专栏:c语言_小八哥向前冲~的博客-CSDN博客
值得注意的是,如果你十分了解顺序表和链表,今天这期会很轻松哦!
哈哈哈哈!当然,这期也能检测你对顺序表和链表的理解!一起看看吧!
目录
上图理解一下:
注意:遵循后进先出的原则!
知道了这个原则,我们来巩固一下:
1.一个栈的初始状态为空。现将元素1、2、3、4、5、A、B、C、D、E依次入栈,然后再依次出栈,则元素出 栈的顺序是( )。
A .12345ABCDE
B.EDCBA54321
C.ABCDE12345
D.54321EDCBA
2.若进栈序列为 1,2,3,4 ,进栈过程中可以出栈,则下列不可能的一个出栈序列是()
A.1,4,3,2
B.2,3,4,1
C.3,1,4,2
D.3,4,2,1
显然:1.B 2.C
相信第一题不难,我们解释一下第二题:看到C选项,1,2,3进栈后,3出栈,而第二次出栈的只能是2或4,不可能是1,所以C错误!
了解了栈的概念,我们实现这个栈是使用顺序表还是链表呢?
综上所述,我们栈使用顺序表较好!(两种都实现看看)
上图看看它们:
为了更好透彻了解顺序表和链表,我们将它们比较看看!
图文更加直观:
这里的缓存利用率不做过多解释,详情见:https://www.cnblogs.com/yungyu16/p/13054874.html
既然是要在顺序表基础上实现栈,那么就要实现顺序表和栈的基本框架。
(单链表若有不懂的知识点,可见:通讯录的实现(顺序表版本)-CSDN博客)
stack.h文件--包含各种需要的函数
栈里面的变量:top表示栈顶下标,capacity表示栈空间。
- #include<stdio.h>
- #include<stdlib.h>
- #include<assert.h>
- #include<stdbool.h>
-
- typedef int STDateType;
- //栈
- typedef struct stack
- {
- STDateType* a;
- int top;
- int capacity;
- }ST;
-
- //栈的初始化和销毁
- void STInit(ST* p);
- void STDestroy(ST* p);
- //入栈,出栈
- void STpush(ST* p,STDateType x);
- void STpop(ST* p);
- //栈顶的数据
- STDateType STtop(ST* p);
- //栈的数据个数
- int STsize(ST* p);
- //判空
- bool STEmpty(ST* p);
接下来我们一一实现!
我们要将栈中各个变量进行初始化。
- void STInit(ST* p)
- {
- assert(p);
- p->a = NULL;
- p->capacity = 0;
- p->top = 0;
- }
我们在实现这个函数时,很多人会用 if语句来判断是否为空,但我们仔细一想,可以好好优化一下代码!
- //判空
- bool STEmpty(ST* p)
- {
- assert(p);
- return p->top == 0;
- }
经过我们刚刚的分析,入栈要在数组尾部!记得每次入栈需要判断空间是否够用哦!
- void STpush(ST* p, STDateType x)
- {
- assert(p);
- if (p->top == p->capacity)
- {
- int newcapacity = p->capacity == 0 ? 4 : p->capacity * 2;
- STDateType* tmp = (STDateType*)realloc(p->a, newcapacity * sizeof(STDateType));
- if (tmp == NULL)
- {
- perror("realloc failed!");
- return;
- }
- p->a = tmp;
- p->capacity = newcapacity;
- }
- p->a[p->top++] = x;
- }
入栈要在尾部,出栈也要在尾部,后进先出的原则要时刻记住!
需要注意的是:当栈为空时,数据出不了栈!所以我们先需要判断是否为空!
- void STpop(ST* p)
- {
- assert(p);
- //出栈的话要判断一下空的情况
- assert(!STEmpty(p));
- p->top--;
- }
我们既然用了开辟内存函数,当我们不使用栈时,要将空间释放掉!
- void STDestroy(ST* p)
- {
- assert(p);
- free(p->a);
- p->capacity = p->top = 0;
- }
在访问栈顶数据时,我们也要先判断栈是否为空,否则当栈为空时,访问栈顶数据便会越界访问!
- //栈顶的数据
- STDateType STtop(ST* p)
- {
- assert(p);
- //出栈的话要判断一下空的情况
- assert(!STEmpty(p));
- return p->a[p->top-1];
- }
- //栈的数据个数
- int STsize(ST* p)
- {
- assert(p);
- return p->top;
- }
既然我们已经实现的栈,我们来应用一下吧!
题目:详情--20. 有效的括号 - 力扣(LeetCode)
思路:
遍历数组,当是左括号时("(","{","】")时就入栈,当不是左括号时就出栈比较,直到遍历完成!
这样听是不是很简单呢?当然里面没有栈,我们需要将栈创建一下!
代码:
- typedef char STDateType;
- //栈
- typedef struct stack
- {
- STDateType* a;
- int top;
- int capacity;
- }ST;
-
- //栈的初始化和销毁
- void STInit(ST* p);
- void STDestroy(ST* p);
- //入栈,出栈
- void STpush(ST* p,STDateType x);
- void STpop(ST* p);
- //栈顶的数据
- STDateType STtop(ST* p);
- //栈的数据个数
- int STsize(ST* p);
- //判空
- bool STEmpty(ST* p);
- //栈的初始化和销毁
- void STInit(ST* p)
- {
- assert(p);
- p->a = NULL;
- p->capacity = 0;
- p->top = 0;
- }
- void STDestroy(ST* p)
- {
- assert(p);
- free(p->a);
- p->capacity = p->top = 0;
- }
- //入栈,出栈
- void STpush(ST* p, STDateType x)
- {
- assert(p);
- if (p->top == p->capacity)
- {
- int newcapacity = p->capacity == 0 ? 4 : p->capacity * 2;
- STDateType* tmp = (STDateType*)realloc(p->a, newcapacity * sizeof(STDateType));
- if (tmp == NULL)
- {
- perror("realloc failed!");
- return;
- }
- p->a = tmp;
- p->capacity = newcapacity;
- }
- p->a[p->top++] = x;
- }
- void STpop(ST* p)
- {
- assert(p);
- //出栈的话要判断一下空的情况
- assert(!STEmpty(p));
- p->top--;
- }
- //栈顶的数据
- STDateType STtop(ST* p)
- {
- assert(p);
- //出栈的话要判断一下空的情况
- assert(!STEmpty(p));
- return p->a[p->top-1];
- }
- //栈的数据个数
- int STsize(ST* p)
- {
- assert(p);
- return p->top;
- }
- //判空
- bool STEmpty(ST* p)
- {
- assert(p);
- return p->top == 0;
- }
- bool isValid(char* s) {
- ST st;
- STInit(&st);
- while(*s)
- {
- //左括号入栈
- if(*s=='('||*s=='['||*s=='{')
- {
- STpush(&st,*s);
- }
- else
- //不是左括号出栈比较
- {
- if(STEmpty(&st))
- {
- STDestroy(&st);
- return false;
- }
- char top=STtop(&st);
- STpop(&st);
- if(top=='('&&*s!=')'
- ||top=='['&&*s!=']'
- ||top=='{'&&*s!='}')
- {
- STDestroy(&st);
- return false;
- }
- }
- s++;
- }
- //当栈中没有左括号比较完时,便匹配不成
- bool ret=STEmpty(&st);
- STDestroy(&st);
- return ret;
- }
可能有人说太麻烦了,但c语言中没有栈,只能自己创建哦!这是用目前c语言最简单的方法!
和顺序表一样,我们首先要创建栈和链表的基本框架!
stack.h文件--包含需要的函数
- #include<stdio.h>
- #include<stdlib.h>
- #include<assert.h>
- #include<stdbool.h>
-
- typedef int STDataType;
- //栈
- typedef struct stack
- {
- struct stcak* next;
- STDataType data;
- }STNode;
-
-
- //栈的销毁
- void STDestroy(STNode* phead);
- //入栈
- void STpush(STNode** pphead,STDataType x);
- //出栈
- void STpop(STNode** pphead);
- //栈顶数据
- STDataType STtop(STNode* phead);
- //判空
- bool STEmpty(STNode* phead);
- //栈数据个数
- int STsize(STNode* phead);
有了顺序表的基础,接下来依葫芦画瓢----最简单不过!
- //判空
- bool STEmpty(STNode* phead)
- {
- return phead == NULL;
- }
我们分析将链表的头部为栈顶,进出都在头!(这种方案最佳!)
- //创建节点
- STNode* STBuyNode(STDataType x)
- {
- STNode* node = (STNode*)malloc(sizeof(STNode));
- if (node == NULL)
- {
- perror("malloc failed!");
- return NULL;
- }
- node->data = x;
- node->next = NULL;
- return node;
- }
-
- //入栈
- void STpush(STNode** pphead, STDataType x)
- {
- STNode* node = STBuyNode(x);
- node->next = *pphead;
- *pphead = node;
- }
将头节点指向下一个节点,原来的头节点释放!
- //出栈
- void STpop(STNode** pphead)
- {
- assert(!STEmpty(*pphead));
- STNode* cur = *pphead;
- *pphead = (*pphead)->next;
- free(cur);
- }
同样的,动态开辟了空间,当我们不用栈时,要将开辟的空间释放掉!
- //栈的销毁
- void STDestroy(STNode* phead)
- {
- STNode* cur = phead;
- while (cur)
- {
- STNode* next = cur->next;
- free(cur);
- cur = next;
- }
- }
也是一样的,在访问栈顶数据时,要判断栈是否为空,防止越界访问!
- //栈顶数据
- STDataType STtop(STNode* phead)
- {
- assert(!STEmpty(phead));
- return phead->data;
- }
遍历链表,将一个一个节点计数起来!
- //栈数据个数
- int STsize(STNode* phead)
- {
- STNode* cur = phead;
- int count = 0;
- while (cur)
- {
- count++;
- cur = cur->next;
- }
- return count;
- }
stack.h文件
- #include<stdio.h>
- #include<stdlib.h>
- #include<assert.h>
- #include<stdbool.h>
-
- typedef int STDateType;
- //栈
- typedef struct stack
- {
- STDateType* a;
- int top;
- int capacity;
- }ST;
-
- //栈的初始化和销毁
- void STInit(ST* p);
- void STDestroy(ST* p);
- //入栈,出栈
- void STpush(ST* p,STDateType x);
- void STpop(ST* p);
- //栈顶的数据
- STDateType STtop(ST* p);
- //栈的数据个数
- int STsize(ST* p);
- //判空
- bool STEmpty(ST* p);
stack.c文件
- #include"stack.h"
- //栈的初始化和销毁
- void STInit(ST* p)
- {
- assert(p);
- p->a = NULL;
- p->capacity = 0;
- p->top = 0;
- }
- void STDestroy(ST* p)
- {
- assert(p);
- free(p->a);
- p->capacity = p->top = 0;
- }
- //入栈,出栈
- void STpush(ST* p, STDateType x)
- {
- assert(p);
- if (p->top == p->capacity)
- {
- int newcapacity = p->capacity == 0 ? 4 : p->capacity * 2;
- STDateType* tmp = (STDateType*)realloc(p->a, newcapacity * sizeof(STDateType));
- if (tmp == NULL)
- {
- perror("realloc failed!");
- return;
- }
- p->a = tmp;
- p->capacity = newcapacity;
- }
- p->a[p->top++] = x;
- }
- void STpop(ST* p)
- {
- assert(p);
- //出栈的话要判断一下空的情况
- assert(!STEmpty(p));
- p->top--;
- }
- //栈顶的数据
- STDateType STtop(ST* p)
- {
- assert(p);
- //出栈的话要判断一下空的情况
- assert(!STEmpty(p));
- return p->a[p->top-1];
- }
- //栈的数据个数
- int STsize(ST* p)
- {
- assert(p);
- return p->top;
- }
- //判空
- bool STEmpty(ST* p)
- {
- assert(p);
- return p->top == 0;
- }
stack.h文件
- #include<stdio.h>
- #include<stdlib.h>
- #include<assert.h>
- #include<stdbool.h>
-
- typedef int STDataType;
- //栈
- typedef struct stack
- {
- struct stcak* next;
- STDataType data;
- }STNode;
-
-
- //栈的销毁
- void STDestroy(STNode* phead);
- //入栈
- void STpush(STNode** pphead,STDataType x);
- //出栈
- void STpop(STNode** pphead);
- //栈顶数据
- STDataType STtop(STNode* phead);
- //判空
- bool STEmpty(STNode* phead);
- //栈数据个数
- int STsize(STNode* phead);
stack.c文件
- #include"stack.h"
-
- STNode* STBuyNode(STDataType x)
- {
- STNode* node = (STNode*)malloc(sizeof(STNode));
- if (node == NULL)
- {
- perror("malloc failed!");
- return NULL;
- }
- node->data = x;
- node->next = NULL;
- return node;
- }
-
- //入栈
- void STpush(STNode** pphead, STDataType x)
- {
- STNode* node = STBuyNode(x);
- node->next = *pphead;
- *pphead = node;
- }
-
- //出栈
- void STpop(STNode** pphead)
- {
- assert(!STEmpty(*pphead));
- STNode* cur = *pphead;
- *pphead = (*pphead)->next;
- free(cur);
- }
-
- //栈顶数据
- STDataType STtop(STNode* phead)
- {
- assert(!STEmpty(phead));
- return phead->data;
- }
-
- //判空
- bool STEmpty(STNode* phead)
- {
- return phead == NULL;
- }
-
- //栈数据个数
- int STsize(STNode* phead)
- {
- STNode* cur = phead;
- int count = 0;
- while (cur)
- {
- count++;
- cur = cur->next;
- }
- return count;
- }
-
- //栈的销毁
- void STDestroy(STNode* phead)
- {
- STNode* cur = phead;
- while (cur)
- {
- STNode* next = cur->next;
- free(cur);
- cur = next;
- }
- }
是不是觉得今天的比较简单?好了,我们下期见!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。