数据结构_第六关:栈和队列(栈)
Posted 小羊在摸鱼
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构_第六关:栈和队列(栈)相关的知识,希望对你有一定的参考价值。
本关目标:
1.栈
2.队列
3.栈和队列的面试题
目录
1.栈
1.1栈的概念和结构
- 栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
- 压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
- 出栈:栈的删除操作叫做出栈。出数据也在栈顶。
1.2关于栈的概念的两个选择题
1.一个栈的初始状态为空。现将元素1、2、3、4、5、A、B、C、D、E依次入栈,然后再依次出栈,则元素出栈的顺序是(B)。
A 12345ABCDE
B EDCBA54321
C ABCDE12345
D 54321EDCBA
2.若进栈序列为 1,2,3,4 ,进栈过程中可以出栈,则下列不可能的一个出栈序列是(C)
A 1,4,3,2
B 2,3,4,1
C 3,1,4,2
D 3,4,2,1栈的出栈顺序不一定非得是数据全部进入完毕后再出,也可以是边进边出。
1.3栈的实现
栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些
因为数组在尾上插入数据的代价比较小。
如果用链表作为栈的话,一般用头做栈顶,尾做栈底,因为链表的头插和头删更有优势
这里我们主要实现数组栈,数组栈分为静态栈和动态栈(和顺序表一样)
静态栈的结构:
typedef int STDataType;
#define N 10
typedef struct Stack
STDataType _a[N];
int _top; // 栈顶
Stack;
动态栈结构:
typedef int STDataType;
typedef struct Stack
STDataType* _a;
int _top; // 栈顶,初始为0,表示栈顶下一个位置的下标
int _capacity; // 容量
ST;
下面以动态栈为例,进行实现
1)声明
typedef int STDatatype;
typedef struct Stack
STDatatype* a;
int capacity;
int top; // 初始为0,表示栈顶位置下一个位置下标
ST;
//初始化
void StackInit(ST* ps);
//销毁
void StackDestroy(ST* ps);
//入栈
void StackPush(ST* ps, STDatatype x);
//出栈
void StackPop(ST* ps);
//获取栈顶元素
STDatatype StackTop(ST* ps);
//栈中的有效个数
int StackSize(ST* ps);
//判断栈是否为空
bool StackEmpty(ST* ps);
//打印
void StackPrant(ST* ps);
2)实现
1.初始化
void StackInit(ST* ps)
assert(ps);
//可以全部初始化NULL和0
//ps->a = NULL;
//ps->top = 0;
//ps->capacity = 0;
//也可以先给其开辟4个空间大小的地址
ps->a = (STDatatype*)malloc(sizeof(STDatatype) * 4);
if (ps->a == NULL)
perror("malloc fail");
exit(-1);
ps->top = 0;
ps->capacity = 4;
如果不在初始化这里开辟大小的话,需要在入栈的realloc前加上:
int NewCapacity = p->capacity == 0 ? 4 : p->capacity * 2;
realloc变为:
STDatatype* tmp = (STDatatype*)realloc(ps->a, NewCapacity * sizeof(STDatatype));
realloc在pa->a为NULL时会为其开辟新的空间
2.销毁栈
void StackDestroy(ST* ps)
assert(ps);
free(ps->a);
ps->a = NULL;
ps->top = ps->capacity = 0;
3.入栈
void StackPush(ST* ps, STDatatype x)
assert(ps);
// 扩容
//这里注意top是从0开始的,top指向的是顶的下一个,当存放了4个数据后,top=4(0,1,2,3)
if (ps->top == ps->capacity)
STDatatype* tmp = (STDatatype*)realloc(ps->a, ps->capacity * 2 * sizeof(STDatatype));
if (tmp == NULL)
perror("realloc fail");
exit(-1);
ps->a = tmp;
ps->capacity *= 2;
ps->a[ps->top] = x;
ps->top++;
4.出栈
void StackPop(ST* ps)
//判断栈是不是为NULL
assert(ps);
//判断栈里面还有没有元素
assert(!StackEmpty(ps));
ps->top--;
5.返回栈顶元素
STDatatype StackTop(ST* ps)
assert(ps);
assert(!StackEmpty(ps));
//栈顶元素是top-1
return ps->a[ps->top - 1];
6.返回栈的元素数量
int StackSize(ST* ps)
assert(ps);
return ps->top;
因为数据存储是从0开始的,top是栈顶数据+1,刚好就是我们所说的元素数量
7.判断栈是否为空
bool StackEmpty(ST* ps)
assert(ps);
/*if (ps->top == 0)
return true;
else
return false;
*/
return ps->top == 0;
8.打印栈
void StackPrant(ST* ps)
int i = 0;
while (i != ps->top)
printf("%d ", ps->a[i]);
i++;
printf("\\n");
2.栈实现的源代码(vs2022下编译)
#define _CRT_SECURE_NO_WARNINGS
#include <stdbool.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
//声明
typedef int STDatatype;
typedef struct Stack
STDatatype* a;
int capacity;
int top; // 初始为0,表示栈顶位置下一个位置下标
ST;
//初始化
void StackInit(ST* ps);
//销毁
void StackDestroy(ST* ps);
//入栈
void StackPush(ST* ps, STDatatype x);
//出栈
void StackPop(ST* ps);
//获取栈顶元素
STDatatype StackTop(ST* ps);
//栈中的有效个数
int StackSize(ST* ps);
//判断栈是否为空
bool StackEmpty(ST* ps);
//打印
void StackPrant(ST* ps);
//实现
void StackInit(ST* ps)
assert(ps);
//可以全部初始化NULL和0
//ps->a = NULL;
//ps->top = 0;
//ps->capacity = 0;
//也可以先给其开辟4个空间大小的地址
ps->a = (STDatatype*)malloc(sizeof(STDatatype) * 4);
if (ps->a == NULL)
perror("malloc fail");
exit(-1);
ps->top = 0;
ps->capacity = 4;
void StackDestroy(ST* ps)
assert(ps);
free(ps->a);
ps->a = NULL;
ps->top = ps->capacity = 0;
void StackPush(ST* ps, STDatatype x)
assert(ps);
// 扩容
//这里注意top是从0开始的,top指向的是顶的下一个,当存放了4个数据后,top=4(0,1,2,3)
if (ps->top == ps->capacity)
STDatatype* tmp = (STDatatype*)realloc(ps->a, ps->capacity * 2 * sizeof(STDatatype));
/*if (tmp == NULL)
perror("realloc fail");
exit(-1);
*/
ps->a = tmp;
ps->capacity *= 2;
ps->a[ps->top] = x;
ps->top++;
void StackPop(ST* ps)
//判断栈是不是为NULL
assert(ps);
//判断栈里面还有没有元素
assert(!StackEmpty(ps));
ps->top--;
STDatatype StackTop(ST* ps)
assert(ps);
assert(!StackEmpty(ps));
//栈顶元素是top-1
return ps->a[ps->top - 1];
int StackSize(ST* ps)
assert(ps);
return ps->top;
bool StackEmpty(ST* ps)
assert(ps);
/*if (ps->top == 0)
return true;
else
return false;
*/
return ps->top == 0;
void StackPrant(ST* ps)
int i = 0;
while (i != ps->top)
printf("%d ", ps->a[i]);
i++;
printf("\\n");
//测试
void text1()
ST ps;
StackInit(&ps);
StackPush(&ps, 1);
StackPush(&ps, 2);
StackPush(&ps, 3);
StackPush(&ps, 4);
StackPush(&ps, 5);
StackPush(&ps, 6);
StackPush(&ps, 7);
StackPush(&ps, 8);
StackPrant(&ps);
int a = StackTop(&ps);
printf("size:%d,栈顶元素为:%d\\n", StackSize(&ps),a); // 不关心底层实现,直接用
printf("size:%d\\n", ps.top); // 关心底层实现
StackPop(&ps);
StackPop(&ps);
StackPop(&ps);
StackPrant(&ps);
a = StackTop(&ps);
printf("size:%d,栈顶元素为:%d\\n", StackSize(&ps), a);
int main()
text1();
return 0;
3.关于栈的OJ题练习:
思路:
- 利用栈进行判断,首先我们创建一个新的栈
- 在遇到左括号的时候,放入栈里面
- 在遇到右括号的时候,出栈,并拿出栈的元素与其进行判断
- 如果有不相同的情况直接return false
- 注意特殊情况的处理:
1:如果,最后栈里面还剩左括号的元素,栈不为空,不符合要求,返回false
2:如果数组中只有右括号,在进行比较的时候,由于我们的栈里面没有元素,肯定会报错
所以需要在之前就进行一次判断,判断我们的栈是否为空,为空返回false就行
代码:
主要实现的函数:
bool isValid(char * s)
//创建一个新的栈
ST st;
StackInit(&st);
//如果*s为空退出循环
while(*s)
if(*s=='[' || *s=='(' || *s=='')
StackPush(&st,*s);
++s;
else
//如果数组中只有右括号,直接对栈进行判空操作
if(StackEmpty(&st))
StackDestroy(&st);
return false;
char top=StackTop(&st);
StackPop(&st);
//不匹配
if( (*s == ']' && top != '[') ||
(*s == ')' && top != '(') ||
(*s == '' && top != '') )
StackDestroy(&st);
return false;
else//继续
++s;
//如果,栈里面还剩左括号的元素,则说明不符合要求,所以要对栈进行判空操作
bool ret =StackEmpty(&st);
StackDestroy(&st);
return ret;
全部代码:
#include <stdbool.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
typedef char STDatatype;
typedef struct Stack
STDatatype* a;
int capacity;
int top; // 初始为0,表示栈顶位置下一个位置下标
ST;
//初始化
void StackInit(ST* ps);
//销毁
void StackDestroy(ST* ps);
//入栈
void StackPush(ST* ps, STDatatype x);
//出栈
void StackPop(ST* ps);
//获取栈顶元素
STDatatype StackTop(ST* ps);
//判断栈是否为空
bool StackEmpty(ST* ps);
void StackInit(ST* ps)
assert(ps);
ps->a = (STDatatype*)malloc(sizeof(STDatatype) * 4);
if (ps->a == NULL)
perror("malloc fail");
exit(-1);
ps->top = 0;
ps->capacity = 4;
void StackDestroy(ST* ps)
assert(ps);
free(ps->a);
ps->a = NULL;
ps->top = ps->capacity = 0;
void StackPush(ST* ps, STDatatype x)
assert(ps);
if (ps->top == ps->capacity)
STDatatype* tmp = (STDatatype*)realloc(ps->a, ps->capacity * 2 * sizeof(STDatatype));
ps->a = tmp;
ps->capacity *= 2;
ps->a[ps->top] = x;
ps->top++;
void StackPop(ST* ps)
//判断栈是不是为NULL
assert(ps);
//判断栈里面还有没有元素
assert(!StackEmpty(ps));
ps->top--;
STDatatype StackTop(ST* ps)
assert(ps);
assert(!StackEmpty(ps));
//栈顶元素是top-1
return ps->a[ps->top - 1];
bool StackEmpty(ST* ps)
assert(ps);
return ps->top == 0;
bool isValid(char * s)
//创建一个新的栈
ST st;
StackInit(&st);
//如果*s为空退出循环
while(*s)
if(*s=='[' || *s=='(' || *s=='')
StackPush(&st,*s);
++s;
else
//如果数组中只有右括号,直接对栈进行判空操作
if(StackEmpty(&st))
StackDestroy(&st);
return false;
char top=StackTop(&st);
StackPop(&st);
//不匹配
if( (*s == ']' && top != '[') ||
(*s == ')' && top != '(') ||
(*s == '' && top != '') )
StackDestroy(&st);
return false;
else//继续
++s;
//如果,栈里面还剩左括号的元素,则说明不符合要求,所以要对栈进行判空操作
bool ret =StackEmpty(&st);
StackDestroy(&st);
return ret;
数据结构- 栈和队列的实现
栈
采用数组实现
#include<iostream>
typedef int DataType;
using namespace std;
typedef struct Stack
{
DataType* _array;
int _top;// 表示有效元素个数 表示栈顶位置
int _capcity;//栈容量
}Stack;
void StackInit(Stack* s)
{
s->_array = (DataType*)malloc(sizeof(DataType));
s->_top = 0;
s->_capcity = 1;
}
void StackDestory(Stack* s)
{
if (s->_array)
{
free(s->_array);
s->_array = NULL;
s->_top = 0;
s->_capcity = 0;
}
}
void StackPush(Stack* p, DataType data)
{
//如果栈顶大于等于容量则扩容
if (p->_top >= p->_capcity)
{
p->_array = (DataType*)realloc(p->_array, sizeof(DataType)*(2 * p->_capcity));
p->_capcity *= 2;
}
p->_array[p->_top++] = data;
}
void StackPop(Stack* s)
{
if (s->_top < 0)return;
s->_top--;
}
DataType StackTop(Stack* s)
{
return s->_array[s->_top - 1];
}
int StackEmpty(Stack* s)
{
return s->_top == 0 ? 1 : 0;
}
int StackSize(Stack* s)
{
return s->_top;
}
int main()
{
}
队列
队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头
采用链表实现
#include<iostream>
typedef int DataType;
using namespace std;
typedef struct Node
{
DataType _data;
struct Node* next;
}Node,*pNode;
typedef struct Queue
{
pNode pHead;//队头
pNode pTail;//队尾
};
pNode CreateNode(DataType data)
{
pNode pNewNode = (pNode)malloc(sizeof(pNode));
pNewNode->_data = data;
pNewNode->next = nullptr;
return pNewNode;
}
void QueueInit(Queue* q)
{
q->pHead = nullptr;
q->pTail = nullptr;
}
void QueuePush(Queue* q, DataType data)
{
if (q->pHead == NULL)
{
q->pHead = q->pTail = CreateNode(data);
}
else
{
q->pTail->next = CreateNode(data);
q->pTail = q->pTail->next;
}
}
void QueuePop(Queue* q)
{
pNode t = q->pHead;
if (t != nullptr)
{
q->pHead = t->next;
free(t);
}
}
DataType QueueFront(Queue* q)
{
return q->pHead->_data;
}
DataType QueueBack(Queue* q)
{
return q->pTail->_data;
}
int QueueSize(Queue* q)
{
int count = 0;
pNode t = q->pHead;
while (t != nullptr)
{
count++;
t = t->next;
}
return count;
}
int QueueEmpty(Queue* q)
{
return q->pHead == nullptr;
}
以上是关于数据结构_第六关:栈和队列(栈)的主要内容,如果未能解决你的问题,请参考以下文章