【数据结构之栈】

数据结构学习笔记---005

  • 数据结构之栈
    • 1、栈的概念和结构
      • 1.1、如何实现栈?
    • 2、数组栈的实现
      • 2.1、栈的Stack.h
      • 2.2、栈的Stack.c
        • 2.2.1、栈的初始化
        • 2.2.2、栈的销毁
        • 2.2.3、栈的出栈和入栈
        • 2.2.4、获取栈顶元素
        • 2.2.5、栈空判定
        • 2.2.6、栈的大小
      • 2.3、栈的main.c
    • 3、栈的巩固练习 -- 有效的括号匹配

数据结构之栈

前言:
前篇学习了 数据结构的顺序表和单链表 那么这篇继续学习后面栈部分的基础内容。

/知识点汇总/

1、栈的概念和结构

:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素的操作。
进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。
即遵循“先进后出(LIFO:Last in First Out)”
压栈操作:栈的插入操作叫做栈/压栈/入栈,入数据在栈顶。
出栈操作:栈的删除操作叫做出栈,出数据也在栈顶。

1.1、如何实现栈?

基本分为两种形式
数组栈:数组栈是以数组形式存储的栈;(最佳实现);
链式栈:而链式栈是以链式结构形式存储的栈;
双向链表实现:栈顶可以是尾,也可以是头;
单链表:栈顶只能是头。

2、数组栈的实现

数组栈的实现的结构类型,那么就需要类似于顺序表一样的存储结构,不过额外注意一个top表示栈顶,如下所示:

typedef int STDatatype;
//定义数组栈结构体成员及变量
typedef struct Stack
{
	STDatatype* a;
	int top;           //标识栈顶位置
	int capacity;
}ST;

2.1、栈的Stack.h

//栈初始化
void STInit(ST* pst);

//栈销毁
void STDestory(ST* pst);

//入栈
void STPush(ST* pst, STDatatype x);

//出栈
void STPop(ST* pst);

//获取栈顶元素
STDatatype STTop(ST* pst);

//栈空判定
bool STEmpty(ST* pst);

//获取栈的大小
int STSize(ST* pst);

2.2、栈的Stack.c

2.2.1、栈的初始化

首先对于栈的初始化中,需要确定对于栈顶的初始化为0还是-1,因为要明确top是栈顶元素还是栈顶元素的下一个元素。而且此时栈内只有一个元素时表示top=0,那么top无法区分top指向栈顶元素,还是指向栈顶元素的下一个位置,所以给-1还是0,写法不同。

//栈初始化
void STInit(ST* pst)
{
	assert(pst);
	pst->a = NULL;
	pst->capacity = 0;
	//pst->top = -1; //表示top指向栈顶元素的位置
	pst->top = 0;  //表示top指向栈顶元素的下一个元素位置。
	//主要区别,先++top还是先赋值的区别,根据自己合理即可
}
2.2.2、栈的销毁

只需要正确的调用使用free函数即可。

//栈销毁
void STDestory(ST* pst)
{
	assert(pst);
	free(pst->a);
	pst->a = NULL;
	pst->capacity = pst->top = 0;
}
2.2.3、栈的出栈和入栈

由于栈是特殊的线性表,只能在一端进行数据的操作,具体就是把数据放入top的位置,然后移动top栈顶指针即可。同理,出栈就是移除元素top指针下移。

//入栈
void STPush(ST* pst, STDatatype x)
{
	assert(pst);
	//检查容量,扩容
	if (pst->top == pst->capacity)
	{
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDatatype* tmp = (STDatatype*)realloc(pst->a, sizeof(STDatatype) * newcapacity);
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		pst->a = tmp;
		pst->capacity = newcapacity;
	}
	//入栈
	pst->a[pst->top] = x;
	pst->top++;
}

//出栈
void STPop(ST* pst)
{
	assert(pst);
	//判空
	assert(pst->top > 0);
	pst->top--;
}
2.2.4、获取栈顶元素

取栈顶元素的操作就是根据初始化时定义的top情况,输出该数组栈顶元素即可。

//获取栈顶元素
STDatatype STTop(ST* pst)
{
	assert(pst);
	//判空
	assert(pst->top > 0);
	return pst->a[pst->top - 1];//注意此时top表示栈顶元素的下一个,所以需要减1
}
2.2.5、栈空判定

对于栈顶可以判定栈为空的情况。


//栈空判定
bool STEmpty(ST* pst)
{
	assert(pst);
	//直接以判断返回即可
	return pst->top == 0;
}
2.2.6、栈的大小

想要得到栈的大小, 直接返回top的数值即可。


//获取栈的大小
int STSize(ST* pst)
{
	assert(pst);
	return pst->top;
}

2.3、栈的main.c

#include "Stack.h"

//测试1:
void TestST1()
{
	ST s;
	STInit(&s);//初始化

	STPush(&s, 1);//入栈
	STPush(&s, 2);
	STPush(&s, 3);
	STPush(&s, 4);
	STPush(&s, 5);

	while (!STEmpty(&s))//判空循环
	{
		printf("%d ", STTop(&s));//取栈顶元素
		STPop(&s);//出栈
	}
	printf("\n");
}

//测试2:不同出栈顺序
void TestST2()
{
	ST s;
	STInit(&s);//初始化

	STPush(&s, 1);//入栈
	STPush(&s, 2);
	STPush(&s, 3);
	printf("%d ", STTop(&s));//取栈顶元素
	STPop(&s);//出栈
	STPush(&s, 4);
	STPush(&s, 5);

	while (!STEmpty(&s))//判空循环
	{
		printf("%d ", STTop(&s));//取栈顶元素
		STPop(&s);//出栈
	}
	printf("\n");
}

int main()
{
	//TestST1();
	TestST2();
	return 0;
}

小结
栈的性质:先进后出,但是入栈顺序相同的情况下,出栈顺序不一定相同。所以出入栈顺序是相对的,一对多关系。

3、栈的巩固练习 – 有效的括号匹配

有效的括号 – ‘(’ ,‘)’,‘[’,‘]’,‘{’.'}'的匹配
思路:数量匹配,顺序匹配
左括号入栈,有右括号则取栈顶左括号。

#include "Stack.h"

bool isValid(char* s)
{
	ST st;
	STInit(&st);//初始化
	while (*s)
	{
		if (*s == '[' || *s == '(' || *s == '{')//如果是左括号就入栈
		{
			STPush(&st, *s);
		}
		else//否则遇见右括号就出栈
		{
			//数量匹配问题,右括号比左括号多的情况
			if (STEmpty(&st))
			{
				STDestory(&st);//添加这一步,是因为这些特殊情况时,不会走到最后一步就返回了,导致没有释放内存,而导致内存泄漏。
				return false;
			}
			//栈出左括号
			char top = STTop(&st);
			STPop(&st);
			//顺序不匹配
			if ((*s == ']' && top != '[')||
				(*s == '}' && top != '{')||
				(* s == ')' && top != '('))
			{
				STDestory(&st);
				return false;
			}
		}
		++s;
	}
	//栈为空,返回真,说明数量匹配,没有剩余括号
	bool ret = STEmpty(&st);
	STDestory(&st);
	return ret;
}
int main()
{
	char* ch = "{[({})]}";
	if (isValid(ch))
	{
		printf("True\n");
	}
	else
	{
		printf("False\n");
	}
	return 0;
}

你可能感兴趣的:(数据结构,数据结构,笔记,栈,顺序表,单链表,C语言,学习)